From b9c1b51e45b845debb76d8658edabca70ca56079 Mon Sep 17 00:00:00 2001 From: Kate Stone Date: Tue, 6 Sep 2016 20:57:50 +0000 Subject: *** This commit represents a complete reformatting of the LLDB source code *** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751 --- lldb/source/Interpreter/Args.cpp | 3053 +++++----- lldb/source/Interpreter/CommandAlias.cpp | 463 +- lldb/source/Interpreter/CommandHistory.cpp | 175 +- lldb/source/Interpreter/CommandInterpreter.cpp | 6026 ++++++++++---------- lldb/source/Interpreter/CommandObject.cpp | 1845 +++--- .../Interpreter/CommandObjectRegexCommand.cpp | 190 +- lldb/source/Interpreter/CommandObjectScript.cpp | 96 +- lldb/source/Interpreter/CommandObjectScript.h | 12 +- .../source/Interpreter/CommandOptionValidators.cpp | 32 +- lldb/source/Interpreter/CommandReturnObject.cpp | 304 +- .../source/Interpreter/OptionGroupArchitecture.cpp | 85 +- lldb/source/Interpreter/OptionGroupBoolean.cpp | 78 +- lldb/source/Interpreter/OptionGroupFile.cpp | 116 +- lldb/source/Interpreter/OptionGroupFormat.cpp | 456 +- lldb/source/Interpreter/OptionGroupOutputFile.cpp | 86 +- lldb/source/Interpreter/OptionGroupPlatform.cpp | 270 +- lldb/source/Interpreter/OptionGroupString.cpp | 60 +- lldb/source/Interpreter/OptionGroupUInt64.cpp | 60 +- lldb/source/Interpreter/OptionGroupUUID.cpp | 76 +- .../Interpreter/OptionGroupValueObjectDisplay.cpp | 364 +- lldb/source/Interpreter/OptionGroupVariable.cpp | 212 +- lldb/source/Interpreter/OptionGroupWatchpoint.cpp | 162 +- lldb/source/Interpreter/OptionValue.cpp | 1220 ++-- lldb/source/Interpreter/OptionValueArch.cpp | 127 +- lldb/source/Interpreter/OptionValueArgs.cpp | 29 +- lldb/source/Interpreter/OptionValueArray.cpp | 576 +- lldb/source/Interpreter/OptionValueBoolean.cpp | 182 +- lldb/source/Interpreter/OptionValueChar.cpp | 86 +- lldb/source/Interpreter/OptionValueDictionary.cpp | 696 ++- lldb/source/Interpreter/OptionValueEnumeration.cpp | 219 +- lldb/source/Interpreter/OptionValueFileSpec.cpp | 228 +- .../source/Interpreter/OptionValueFileSpecLIst.cpp | 290 +- lldb/source/Interpreter/OptionValueFormat.cpp | 87 +- .../source/Interpreter/OptionValueFormatEntity.cpp | 183 +- lldb/source/Interpreter/OptionValueLanguage.cpp | 111 +- .../source/Interpreter/OptionValuePathMappings.cpp | 379 +- lldb/source/Interpreter/OptionValueProperties.cpp | 1269 ++--- lldb/source/Interpreter/OptionValueRegex.cpp | 102 +- lldb/source/Interpreter/OptionValueSInt64.cpp | 116 +- lldb/source/Interpreter/OptionValueString.cpp | 268 +- lldb/source/Interpreter/OptionValueUInt64.cpp | 114 +- lldb/source/Interpreter/OptionValueUUID.cpp | 162 +- lldb/source/Interpreter/Options.cpp | 1786 +++--- lldb/source/Interpreter/Property.cpp | 517 +- lldb/source/Interpreter/ScriptInterpreter.cpp | 116 +- lldb/source/Interpreter/embedded_interpreter.py | 44 +- 46 files changed, 10776 insertions(+), 12352 deletions(-) (limited to 'lldb/source/Interpreter') diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp index 2ffb8235430..997c0e1012b 100644 --- a/lldb/source/Interpreter/Args.cpp +++ b/lldb/source/Interpreter/Args.cpp @@ -12,15 +12,15 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -33,1822 +33,1635 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Args constructor //---------------------------------------------------------------------- -Args::Args (llvm::StringRef command) : - m_args(), - m_argv(), - m_args_quote_char() -{ - SetCommandString (command); +Args::Args(llvm::StringRef command) : m_args(), m_argv(), m_args_quote_char() { + SetCommandString(command); } - //---------------------------------------------------------------------- // We have to be very careful on the copy constructor of this class // to make sure we copy all of the string values, but we can't copy the -// rhs.m_argv into m_argv since it will point to the "const char *" c +// rhs.m_argv into m_argv since it will point to the "const char *" c // strings in rhs.m_args. We need to copy the string list and update our -// own m_argv appropriately. +// own m_argv appropriately. //---------------------------------------------------------------------- -Args::Args (const Args &rhs) : - m_args (rhs.m_args), - m_argv (), - m_args_quote_char(rhs.m_args_quote_char) -{ - UpdateArgvFromArgs(); +Args::Args(const Args &rhs) + : m_args(rhs.m_args), m_argv(), m_args_quote_char(rhs.m_args_quote_char) { + UpdateArgvFromArgs(); } //---------------------------------------------------------------------- // We have to be very careful on the copy constructor of this class // to make sure we copy all of the string values, but we can't copy the -// rhs.m_argv into m_argv since it will point to the "const char *" c +// rhs.m_argv into m_argv since it will point to the "const char *" c // strings in rhs.m_args. We need to copy the string list and update our -// own m_argv appropriately. +// own m_argv appropriately. //---------------------------------------------------------------------- -const Args & -Args::operator= (const Args &rhs) -{ - // Make sure we aren't assigning to self - if (this != &rhs) - { - m_args = rhs.m_args; - m_args_quote_char = rhs.m_args_quote_char; - UpdateArgvFromArgs(); - } - return *this; +const Args &Args::operator=(const Args &rhs) { + // Make sure we aren't assigning to self + if (this != &rhs) { + m_args = rhs.m_args; + m_args_quote_char = rhs.m_args_quote_char; + UpdateArgvFromArgs(); + } + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -Args::~Args () -{ -} - -void -Args::Dump (Stream &s, const char *label_name) const -{ - if (!label_name) - return; - - const size_t argc = m_argv.size(); - for (size_t i=0; i 0) - command += ' '; - command += m_argv[i]; - } - return argc > 0; +bool Args::GetCommandString(std::string &command) const { + command.clear(); + const size_t argc = GetArgumentCount(); + for (size_t i = 0; i < argc; ++i) { + if (i > 0) + command += ' '; + command += m_argv[i]; + } + return argc > 0; } -bool -Args::GetQuotedCommandString (std::string &command) const -{ - command.clear (); - const size_t argc = GetArgumentCount(); - for (size_t i = 0; i < argc; ++i) - { - if (i > 0) - command.append (1, ' '); - char quote_char = GetArgumentQuoteCharAtIndex(i); - if (quote_char) - { - command.append (1, quote_char); - command.append (m_argv[i]); - command.append (1, quote_char); - } - else - command.append (m_argv[i]); - } - return argc > 0; +bool Args::GetQuotedCommandString(std::string &command) const { + command.clear(); + const size_t argc = GetArgumentCount(); + for (size_t i = 0; i < argc; ++i) { + if (i > 0) + command.append(1, ' '); + char quote_char = GetArgumentQuoteCharAtIndex(i); + if (quote_char) { + command.append(1, quote_char); + command.append(m_argv[i]); + command.append(1, quote_char); + } else + command.append(m_argv[i]); + } + return argc > 0; } // A helper function for argument parsing. -// Parses the initial part of the first argument using normal double quote rules: -// backslash escapes the double quote and itself. The parsed string is appended to the second -// argument. The function returns the unparsed portion of the string, starting at the closing +// Parses the initial part of the first argument using normal double quote +// rules: +// backslash escapes the double quote and itself. The parsed string is appended +// to the second +// argument. The function returns the unparsed portion of the string, starting +// at the closing // quote. -static llvm::StringRef -ParseDoubleQuotes(llvm::StringRef quoted, std::string &result) -{ - // Inside double quotes, '\' and '"' are special. - static const char *k_escapable_characters = "\"\\"; - while (true) - { - // Skip over over regular characters and append them. - size_t regular = quoted.find_first_of(k_escapable_characters); - result += quoted.substr(0, regular); - quoted = quoted.substr(regular); - - // If we have reached the end of string or the closing quote, we're done. - if (quoted.empty() || quoted.front() == '"') - break; - - // We have found a backslash. - quoted = quoted.drop_front(); - - if (quoted.empty()) - { - // A lone backslash at the end of string, let's just append it. - result += '\\'; - break; - } +static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted, + std::string &result) { + // Inside double quotes, '\' and '"' are special. + static const char *k_escapable_characters = "\"\\"; + while (true) { + // Skip over over regular characters and append them. + size_t regular = quoted.find_first_of(k_escapable_characters); + result += quoted.substr(0, regular); + quoted = quoted.substr(regular); + + // If we have reached the end of string or the closing quote, we're done. + if (quoted.empty() || quoted.front() == '"') + break; + + // We have found a backslash. + quoted = quoted.drop_front(); + + if (quoted.empty()) { + // A lone backslash at the end of string, let's just append it. + result += '\\'; + break; + } - // If the character after the backslash is not a whitelisted escapable character, we - // leave the character sequence untouched. - if (strchr(k_escapable_characters, quoted.front()) == nullptr) - result += '\\'; + // If the character after the backslash is not a whitelisted escapable + // character, we + // leave the character sequence untouched. + if (strchr(k_escapable_characters, quoted.front()) == nullptr) + result += '\\'; - result += quoted.front(); - quoted = quoted.drop_front(); - } + result += quoted.front(); + quoted = quoted.drop_front(); + } - return quoted; + return quoted; } // A helper function for SetCommandString. -// Parses a single argument from the command string, processing quotes and backslashes in a -// shell-like manner. The parsed argument is appended to the m_args array. The function returns -// the unparsed portion of the string, starting at the first unqouted, unescaped whitespace +// Parses a single argument from the command string, processing quotes and +// backslashes in a +// shell-like manner. The parsed argument is appended to the m_args array. The +// function returns +// the unparsed portion of the string, starting at the first unqouted, unescaped +// whitespace // character. -llvm::StringRef -Args::ParseSingleArgument(llvm::StringRef command) -{ - // Argument can be split into multiple discontiguous pieces, - // for example: - // "Hello ""World" - // this would result in a single argument "Hello World" (without/ - // the quotes) since the quotes would be removed and there is - // not space between the strings. - - std::string arg; - - // Since we can have multiple quotes that form a single command - // in a command like: "Hello "world'!' (which will make a single - // argument "Hello world!") we remember the first quote character - // we encounter and use that for the quote character. - char first_quote_char = '\0'; - - bool arg_complete = false; - do - { - // Skip over over regular characters and append them. - size_t regular = command.find_first_of(" \t\"'`\\"); - arg += command.substr(0, regular); - command = command.substr(regular); - - if (command.empty()) - break; - - char special = command.front(); +llvm::StringRef Args::ParseSingleArgument(llvm::StringRef command) { + // Argument can be split into multiple discontiguous pieces, + // for example: + // "Hello ""World" + // this would result in a single argument "Hello World" (without/ + // the quotes) since the quotes would be removed and there is + // not space between the strings. + + std::string arg; + + // Since we can have multiple quotes that form a single command + // in a command like: "Hello "world'!' (which will make a single + // argument "Hello world!") we remember the first quote character + // we encounter and use that for the quote character. + char first_quote_char = '\0'; + + bool arg_complete = false; + do { + // Skip over over regular characters and append them. + size_t regular = command.find_first_of(" \t\"'`\\"); + arg += command.substr(0, regular); + command = command.substr(regular); + + if (command.empty()) + break; + + char special = command.front(); + command = command.drop_front(); + switch (special) { + case '\\': + if (command.empty()) { + arg += '\\'; + break; + } + + // If the character after the backslash is not a whitelisted escapable + // character, we + // leave the character sequence untouched. + if (strchr(" \t\\'\"`", command.front()) == nullptr) + arg += '\\'; + + arg += command.front(); + command = command.drop_front(); + + break; + + case ' ': + case '\t': + // We are not inside any quotes, we just found a space after an + // argument. We are done. + arg_complete = true; + break; + + case '"': + case '\'': + case '`': + // We found the start of a quote scope. + if (first_quote_char == '\0') + first_quote_char = special; + + if (special == '"') + command = ParseDoubleQuotes(command, arg); + else { + // For single quotes, we simply skip ahead to the matching quote + // character + // (or the end of the string). + size_t quoted = command.find(special); + arg += command.substr(0, quoted); + command = command.substr(quoted); + } + + // If we found a closing quote, skip it. + if (!command.empty()) command = command.drop_front(); - switch (special) - { - case '\\': - if (command.empty()) - { - arg += '\\'; - break; - } - - // If the character after the backslash is not a whitelisted escapable character, we - // leave the character sequence untouched. - if (strchr(" \t\\'\"`", command.front()) == nullptr) - arg += '\\'; - arg += command.front(); - command = command.drop_front(); - - break; - - case ' ': - case '\t': - // We are not inside any quotes, we just found a space after an - // argument. We are done. - arg_complete = true; - break; - - case '"': - case '\'': - case '`': - // We found the start of a quote scope. - if (first_quote_char == '\0') - first_quote_char = special; - - if (special == '"') - command = ParseDoubleQuotes(command, arg); - else - { - // For single quotes, we simply skip ahead to the matching quote character - // (or the end of the string). - size_t quoted = command.find(special); - arg += command.substr(0, quoted); - command = command.substr(quoted); - } - - // If we found a closing quote, skip it. - if (! command.empty()) - command = command.drop_front(); - - break; - } - } while (!arg_complete); + break; + } + } while (!arg_complete); - m_args.push_back(arg); - m_args_quote_char.push_back (first_quote_char); - return command; + m_args.push_back(arg); + m_args_quote_char.push_back(first_quote_char); + return command; } -void -Args::SetCommandString (llvm::StringRef command) -{ - m_args.clear(); - m_argv.clear(); - m_args_quote_char.clear(); +void Args::SetCommandString(llvm::StringRef command) { + m_args.clear(); + m_argv.clear(); + m_args_quote_char.clear(); - static const char *k_space_separators = " \t"; + static const char *k_space_separators = " \t"; + command = command.ltrim(k_space_separators); + while (!command.empty()) { + command = ParseSingleArgument(command); command = command.ltrim(k_space_separators); - while (!command.empty()) - { - command = ParseSingleArgument(command); - command = command.ltrim(k_space_separators); - } + } - UpdateArgvFromArgs(); + UpdateArgvFromArgs(); } -void -Args::UpdateArgsAfterOptionParsing() -{ - // Now m_argv might be out of date with m_args, so we need to fix that - arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end(); - arg_sstr_collection::iterator args_pos; - arg_quote_char_collection::iterator quotes_pos; - - for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin(); - argv_pos != argv_end && args_pos != m_args.end(); - ++argv_pos) - { - const char *argv_cstr = *argv_pos; - if (argv_cstr == nullptr) - break; - - while (args_pos != m_args.end()) - { - const char *args_cstr = args_pos->c_str(); - if (args_cstr == argv_cstr) - { - // We found the argument that matches the C string in the - // vector, so we can now look for the next one - ++args_pos; - ++quotes_pos; - break; - } - else - { - quotes_pos = m_args_quote_char.erase (quotes_pos); - args_pos = m_args.erase (args_pos); - } - } +void Args::UpdateArgsAfterOptionParsing() { + // Now m_argv might be out of date with m_args, so we need to fix that + arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end(); + arg_sstr_collection::iterator args_pos; + arg_quote_char_collection::iterator quotes_pos; + + for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), + quotes_pos = m_args_quote_char.begin(); + argv_pos != argv_end && args_pos != m_args.end(); ++argv_pos) { + const char *argv_cstr = *argv_pos; + if (argv_cstr == nullptr) + break; + + while (args_pos != m_args.end()) { + const char *args_cstr = args_pos->c_str(); + if (args_cstr == argv_cstr) { + // We found the argument that matches the C string in the + // vector, so we can now look for the next one + ++args_pos; + ++quotes_pos; + break; + } else { + quotes_pos = m_args_quote_char.erase(quotes_pos); + args_pos = m_args.erase(args_pos); + } } + } - if (args_pos != m_args.end()) - m_args.erase (args_pos, m_args.end()); + if (args_pos != m_args.end()) + m_args.erase(args_pos, m_args.end()); - if (quotes_pos != m_args_quote_char.end()) - m_args_quote_char.erase (quotes_pos, m_args_quote_char.end()); + if (quotes_pos != m_args_quote_char.end()) + m_args_quote_char.erase(quotes_pos, m_args_quote_char.end()); } -void -Args::UpdateArgvFromArgs() -{ - m_argv.clear(); - arg_sstr_collection::const_iterator pos, end = m_args.end(); - for (pos = m_args.begin(); pos != end; ++pos) - m_argv.push_back(pos->c_str()); - m_argv.push_back(nullptr); - // Make sure we have enough arg quote chars in the array - if (m_args_quote_char.size() < m_args.size()) - m_args_quote_char.resize (m_argv.size()); +void Args::UpdateArgvFromArgs() { + m_argv.clear(); + arg_sstr_collection::const_iterator pos, end = m_args.end(); + for (pos = m_args.begin(); pos != end; ++pos) + m_argv.push_back(pos->c_str()); + m_argv.push_back(nullptr); + // Make sure we have enough arg quote chars in the array + if (m_args_quote_char.size() < m_args.size()) + m_args_quote_char.resize(m_argv.size()); } -size_t -Args::GetArgumentCount() const -{ - if (m_argv.empty()) - return 0; - return m_argv.size() - 1; +size_t Args::GetArgumentCount() const { + if (m_argv.empty()) + return 0; + return m_argv.size() - 1; } -const char * -Args::GetArgumentAtIndex (size_t idx) const -{ - if (idx < m_argv.size()) - return m_argv[idx]; - return nullptr; +const char *Args::GetArgumentAtIndex(size_t idx) const { + if (idx < m_argv.size()) + return m_argv[idx]; + return nullptr; } -char -Args::GetArgumentQuoteCharAtIndex (size_t idx) const -{ - if (idx < m_args_quote_char.size()) - return m_args_quote_char[idx]; - return '\0'; +char Args::GetArgumentQuoteCharAtIndex(size_t idx) const { + if (idx < m_args_quote_char.size()) + return m_args_quote_char[idx]; + return '\0'; } -char ** -Args::GetArgumentVector() -{ - if (!m_argv.empty()) - return const_cast(&m_argv[0]); - return nullptr; +char **Args::GetArgumentVector() { + if (!m_argv.empty()) + return const_cast(&m_argv[0]); + return nullptr; } -const char ** -Args::GetConstArgumentVector() const -{ - if (!m_argv.empty()) - return const_cast(&m_argv[0]); - return nullptr; +const char **Args::GetConstArgumentVector() const { + if (!m_argv.empty()) + return const_cast(&m_argv[0]); + return nullptr; } -void -Args::Shift () -{ - // Don't pop the last NULL terminator from the argv array - if (m_argv.size() > 1) - { - m_argv.erase(m_argv.begin()); - m_args.pop_front(); - if (!m_args_quote_char.empty()) - m_args_quote_char.erase(m_args_quote_char.begin()); - } +void Args::Shift() { + // Don't pop the last NULL terminator from the argv array + if (m_argv.size() > 1) { + m_argv.erase(m_argv.begin()); + m_args.pop_front(); + if (!m_args_quote_char.empty()) + m_args_quote_char.erase(m_args_quote_char.begin()); + } } -const char * -Args::Unshift (const char *arg_cstr, char quote_char) -{ - m_args.push_front(arg_cstr); - m_argv.insert(m_argv.begin(), m_args.front().c_str()); - m_args_quote_char.insert(m_args_quote_char.begin(), quote_char); - return GetArgumentAtIndex (0); +const char *Args::Unshift(const char *arg_cstr, char quote_char) { + m_args.push_front(arg_cstr); + m_argv.insert(m_argv.begin(), m_args.front().c_str()); + m_args_quote_char.insert(m_args_quote_char.begin(), quote_char); + return GetArgumentAtIndex(0); } -void -Args::AppendArguments (const Args &rhs) -{ - const size_t rhs_argc = rhs.GetArgumentCount(); - for (size_t i=0; i 0 && pos != end; ++pos) + --i; + + pos = m_args.insert(pos, arg_cstr); + + if (idx >= m_args_quote_char.size()) { + m_args_quote_char.resize(idx + 1); + m_args_quote_char[idx] = quote_char; + } else + m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char); + + UpdateArgvFromArgs(); + return GetArgumentAtIndex(idx); } -const char * -Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char) -{ - // Since we are using a std::list to hold onto the copied C string and - // we don't have direct access to the elements, we have to iterate to - // find the value. - arg_sstr_collection::iterator pos, end = m_args.end(); - size_t i = idx; - for (pos = m_args.begin(); i > 0 && pos != end; ++pos) - --i; - - pos = m_args.insert(pos, arg_cstr); - +const char *Args::ReplaceArgumentAtIndex(size_t idx, const char *arg_cstr, + char quote_char) { + // Since we are using a std::list to hold onto the copied C string and + // we don't have direct access to the elements, we have to iterate to + // find the value. + arg_sstr_collection::iterator pos, end = m_args.end(); + size_t i = idx; + for (pos = m_args.begin(); i > 0 && pos != end; ++pos) + --i; + + if (pos != end) { + pos->assign(arg_cstr); + assert(idx < m_argv.size() - 1); + m_argv[idx] = pos->c_str(); if (idx >= m_args_quote_char.size()) - { - m_args_quote_char.resize(idx + 1); - m_args_quote_char[idx] = quote_char; - } - else - m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char); - - UpdateArgvFromArgs(); + m_args_quote_char.resize(idx + 1); + m_args_quote_char[idx] = quote_char; return GetArgumentAtIndex(idx); + } + return nullptr; } -const char * -Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char) -{ - // Since we are using a std::list to hold onto the copied C string and - // we don't have direct access to the elements, we have to iterate to - // find the value. - arg_sstr_collection::iterator pos, end = m_args.end(); - size_t i = idx; - for (pos = m_args.begin(); i > 0 && pos != end; ++pos) - --i; - - if (pos != end) - { - pos->assign(arg_cstr); - assert(idx < m_argv.size() - 1); - m_argv[idx] = pos->c_str(); - if (idx >= m_args_quote_char.size()) - m_args_quote_char.resize(idx + 1); - m_args_quote_char[idx] = quote_char; - return GetArgumentAtIndex(idx); - } - return nullptr; +void Args::DeleteArgumentAtIndex(size_t idx) { + // Since we are using a std::list to hold onto the copied C string and + // we don't have direct access to the elements, we have to iterate to + // find the value. + arg_sstr_collection::iterator pos, end = m_args.end(); + size_t i = idx; + for (pos = m_args.begin(); i > 0 && pos != end; ++pos) + --i; + + if (pos != end) { + m_args.erase(pos); + assert(idx < m_argv.size() - 1); + m_argv.erase(m_argv.begin() + idx); + if (idx < m_args_quote_char.size()) + m_args_quote_char.erase(m_args_quote_char.begin() + idx); + } } -void -Args::DeleteArgumentAtIndex (size_t idx) -{ - // Since we are using a std::list to hold onto the copied C string and - // we don't have direct access to the elements, we have to iterate to - // find the value. - arg_sstr_collection::iterator pos, end = m_args.end(); - size_t i = idx; - for (pos = m_args.begin(); i > 0 && pos != end; ++pos) - --i; - - if (pos != end) - { - m_args.erase (pos); - assert(idx < m_argv.size() - 1); - m_argv.erase(m_argv.begin() + idx); - if (idx < m_args_quote_char.size()) - m_args_quote_char.erase(m_args_quote_char.begin() + idx); - } +void Args::SetArguments(size_t argc, const char **argv) { + // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is + // no need to clear it here. + m_args.clear(); + m_args_quote_char.clear(); + + // First copy each string + for (size_t i = 0; i < argc; ++i) { + m_args.push_back(argv[i]); + if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`')) + m_args_quote_char.push_back(argv[i][0]); + else + m_args_quote_char.push_back('\0'); + } + + UpdateArgvFromArgs(); } -void -Args::SetArguments (size_t argc, const char **argv) -{ - // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is - // no need to clear it here. - m_args.clear(); - m_args_quote_char.clear(); +void Args::SetArguments(const char **argv) { + // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is + // no need to clear it here. + m_args.clear(); + m_args_quote_char.clear(); + if (argv) { // First copy each string - for (size_t i=0; ioption_has_arg) { + default: + case OptionParser::eNoArgument: + break; + case OptionParser::eRequiredArgument: + sstr << ':'; + break; + case OptionParser::eOptionalArgument: + sstr << "::"; + break; } + } } - - UpdateArgvFromArgs(); -} - - -Error -Args::ParseOptions (Options &options, ExecutionContext *execution_context, - PlatformSP platform_sp, bool require_validation) -{ - StreamString sstr; - Error error; - Option *long_options = options.GetLongOptions(); - if (long_options == nullptr) - { - error.SetErrorStringWithFormat("invalid long options"); - return error; + } + std::unique_lock lock; + OptionParser::Prepare(lock); + int val; + while (1) { + int long_options_index = -1; + val = + OptionParser::Parse(GetArgumentCount(), GetArgumentVector(), + sstr.GetData(), long_options, &long_options_index); + if (val == -1) + break; + + // Did we get an error? + if (val == '?') { + error.SetErrorStringWithFormat("unknown or ambiguous option"); + break; } - - for (int i=0; long_options[i].definition != nullptr; ++i) - { - if (long_options[i].flag == nullptr) - { - if (isprint8(long_options[i].val)) - { - sstr << (char)long_options[i].val; - switch (long_options[i].definition->option_has_arg) - { - default: - case OptionParser::eNoArgument: break; - case OptionParser::eRequiredArgument: sstr << ':'; break; - case OptionParser::eOptionalArgument: sstr << "::"; break; - } - } + // The option auto-set itself + if (val == 0) + continue; + + ((Options *)&options)->OptionSeen(val); + + // Lookup the long option index + if (long_options_index == -1) { + for (int i = 0; long_options[i].definition || long_options[i].flag || + long_options[i].val; + ++i) { + if (long_options[i].val == val) { + long_options_index = i; + break; } + } } - std::unique_lock lock; - OptionParser::Prepare(lock); - int val; - while (1) - { - int long_options_index = -1; - val = OptionParser::Parse(GetArgumentCount(), - GetArgumentVector(), - sstr.GetData(), - long_options, - &long_options_index); - if (val == -1) - break; - - // Did we get an error? - if (val == '?') - { - error.SetErrorStringWithFormat("unknown or ambiguous option"); - break; - } - // The option auto-set itself - if (val == 0) - continue; - - ((Options *) &options)->OptionSeen (val); - - // Lookup the long option index - if (long_options_index == -1) - { - for (int i=0; - long_options[i].definition || long_options[i].flag || long_options[i].val; - ++i) - { - if (long_options[i].val == val) - { - long_options_index = i; - break; - } - } - } - // Call the callback with the option - if (long_options_index >= 0 && long_options[long_options_index].definition) - { - const OptionDefinition *def = long_options[long_options_index].definition; - - if (!platform_sp) - { - // User did not pass in an explicit platform. Try to grab - // from the execution context. - TargetSP target_sp = execution_context ? - execution_context->GetTargetSP() : TargetSP(); - platform_sp = target_sp ? - target_sp->GetPlatform() : PlatformSP(); - } - OptionValidator *validator = def->validator; - - if (!platform_sp && require_validation) - { - // Caller requires validation but we cannot validate as we - // don't have the mandatory platform against which to - // validate. - error.SetErrorString("cannot validate options: " - "no platform available"); - return error; - } - - bool validation_failed = false; - if (platform_sp) - { - // Ensure we have an execution context, empty or not. - ExecutionContext dummy_context; - ExecutionContext *exe_ctx_p = - execution_context ? execution_context : &dummy_context; - if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) - { - validation_failed = true; - error.SetErrorStringWithFormat("Option \"%s\" invalid. %s", def->long_option, def->validator->LongConditionString()); - } - } - - // As long as validation didn't fail, we set the option value. - if (!validation_failed) - error = options.SetOptionValue(long_options_index, - (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument(), - execution_context); - } - else - { - error.SetErrorStringWithFormat("invalid option with value '%i'", val); + // Call the callback with the option + if (long_options_index >= 0 && + long_options[long_options_index].definition) { + const OptionDefinition *def = long_options[long_options_index].definition; + + if (!platform_sp) { + // User did not pass in an explicit platform. Try to grab + // from the execution context. + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); + } + OptionValidator *validator = def->validator; + + if (!platform_sp && require_validation) { + // Caller requires validation but we cannot validate as we + // don't have the mandatory platform against which to + // validate. + error.SetErrorString("cannot validate options: " + "no platform available"); + return error; + } + + bool validation_failed = false; + if (platform_sp) { + // Ensure we have an execution context, empty or not. + ExecutionContext dummy_context; + ExecutionContext *exe_ctx_p = + execution_context ? execution_context : &dummy_context; + if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) { + validation_failed = true; + error.SetErrorStringWithFormat("Option \"%s\" invalid. %s", + def->long_option, + def->validator->LongConditionString()); } - if (error.Fail()) - break; + } + + // As long as validation didn't fail, we set the option value. + if (!validation_failed) + error = options.SetOptionValue( + long_options_index, + (def->option_has_arg == OptionParser::eNoArgument) + ? nullptr + : OptionParser::GetOptionArgument(), + execution_context); + } else { + error.SetErrorStringWithFormat("invalid option with value '%i'", val); } - - // Update our ARGV now that get options has consumed all the options - m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex()); - UpdateArgsAfterOptionParsing (); - return error; + if (error.Fail()) + break; + } + + // Update our ARGV now that get options has consumed all the options + m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex()); + UpdateArgsAfterOptionParsing(); + return error; } -void -Args::Clear () -{ - m_args.clear (); - m_argv.clear (); - m_args_quote_char.clear(); +void Args::Clear() { + m_args.clear(); + m_argv.clear(); + m_args_quote_char.clear(); } -lldb::addr_t -Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr) -{ - bool error_set = false; - if (s && s[0]) - { - char *end = nullptr; - lldb::addr_t addr = ::strtoull (s, &end, 0); - if (*end == '\0') - { - if (error_ptr) - error_ptr->Clear(); - return addr; // All characters were used, return the result - } - // Try base 16 with no prefix... - addr = ::strtoull (s, &end, 16); - if (*end == '\0') - { +lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx, + const char *s, lldb::addr_t fail_value, + Error *error_ptr) { + bool error_set = false; + if (s && s[0]) { + char *end = nullptr; + lldb::addr_t addr = ::strtoull(s, &end, 0); + if (*end == '\0') { + if (error_ptr) + error_ptr->Clear(); + return addr; // All characters were used, return the result + } + // Try base 16 with no prefix... + addr = ::strtoull(s, &end, 16); + if (*end == '\0') { + if (error_ptr) + error_ptr->Clear(); + return addr; // All characters were used, return the result + } + + if (exe_ctx) { + Target *target = exe_ctx->GetTargetPtr(); + if (target) { + lldb::ValueObjectSP valobj_sp; + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(false); + options.SetTryAllThreads(true); + + ExpressionResults expr_result = target->EvaluateExpression( + s, exe_ctx->GetFramePtr(), valobj_sp, options); + + bool success = false; + if (expr_result == eExpressionCompleted) { + if (valobj_sp) + valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( + valobj_sp->GetDynamicValueType(), true); + // Get the address to watch. + if (valobj_sp) + addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); + if (success) { if (error_ptr) - error_ptr->Clear(); - return addr; // All characters were used, return the result - } - - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) - { - lldb::ValueObjectSP valobj_sp; - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(false); - options.SetTryAllThreads(true); - - ExpressionResults expr_result = target->EvaluateExpression(s, - exe_ctx->GetFramePtr(), - valobj_sp, - options); - - bool success = false; - if (expr_result == eExpressionCompleted) - { - if (valobj_sp) - valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(valobj_sp->GetDynamicValueType(), true); - // Get the address to watch. - if (valobj_sp) - addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); - if (success) - { - if (error_ptr) - error_ptr->Clear(); - return addr; - } - else - { - if (error_ptr) - { - error_set = true; - error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString()); - } - } - - } - else - { - // Since the compiler can't handle things like "main + 12" we should - // try to do this for now. The compiler doesn't like adding offsets - // to function pointer types. - static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); - RegularExpression::Match regex_match(3); - if (g_symbol_plus_offset_regex.Execute(s, ®ex_match)) - { - uint64_t offset = 0; - bool add = true; - std::string name; - std::string str; - if (regex_match.GetMatchAtIndex(s, 1, name)) - { - if (regex_match.GetMatchAtIndex(s, 2, str)) - { - add = str[0] == '+'; - - if (regex_match.GetMatchAtIndex(s, 3, str)) - { - offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success); - - if (success) - { - Error error; - addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error); - if (addr != LLDB_INVALID_ADDRESS) - { - if (add) - return addr + offset; - else - return addr - offset; - } - } - } - } - } - } - - if (error_ptr) - { - error_set = true; - error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s); + error_ptr->Clear(); + return addr; + } else { + if (error_ptr) { + error_set = true; + error_ptr->SetErrorStringWithFormat( + "address expression \"%s\" resulted in a value whose type " + "can't be converted to an address: %s", + s, valobj_sp->GetTypeName().GetCString()); + } + } + + } else { + // Since the compiler can't handle things like "main + 12" we should + // try to do this for now. The compiler doesn't like adding offsets + // to function pointer types. + static RegularExpression g_symbol_plus_offset_regex( + "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); + RegularExpression::Match regex_match(3); + if (g_symbol_plus_offset_regex.Execute(s, ®ex_match)) { + uint64_t offset = 0; + bool add = true; + std::string name; + std::string str; + if (regex_match.GetMatchAtIndex(s, 1, name)) { + if (regex_match.GetMatchAtIndex(s, 2, str)) { + add = str[0] == '+'; + + if (regex_match.GetMatchAtIndex(s, 3, str)) { + offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success); + + if (success) { + Error error; + addr = StringToAddress(exe_ctx, name.c_str(), + LLDB_INVALID_ADDRESS, &error); + if (addr != LLDB_INVALID_ADDRESS) { + if (add) + return addr + offset; + else + return addr - offset; } + } } + } } + } + + if (error_ptr) { + error_set = true; + error_ptr->SetErrorStringWithFormat( + "address expression \"%s\" evaluation failed", s); + } } + } } - if (error_ptr) - { - if (!error_set) - error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s); - } - return fail_value; + } + if (error_ptr) { + if (!error_set) + error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", + s); + } + return fail_value; } -const char * -Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty) -{ - static const char *k_white_space = " \t\v"; - if (!s.empty()) - { - if (leading) - { - size_t pos = s.find_first_not_of (k_white_space); - if (pos == std::string::npos) - s.clear(); - else if (pos > 0) - s.erase(0, pos); - } - - if (trailing) - { - size_t rpos = s.find_last_not_of(k_white_space); - if (rpos != std::string::npos && rpos + 1 < s.size()) - s.erase(rpos + 1); - } +const char *Args::StripSpaces(std::string &s, bool leading, bool trailing, + bool return_null_if_empty) { + static const char *k_white_space = " \t\v"; + if (!s.empty()) { + if (leading) { + size_t pos = s.find_first_not_of(k_white_space); + if (pos == std::string::npos) + s.clear(); + else if (pos > 0) + s.erase(0, pos); } - if (return_null_if_empty && s.empty()) - return nullptr; - return s.c_str(); -} -bool -Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr) -{ - if (!s) - return fail_value; - return Args::StringToBoolean(llvm::StringRef(s), fail_value, success_ptr); + if (trailing) { + size_t rpos = s.find_last_not_of(k_white_space); + if (rpos != std::string::npos && rpos + 1 < s.size()) + s.erase(rpos + 1); + } + } + if (return_null_if_empty && s.empty()) + return nullptr; + return s.c_str(); } -bool -Args::StringToBoolean(llvm::StringRef ref, bool fail_value, bool *success_ptr) -{ - ref = ref.trim(); - if (ref.equals_lower("false") || - ref.equals_lower("off") || - ref.equals_lower("no") || - ref.equals_lower("0")) - { - if (success_ptr) - *success_ptr = true; - return false; - } - else if (ref.equals_lower("true") || ref.equals_lower("on") || ref.equals_lower("yes") || ref.equals_lower("1")) - { - if (success_ptr) - *success_ptr = true; - return true; - } - if (success_ptr) *success_ptr = false; +bool Args::StringToBoolean(const char *s, bool fail_value, bool *success_ptr) { + if (!s) return fail_value; + return Args::StringToBoolean(llvm::StringRef(s), fail_value, success_ptr); } -char -Args::StringToChar(const char *s, char fail_value, bool *success_ptr) -{ - bool success = false; - char result = fail_value; - - if (s) - { - size_t length = strlen(s); - if (length == 1) - { - success = true; - result = s[0]; - } - } +bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value, + bool *success_ptr) { + ref = ref.trim(); + if (ref.equals_lower("false") || ref.equals_lower("off") || + ref.equals_lower("no") || ref.equals_lower("0")) { if (success_ptr) - *success_ptr = success; - return result; + *success_ptr = true; + return false; + } else if (ref.equals_lower("true") || ref.equals_lower("on") || + ref.equals_lower("yes") || ref.equals_lower("1")) { + if (success_ptr) + *success_ptr = true; + return true; + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -const char * -Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update) -{ - major = UINT32_MAX; - minor = UINT32_MAX; - update = UINT32_MAX; - - if (s && s[0]) - { - char *pos = nullptr; - unsigned long uval32 = ::strtoul (s, &pos, 0); - if (pos == s) - return s; - major = uval32; - if (*pos == '\0') - { - return pos; // Decoded major and got end of string - } - else if (*pos == '.') - { - const char *minor_cstr = pos + 1; - uval32 = ::strtoul (minor_cstr, &pos, 0); - if (pos == minor_cstr) - return pos; // Didn't get any digits for the minor version... - minor = uval32; - if (*pos == '.') - { - const char *update_cstr = pos + 1; - uval32 = ::strtoul (update_cstr, &pos, 0); - if (pos == update_cstr) - return pos; - update = uval32; - } - return pos; - } +char Args::StringToChar(const char *s, char fail_value, bool *success_ptr) { + bool success = false; + char result = fail_value; + + if (s) { + size_t length = strlen(s); + if (length == 1) { + success = true; + result = s[0]; } - return nullptr; + } + if (success_ptr) + *success_ptr = success; + return result; } -const char * -Args::GetShellSafeArgument (const FileSpec& shell, - const char *unsafe_arg, - std::string &safe_arg) -{ - struct ShellDescriptor - { - ConstString m_basename; - const char* m_escapables; - }; - - static ShellDescriptor g_Shells[] = { - {ConstString("bash")," '\"<>()&"}, - {ConstString("tcsh")," '\"<>()&$"}, - {ConstString("sh")," '\"<>()&"} - }; - - // safe minimal set - const char* escapables = " '\""; - - if (auto basename = shell.GetFilename()) - { - for (const auto& Shell : g_Shells) - { - if (Shell.m_basename == basename) - { - escapables = Shell.m_escapables; - break; - } - } +const char *Args::StringToVersion(const char *s, uint32_t &major, + uint32_t &minor, uint32_t &update) { + major = UINT32_MAX; + minor = UINT32_MAX; + update = UINT32_MAX; + + if (s && s[0]) { + char *pos = nullptr; + unsigned long uval32 = ::strtoul(s, &pos, 0); + if (pos == s) + return s; + major = uval32; + if (*pos == '\0') { + return pos; // Decoded major and got end of string + } else if (*pos == '.') { + const char *minor_cstr = pos + 1; + uval32 = ::strtoul(minor_cstr, &pos, 0); + if (pos == minor_cstr) + return pos; // Didn't get any digits for the minor version... + minor = uval32; + if (*pos == '.') { + const char *update_cstr = pos + 1; + uval32 = ::strtoul(update_cstr, &pos, 0); + if (pos == update_cstr) + return pos; + update = uval32; + } + return pos; } + } + return nullptr; +} - safe_arg.assign (unsafe_arg); - size_t prev_pos = 0; - while (prev_pos < safe_arg.size()) - { - // Escape spaces and quotes - size_t pos = safe_arg.find_first_of(escapables, prev_pos); - if (pos != std::string::npos) - { - safe_arg.insert (pos, 1, '\\'); - prev_pos = pos + 2; - } - else - break; +const char *Args::GetShellSafeArgument(const FileSpec &shell, + const char *unsafe_arg, + std::string &safe_arg) { + struct ShellDescriptor { + ConstString m_basename; + const char *m_escapables; + }; + + static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"}, + {ConstString("tcsh"), " '\"<>()&$"}, + {ConstString("sh"), " '\"<>()&"}}; + + // safe minimal set + const char *escapables = " '\""; + + if (auto basename = shell.GetFilename()) { + for (const auto &Shell : g_Shells) { + if (Shell.m_basename == basename) { + escapables = Shell.m_escapables; + break; + } } - return safe_arg.c_str(); + } + + safe_arg.assign(unsafe_arg); + size_t prev_pos = 0; + while (prev_pos < safe_arg.size()) { + // Escape spaces and quotes + size_t pos = safe_arg.find_first_of(escapables, prev_pos); + if (pos != std::string::npos) { + safe_arg.insert(pos, 1, '\\'); + prev_pos = pos + 2; + } else + break; + } + return safe_arg.c_str(); } -int64_t -Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error) -{ - if (enum_values) - { - if (s && s[0]) - { - for (int i = 0; enum_values[i].string_value != nullptr ; i++) - { - if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value) - { - error.Clear(); - return enum_values[i].value; - } - } - } - - StreamString strm; - strm.PutCString ("invalid enumeration value, valid values are: "); - for (int i = 0; enum_values[i].string_value != nullptr; i++) - { - strm.Printf ("%s\"%s\"", - i > 0 ? ", " : "", - enum_values[i].string_value); +int64_t Args::StringToOptionEnum(const char *s, + OptionEnumValueElement *enum_values, + int32_t fail_value, Error &error) { + if (enum_values) { + if (s && s[0]) { + for (int i = 0; enum_values[i].string_value != nullptr; i++) { + if (strstr(enum_values[i].string_value, s) == + enum_values[i].string_value) { + error.Clear(); + return enum_values[i].value; } - error.SetErrorString(strm.GetData()); + } } - else - { - error.SetErrorString ("invalid enumeration argument"); + + StreamString strm; + strm.PutCString("invalid enumeration value, valid values are: "); + for (int i = 0; enum_values[i].string_value != nullptr; i++) { + strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value); } - return fail_value; + error.SetErrorString(strm.GetData()); + } else { + error.SetErrorString("invalid enumeration argument"); + } + return fail_value; } -ScriptLanguage -Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr) -{ - if (s && s[0]) - { - if ((::strcasecmp (s, "python") == 0) || - (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault)) - { - if (success_ptr) *success_ptr = true; - return eScriptLanguagePython; - } - if (::strcasecmp (s, "none")) - { - if (success_ptr) *success_ptr = true; - return eScriptLanguageNone; - } +ScriptLanguage Args::StringToScriptLanguage(const char *s, + ScriptLanguage fail_value, + bool *success_ptr) { + if (s && s[0]) { + if ((::strcasecmp(s, "python") == 0) || + (::strcasecmp(s, "default") == 0 && + eScriptLanguagePython == eScriptLanguageDefault)) { + if (success_ptr) + *success_ptr = true; + return eScriptLanguagePython; } - if (success_ptr) *success_ptr = false; - return fail_value; + if (::strcasecmp(s, "none")) { + if (success_ptr) + *success_ptr = true; + return eScriptLanguageNone; + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -Error -Args::StringToFormat -( - const char *s, - lldb::Format &format, - size_t *byte_size_ptr -) -{ - format = eFormatInvalid; - Error error; - - if (s && s[0]) - { - if (byte_size_ptr) - { - if (isdigit (s[0])) - { - char *format_char = nullptr; - unsigned long byte_size = ::strtoul (s, &format_char, 0); - if (byte_size != ULONG_MAX) - *byte_size_ptr = byte_size; - s = format_char; - } - else - *byte_size_ptr = 0; - } - - const bool partial_match_ok = true; - if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format)) - { - StreamString error_strm; - error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s); - for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1)) - { - char format_char = FormatManager::GetFormatAsFormatChar(f); - if (format_char) - error_strm.Printf ("'%c' or ", format_char); - - error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f)); - error_strm.EOL(); - } - - if (byte_size_ptr) - error_strm.PutCString ("An optional byte size can precede the format character.\n"); - error.SetErrorString(error_strm.GetString().c_str()); - } - - if (error.Fail()) - return error; +Error Args::StringToFormat(const char *s, lldb::Format &format, + size_t *byte_size_ptr) { + format = eFormatInvalid; + Error error; + + if (s && s[0]) { + if (byte_size_ptr) { + if (isdigit(s[0])) { + char *format_char = nullptr; + unsigned long byte_size = ::strtoul(s, &format_char, 0); + if (byte_size != ULONG_MAX) + *byte_size_ptr = byte_size; + s = format_char; + } else + *byte_size_ptr = 0; } - else - { - error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); + + const bool partial_match_ok = true; + if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) { + StreamString error_strm; + error_strm.Printf( + "Invalid format character or name '%s'. Valid values are:\n", s); + for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { + char format_char = FormatManager::GetFormatAsFormatChar(f); + if (format_char) + error_strm.Printf("'%c' or ", format_char); + + error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); + error_strm.EOL(); + } + + if (byte_size_ptr) + error_strm.PutCString( + "An optional byte size can precede the format character.\n"); + error.SetErrorString(error_strm.GetString().c_str()); } - return error; -} -lldb::Encoding -Args::StringToEncoding (const char *s, lldb::Encoding fail_value) -{ - if (!s) - return fail_value; - return StringToEncoding(llvm::StringRef(s), fail_value); + if (error.Fail()) + return error; + } else { + error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); + } + return error; } -lldb::Encoding -Args::StringToEncoding(llvm::StringRef s, lldb::Encoding fail_value) -{ - return llvm::StringSwitch(s) - .Case("uint", eEncodingUint) - .Case("sint", eEncodingSint) - .Case("ieee754", eEncodingIEEE754) - .Case("vector", eEncodingVector) - .Default(fail_value); +lldb::Encoding Args::StringToEncoding(const char *s, + lldb::Encoding fail_value) { + if (!s) + return fail_value; + return StringToEncoding(llvm::StringRef(s), fail_value); } -uint32_t -Args::StringToGenericRegister (const char *s) -{ - if (!s) - return LLDB_INVALID_REGNUM; - return StringToGenericRegister(llvm::StringRef(s)); +lldb::Encoding Args::StringToEncoding(llvm::StringRef s, + lldb::Encoding fail_value) { + return llvm::StringSwitch(s) + .Case("uint", eEncodingUint) + .Case("sint", eEncodingSint) + .Case("ieee754", eEncodingIEEE754) + .Case("vector", eEncodingVector) + .Default(fail_value); } -uint32_t -Args::StringToGenericRegister(llvm::StringRef s) -{ - if (s.empty()) - return LLDB_INVALID_REGNUM; - uint32_t result = llvm::StringSwitch(s) - .Case("pc", LLDB_REGNUM_GENERIC_PC) - .Case("sp", LLDB_REGNUM_GENERIC_SP) - .Case("fp", LLDB_REGNUM_GENERIC_FP) - .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA) - .Case("flags", LLDB_REGNUM_GENERIC_FLAGS) - .Case("arg1", LLDB_REGNUM_GENERIC_ARG1) - .Case("arg2", LLDB_REGNUM_GENERIC_ARG2) - .Case("arg3", LLDB_REGNUM_GENERIC_ARG3) - .Case("arg4", LLDB_REGNUM_GENERIC_ARG4) - .Case("arg5", LLDB_REGNUM_GENERIC_ARG5) - .Case("arg6", LLDB_REGNUM_GENERIC_ARG6) - .Case("arg7", LLDB_REGNUM_GENERIC_ARG7) - .Case("arg8", LLDB_REGNUM_GENERIC_ARG8) - .Default(LLDB_INVALID_REGNUM); - return result; +uint32_t Args::StringToGenericRegister(const char *s) { + if (!s) + return LLDB_INVALID_REGNUM; + return StringToGenericRegister(llvm::StringRef(s)); } +uint32_t Args::StringToGenericRegister(llvm::StringRef s) { + if (s.empty()) + return LLDB_INVALID_REGNUM; + uint32_t result = llvm::StringSwitch(s) + .Case("pc", LLDB_REGNUM_GENERIC_PC) + .Case("sp", LLDB_REGNUM_GENERIC_SP) + .Case("fp", LLDB_REGNUM_GENERIC_FP) + .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA) + .Case("flags", LLDB_REGNUM_GENERIC_FLAGS) + .Case("arg1", LLDB_REGNUM_GENERIC_ARG1) + .Case("arg2", LLDB_REGNUM_GENERIC_ARG2) + .Case("arg3", LLDB_REGNUM_GENERIC_ARG3) + .Case("arg4", LLDB_REGNUM_GENERIC_ARG4) + .Case("arg5", LLDB_REGNUM_GENERIC_ARG5) + .Case("arg6", LLDB_REGNUM_GENERIC_ARG6) + .Case("arg7", LLDB_REGNUM_GENERIC_ARG7) + .Case("arg8", LLDB_REGNUM_GENERIC_ARG8) + .Default(LLDB_INVALID_REGNUM); + return result; +} -void -Args::LongestCommonPrefix (std::string &common_prefix) -{ - arg_sstr_collection::iterator pos, end = m_args.end(); - pos = m_args.begin(); - if (pos == end) - common_prefix.clear(); - else - common_prefix = (*pos); - - for (++pos; pos != end; ++pos) - { - size_t new_size = (*pos).size(); +void Args::LongestCommonPrefix(std::string &common_prefix) { + arg_sstr_collection::iterator pos, end = m_args.end(); + pos = m_args.begin(); + if (pos == end) + common_prefix.clear(); + else + common_prefix = (*pos); - // First trim common_prefix if it is longer than the current element: - if (common_prefix.size() > new_size) - common_prefix.erase (new_size); + for (++pos; pos != end; ++pos) { + size_t new_size = (*pos).size(); - // Then trim it at the first disparity: + // First trim common_prefix if it is longer than the current element: + if (common_prefix.size() > new_size) + common_prefix.erase(new_size); - for (size_t i = 0; i < common_prefix.size(); i++) - { - if ((*pos)[i] != common_prefix[i]) - { - common_prefix.erase(i); - break; - } - } + // Then trim it at the first disparity: - // If we've emptied the common prefix, we're done. - if (common_prefix.empty()) - break; + for (size_t i = 0; i < common_prefix.size(); i++) { + if ((*pos)[i] != common_prefix[i]) { + common_prefix.erase(i); + break; + } } + + // If we've emptied the common prefix, we're done. + if (common_prefix.empty()) + break; + } } -void -Args::AddOrReplaceEnvironmentVariable(const char *env_var_name, - const char *new_value) -{ - if (!env_var_name || !new_value) - return; - - // Build the new entry. - StreamString stream; - stream << env_var_name; - stream << '='; - stream << new_value; - stream.Flush(); - - // Find the environment variable if present and replace it. - for (size_t i = 0; i < GetArgumentCount(); ++i) - { - // Get the env var value. - const char *arg_value = GetArgumentAtIndex(i); - if (!arg_value) - continue; - - // Find the name of the env var: before the first =. - auto equal_p = strchr(arg_value, '='); - if (!equal_p) - continue; - - // Check if the name matches the given env_var_name. - if (strncmp(env_var_name, arg_value, equal_p - arg_value) == 0) - { - ReplaceArgumentAtIndex(i, stream.GetString().c_str()); - return; - } +void Args::AddOrReplaceEnvironmentVariable(const char *env_var_name, + const char *new_value) { + if (!env_var_name || !new_value) + return; + + // Build the new entry. + StreamString stream; + stream << env_var_name; + stream << '='; + stream << new_value; + stream.Flush(); + + // Find the environment variable if present and replace it. + for (size_t i = 0; i < GetArgumentCount(); ++i) { + // Get the env var value. + const char *arg_value = GetArgumentAtIndex(i); + if (!arg_value) + continue; + + // Find the name of the env var: before the first =. + auto equal_p = strchr(arg_value, '='); + if (!equal_p) + continue; + + // Check if the name matches the given env_var_name. + if (strncmp(env_var_name, arg_value, equal_p - arg_value) == 0) { + ReplaceArgumentAtIndex(i, stream.GetString().c_str()); + return; } + } - // We didn't find it. Append it instead. - AppendArgument(stream.GetString().c_str()); + // We didn't find it. Append it instead. + AppendArgument(stream.GetString().c_str()); } -bool -Args::ContainsEnvironmentVariable(const char *env_var_name, - size_t *argument_index) const -{ - // Validate args. - if (!env_var_name) - return false; - - // Check each arg to see if it matches the env var name. - for (size_t i = 0; i < GetArgumentCount(); ++i) - { - // Get the arg value. - const char *argument_value = GetArgumentAtIndex(i); - if (!argument_value) - continue; - - // Check if we are the "{env_var_name}={env_var_value}" style. - const char *equal_p = strchr(argument_value, '='); - if (equal_p) - { - if (strncmp(env_var_name, argument_value, - equal_p - argument_value) == 0) - { - // We matched. - if (argument_index) - *argument_index = i; - return true; - } - } - else - { - // We're a simple {env_var_name}-style entry. - if (strcmp(argument_value, env_var_name) == 0) - { - // We matched. - if (argument_index) - *argument_index = i; - return true; - } - } +bool Args::ContainsEnvironmentVariable(const char *env_var_name, + size_t *argument_index) const { + // Validate args. + if (!env_var_name) + return false; + + // Check each arg to see if it matches the env var name. + for (size_t i = 0; i < GetArgumentCount(); ++i) { + // Get the arg value. + const char *argument_value = GetArgumentAtIndex(i); + if (!argument_value) + continue; + + // Check if we are the "{env_var_name}={env_var_value}" style. + const char *equal_p = strchr(argument_value, '='); + if (equal_p) { + if (strncmp(env_var_name, argument_value, equal_p - argument_value) == + 0) { + // We matched. + if (argument_index) + *argument_index = i; + return true; + } + } else { + // We're a simple {env_var_name}-style entry. + if (strcmp(argument_value, env_var_name) == 0) { + // We matched. + if (argument_index) + *argument_index = i; + return true; + } } + } - // We didn't find a match. - return false; + // We didn't find a match. + return false; } -size_t -Args::FindArgumentIndexForOption (Option *long_options, int long_options_index) -{ - char short_buffer[3]; - char long_buffer[255]; - ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val); - ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].definition->long_option); - size_t end = GetArgumentCount (); - size_t idx = 0; - while (idx < end) - { - if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0) - || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0)) - { - return idx; - } - ++idx; +size_t Args::FindArgumentIndexForOption(Option *long_options, + int long_options_index) { + char short_buffer[3]; + char long_buffer[255]; + ::snprintf(short_buffer, sizeof(short_buffer), "-%c", + long_options[long_options_index].val); + ::snprintf(long_buffer, sizeof(long_buffer), "--%s", + long_options[long_options_index].definition->long_option); + size_t end = GetArgumentCount(); + size_t idx = 0; + while (idx < end) { + if ((::strncmp(GetArgumentAtIndex(idx), short_buffer, + strlen(short_buffer)) == 0) || + (::strncmp(GetArgumentAtIndex(idx), long_buffer, strlen(long_buffer)) == + 0)) { + return idx; } + ++idx; + } - return end; + return end; } -bool -Args::IsPositionalArgument (const char *arg) -{ - if (arg == nullptr) - return false; - - bool is_positional = true; - const char *cptr = arg; - - if (cptr[0] == '%') - { - ++cptr; - while (isdigit (cptr[0])) - ++cptr; - if (cptr[0] != '\0') - is_positional = false; - } - else - is_positional = false; +bool Args::IsPositionalArgument(const char *arg) { + if (arg == nullptr) + return false; + + bool is_positional = true; + const char *cptr = arg; + + if (cptr[0] == '%') { + ++cptr; + while (isdigit(cptr[0])) + ++cptr; + if (cptr[0] != '\0') + is_positional = false; + } else + is_positional = false; - return is_positional; + return is_positional; } -void -Args::ParseAliasOptions (Options &options, - CommandReturnObject &result, - OptionArgVector *option_arg_vector, - std::string &raw_input_string) -{ - StreamString sstr; - int i; - Option *long_options = options.GetLongOptions(); - - if (long_options == nullptr) - { - result.AppendError ("invalid long options"); - result.SetStatus (eReturnStatusFailed); - return; +void Args::ParseAliasOptions(Options &options, CommandReturnObject &result, + OptionArgVector *option_arg_vector, + std::string &raw_input_string) { + StreamString sstr; + int i; + Option *long_options = options.GetLongOptions(); + + if (long_options == nullptr) { + result.AppendError("invalid long options"); + result.SetStatus(eReturnStatusFailed); + return; + } + + for (i = 0; long_options[i].definition != nullptr; ++i) { + if (long_options[i].flag == nullptr) { + sstr << (char)long_options[i].val; + switch (long_options[i].definition->option_has_arg) { + default: + case OptionParser::eNoArgument: + break; + case OptionParser::eRequiredArgument: + sstr << ":"; + break; + case OptionParser::eOptionalArgument: + sstr << "::"; + break; + } } - - for (i = 0; long_options[i].definition != nullptr; ++i) - { - if (long_options[i].flag == nullptr) - { - sstr << (char) long_options[i].val; - switch (long_options[i].definition->option_has_arg) - { - default: - case OptionParser::eNoArgument: - break; - case OptionParser::eRequiredArgument: - sstr << ":"; - break; - case OptionParser::eOptionalArgument: - sstr << "::"; - break; - } - } + } + + std::unique_lock lock; + OptionParser::Prepare(lock); + int val; + while (1) { + int long_options_index = -1; + val = + OptionParser::Parse(GetArgumentCount(), GetArgumentVector(), + sstr.GetData(), long_options, &long_options_index); + + if (val == -1) + break; + + if (val == '?') { + result.AppendError("unknown or ambiguous option"); + result.SetStatus(eReturnStatusFailed); + break; } - std::unique_lock lock; - OptionParser::Prepare(lock); - int val; - while (1) - { - int long_options_index = -1; - val = OptionParser::Parse (GetArgumentCount(), - GetArgumentVector(), - sstr.GetData(), - long_options, - &long_options_index); - - if (val == -1) - break; - - if (val == '?') - { - result.AppendError ("unknown or ambiguous option"); - result.SetStatus (eReturnStatusFailed); - break; - } + if (val == 0) + continue; - if (val == 0) - continue; - - options.OptionSeen (val); - - // Look up the long option index - if (long_options_index == -1) - { - for (int j = 0; - long_options[j].definition || long_options[j].flag || long_options[j].val; - ++j) - { - if (long_options[j].val == val) - { - long_options_index = j; - break; - } - } + options.OptionSeen(val); + + // Look up the long option index + if (long_options_index == -1) { + for (int j = 0; long_options[j].definition || long_options[j].flag || + long_options[j].val; + ++j) { + if (long_options[j].val == val) { + long_options_index = j; + break; } + } + } - // See if the option takes an argument, and see if one was supplied. - if (long_options_index >= 0) - { - StreamString option_str; - option_str.Printf ("-%c", val); - const OptionDefinition *def = long_options[long_options_index].definition; - int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg; - - switch (has_arg) - { - case OptionParser::eNoArgument: - option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - OptionArgValue (OptionParser::eNoArgument, ""))); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - break; - case OptionParser::eRequiredArgument: - if (OptionParser::GetOptionArgument() != nullptr) - { - option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - OptionArgValue (OptionParser::eRequiredArgument, - std::string (OptionParser::GetOptionArgument())))); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n", - option_str.GetData()); - result.SetStatus (eReturnStatusFailed); - } - break; - case OptionParser::eOptionalArgument: - if (OptionParser::GetOptionArgument() != nullptr) - { - option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - OptionArgValue (OptionParser::eOptionalArgument, - std::string (OptionParser::GetOptionArgument())))); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - OptionArgValue (OptionParser::eOptionalArgument, ""))); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - break; - default: - result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val); - result.SetStatus (eReturnStatusFailed); - break; - } + // See if the option takes an argument, and see if one was supplied. + if (long_options_index >= 0) { + StreamString option_str; + option_str.Printf("-%c", val); + const OptionDefinition *def = long_options[long_options_index].definition; + int has_arg = + (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg; + + switch (has_arg) { + case OptionParser::eNoArgument: + option_arg_vector->push_back(OptionArgPair( + std::string(option_str.GetData()), + OptionArgValue(OptionParser::eNoArgument, ""))); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + break; + case OptionParser::eRequiredArgument: + if (OptionParser::GetOptionArgument() != nullptr) { + option_arg_vector->push_back(OptionArgPair( + std::string(option_str.GetData()), + OptionArgValue(OptionParser::eRequiredArgument, + std::string(OptionParser::GetOptionArgument())))); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendErrorWithFormat( + "Option '%s' is missing argument specifier.\n", + option_str.GetData()); + result.SetStatus(eReturnStatusFailed); } - else - { - result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val); - result.SetStatus (eReturnStatusFailed); + break; + case OptionParser::eOptionalArgument: + if (OptionParser::GetOptionArgument() != nullptr) { + option_arg_vector->push_back(OptionArgPair( + std::string(option_str.GetData()), + OptionArgValue(OptionParser::eOptionalArgument, + std::string(OptionParser::GetOptionArgument())))); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + option_arg_vector->push_back( + OptionArgPair(std::string(option_str.GetData()), + OptionArgValue(OptionParser::eOptionalArgument, + ""))); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + break; + default: + result.AppendErrorWithFormat("error with options table; invalid value " + "in has_arg field for option '%c'.\n", + val); + result.SetStatus(eReturnStatusFailed); + break; + } + } else { + result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val); + result.SetStatus(eReturnStatusFailed); + } - if (long_options_index >= 0) - { - // Find option in the argument list; also see if it was supposed to take an argument and if one was - // supplied. Remove option (and argument, if given) from the argument list. Also remove them from - // the raw_input_string, if one was passed in. - size_t idx = FindArgumentIndexForOption (long_options, long_options_index); - if (idx < GetArgumentCount()) - { - if (raw_input_string.size() > 0) - { - const char *tmp_arg = GetArgumentAtIndex (idx); - size_t pos = raw_input_string.find (tmp_arg); - if (pos != std::string::npos) - raw_input_string.erase (pos, strlen (tmp_arg)); - } - ReplaceArgumentAtIndex (idx, ""); - if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument) - && (OptionParser::GetOptionArgument() != nullptr) - && (idx+1 < GetArgumentCount()) - && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0)) - { - if (raw_input_string.size() > 0) - { - const char *tmp_arg = GetArgumentAtIndex (idx+1); - size_t pos = raw_input_string.find (tmp_arg); - if (pos != std::string::npos) - raw_input_string.erase (pos, strlen (tmp_arg)); - } - ReplaceArgumentAtIndex (idx+1, ""); - } - } + if (long_options_index >= 0) { + // Find option in the argument list; also see if it was supposed to take + // an argument and if one was + // supplied. Remove option (and argument, if given) from the argument + // list. Also remove them from + // the raw_input_string, if one was passed in. + size_t idx = FindArgumentIndexForOption(long_options, long_options_index); + if (idx < GetArgumentCount()) { + if (raw_input_string.size() > 0) { + const char *tmp_arg = GetArgumentAtIndex(idx); + size_t pos = raw_input_string.find(tmp_arg); + if (pos != std::string::npos) + raw_input_string.erase(pos, strlen(tmp_arg)); } - - if (!result.Succeeded()) - break; + ReplaceArgumentAtIndex(idx, ""); + if ((long_options[long_options_index].definition->option_has_arg != + OptionParser::eNoArgument) && + (OptionParser::GetOptionArgument() != nullptr) && + (idx + 1 < GetArgumentCount()) && + (strcmp(OptionParser::GetOptionArgument(), + GetArgumentAtIndex(idx + 1)) == 0)) { + if (raw_input_string.size() > 0) { + const char *tmp_arg = GetArgumentAtIndex(idx + 1); + size_t pos = raw_input_string.find(tmp_arg); + if (pos != std::string::npos) + raw_input_string.erase(pos, strlen(tmp_arg)); + } + ReplaceArgumentAtIndex(idx + 1, ""); + } + } } + + if (!result.Succeeded()) + break; + } } -void -Args::ParseArgsForCompletion -( - Options &options, - OptionElementVector &option_element_vector, - uint32_t cursor_index -) -{ - StreamString sstr; - Option *long_options = options.GetLongOptions(); - option_element_vector.clear(); - - if (long_options == nullptr) - { - return; +void Args::ParseArgsForCompletion(Options &options, + OptionElementVector &option_element_vector, + uint32_t cursor_index) { + StreamString sstr; + Option *long_options = options.GetLongOptions(); + option_element_vector.clear(); + + if (long_options == nullptr) { + return; + } + + // Leading : tells getopt to return a : for a missing option argument AND + // to suppress error messages. + + sstr << ":"; + for (int i = 0; long_options[i].definition != nullptr; ++i) { + if (long_options[i].flag == nullptr) { + sstr << (char)long_options[i].val; + switch (long_options[i].definition->option_has_arg) { + default: + case OptionParser::eNoArgument: + break; + case OptionParser::eRequiredArgument: + sstr << ":"; + break; + case OptionParser::eOptionalArgument: + sstr << "::"; + break; + } } - - // Leading : tells getopt to return a : for a missing option argument AND - // to suppress error messages. - - sstr << ":"; - for (int i = 0; long_options[i].definition != nullptr; ++i) - { - if (long_options[i].flag == nullptr) - { - sstr << (char) long_options[i].val; - switch (long_options[i].definition->option_has_arg) - { - default: - case OptionParser::eNoArgument: - break; - case OptionParser::eRequiredArgument: - sstr << ":"; - break; - case OptionParser::eOptionalArgument: - sstr << "::"; - break; - } - } + } + + std::unique_lock lock; + OptionParser::Prepare(lock); + OptionParser::EnableError(false); + + int val; + const OptionDefinition *opt_defs = options.GetDefinitions(); + + // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the + // options to the front. + // So we have to build another Arg and pass that to OptionParser::Parse so it + // doesn't + // change the one we have. + + std::vector dummy_vec( + GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1); + + bool failed_once = false; + uint32_t dash_dash_pos = -1; + + while (1) { + bool missing_argument = false; + int long_options_index = -1; + + val = OptionParser::Parse( + dummy_vec.size() - 1, const_cast(&dummy_vec.front()), + sstr.GetData(), long_options, &long_options_index); + + if (val == -1) { + // When we're completing a "--" which is the last option on line, + if (failed_once) + break; + + failed_once = true; + + // If this is a bare "--" we mark it as such so we can complete it + // successfully later. + // Handling the "--" is a little tricky, since that may mean end of + // options or arguments, or the + // user might want to complete options by long name. I make this work by + // checking whether the + // cursor is in the "--" argument, and if so I assume we're completing the + // long option, otherwise + // I let it pass to OptionParser::Parse which will terminate the option + // parsing. + // Note, in either case we continue parsing the line so we can figure out + // what other options + // were passed. This will be useful when we come to restricting + // completions based on what other + // options we've seen on the line. + + if (static_cast(OptionParser::GetOptionIndex()) < + dummy_vec.size() - 1 && + (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) { + dash_dash_pos = OptionParser::GetOptionIndex() - 1; + if (static_cast(OptionParser::GetOptionIndex() - 1) == + cursor_index) { + option_element_vector.push_back( + OptionArgElement(OptionArgElement::eBareDoubleDash, + OptionParser::GetOptionIndex() - 1, + OptionArgElement::eBareDoubleDash)); + continue; + } else + break; + } else + break; + } else if (val == '?') { + option_element_vector.push_back( + OptionArgElement(OptionArgElement::eUnrecognizedArg, + OptionParser::GetOptionIndex() - 1, + OptionArgElement::eUnrecognizedArg)); + continue; + } else if (val == 0) { + continue; + } else if (val == ':') { + // This is a missing argument. + val = OptionParser::GetOptionErrorCause(); + missing_argument = true; } - std::unique_lock lock; - OptionParser::Prepare(lock); - OptionParser::EnableError(false); - - int val; - const OptionDefinition *opt_defs = options.GetDefinitions(); - - // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front. - // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't - // change the one we have. - - std::vector dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1); - - bool failed_once = false; - uint32_t dash_dash_pos = -1; - - while (1) - { - bool missing_argument = false; - int long_options_index = -1; - - val = OptionParser::Parse (dummy_vec.size() - 1, - const_cast(&dummy_vec.front()), - sstr.GetData(), - long_options, - &long_options_index); - - if (val == -1) - { - // When we're completing a "--" which is the last option on line, - if (failed_once) - break; - - failed_once = true; - - // If this is a bare "--" we mark it as such so we can complete it successfully later. - // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the - // user might want to complete options by long name. I make this work by checking whether the - // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise - // I let it pass to OptionParser::Parse which will terminate the option parsing. - // Note, in either case we continue parsing the line so we can figure out what other options - // were passed. This will be useful when we come to restricting completions based on what other - // options we've seen on the line. - - if (static_cast(OptionParser::GetOptionIndex()) < dummy_vec.size() - 1 - && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0)) - { - dash_dash_pos = OptionParser::GetOptionIndex() - 1; - if (static_cast(OptionParser::GetOptionIndex() - 1) == cursor_index) - { - option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1, - OptionArgElement::eBareDoubleDash)); - continue; - } - else - break; - } - else - break; - } - else if (val == '?') - { - option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1, - OptionArgElement::eUnrecognizedArg)); - continue; - } - else if (val == 0) - { - continue; - } - else if (val == ':') - { - // This is a missing argument. - val = OptionParser::GetOptionErrorCause(); - missing_argument = true; - } + ((Options *)&options)->OptionSeen(val); - ((Options *) &options)->OptionSeen (val); - - // Look up the long option index - if (long_options_index == -1) - { - for (int j = 0; - long_options[j].definition || long_options[j].flag || long_options[j].val; - ++j) - { - if (long_options[j].val == val) - { - long_options_index = j; - break; - } - } + // Look up the long option index + if (long_options_index == -1) { + for (int j = 0; long_options[j].definition || long_options[j].flag || + long_options[j].val; + ++j) { + if (long_options[j].val == val) { + long_options_index = j; + break; } + } + } - // See if the option takes an argument, and see if one was supplied. - if (long_options_index >= 0) - { - int opt_defs_index = -1; - for (int i = 0; ; i++) - { - if (opt_defs[i].short_option == 0) - break; - else if (opt_defs[i].short_option == val) - { - opt_defs_index = i; - break; - } - } - - const OptionDefinition *def = long_options[long_options_index].definition; - int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg; - switch (has_arg) - { - case OptionParser::eNoArgument: - option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0)); - break; - case OptionParser::eRequiredArgument: - if (OptionParser::GetOptionArgument() != nullptr) - { - int arg_index; - if (missing_argument) - arg_index = -1; - else - arg_index = OptionParser::GetOptionIndex() - 1; - - option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index)); - } - else - { - option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1)); - } - break; - case OptionParser::eOptionalArgument: - if (OptionParser::GetOptionArgument() != nullptr) - { - option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1)); - } - else - { - option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1)); - } - break; - default: - // The options table is messed up. Here we'll just continue - option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1, - OptionArgElement::eUnrecognizedArg)); - break; - } + // See if the option takes an argument, and see if one was supplied. + if (long_options_index >= 0) { + int opt_defs_index = -1; + for (int i = 0;; i++) { + if (opt_defs[i].short_option == 0) + break; + else if (opt_defs[i].short_option == val) { + opt_defs_index = i; + break; } - else - { - option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1, - OptionArgElement::eUnrecognizedArg)); + } + + const OptionDefinition *def = long_options[long_options_index].definition; + int has_arg = + (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg; + switch (has_arg) { + case OptionParser::eNoArgument: + option_element_vector.push_back(OptionArgElement( + opt_defs_index, OptionParser::GetOptionIndex() - 1, 0)); + break; + case OptionParser::eRequiredArgument: + if (OptionParser::GetOptionArgument() != nullptr) { + int arg_index; + if (missing_argument) + arg_index = -1; + else + arg_index = OptionParser::GetOptionIndex() - 1; + + option_element_vector.push_back(OptionArgElement( + opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index)); + } else { + option_element_vector.push_back(OptionArgElement( + opt_defs_index, OptionParser::GetOptionIndex() - 1, -1)); } + break; + case OptionParser::eOptionalArgument: + if (OptionParser::GetOptionArgument() != nullptr) { + option_element_vector.push_back(OptionArgElement( + opt_defs_index, OptionParser::GetOptionIndex() - 2, + OptionParser::GetOptionIndex() - 1)); + } else { + option_element_vector.push_back(OptionArgElement( + opt_defs_index, OptionParser::GetOptionIndex() - 2, + OptionParser::GetOptionIndex() - 1)); + } + break; + default: + // The options table is messed up. Here we'll just continue + option_element_vector.push_back( + OptionArgElement(OptionArgElement::eUnrecognizedArg, + OptionParser::GetOptionIndex() - 1, + OptionArgElement::eUnrecognizedArg)); + break; + } + } else { + option_element_vector.push_back( + OptionArgElement(OptionArgElement::eUnrecognizedArg, + OptionParser::GetOptionIndex() - 1, + OptionArgElement::eUnrecognizedArg)); } - - // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in - // the option_element_vector, but only if it is not after the "--". But it turns out that OptionParser::Parse just ignores - // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position. - // Note, a single quoted dash is not the same as a single dash... - - if ((static_cast(dash_dash_pos) == -1 || cursor_index < dash_dash_pos) - && m_args_quote_char[cursor_index] == '\0' - && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0) - { - option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index, - OptionArgElement::eBareDash)); - - } + } + + // Finally we have to handle the case where the cursor index points at a + // single "-". We want to mark that in + // the option_element_vector, but only if it is not after the "--". But it + // turns out that OptionParser::Parse just ignores + // an isolated "-". So we have to look it up by hand here. We only care if + // it is AT the cursor position. + // Note, a single quoted dash is not the same as a single dash... + + if ((static_cast(dash_dash_pos) == -1 || + cursor_index < dash_dash_pos) && + m_args_quote_char[cursor_index] == '\0' && + strcmp(GetArgumentAtIndex(cursor_index), "-") == 0) { + option_element_vector.push_back( + OptionArgElement(OptionArgElement::eBareDash, cursor_index, + OptionArgElement::eBareDash)); + } } -void -Args::EncodeEscapeSequences (const char *src, std::string &dst) -{ - dst.clear(); - if (src) - { - for (const char *p = src; *p != '\0'; ++p) - { - size_t non_special_chars = ::strcspn (p, "\\"); - if (non_special_chars > 0) - { - dst.append(p, non_special_chars); - p += non_special_chars; - if (*p == '\0') - break; +void Args::EncodeEscapeSequences(const char *src, std::string &dst) { + dst.clear(); + if (src) { + for (const char *p = src; *p != '\0'; ++p) { + size_t non_special_chars = ::strcspn(p, "\\"); + if (non_special_chars > 0) { + dst.append(p, non_special_chars); + p += non_special_chars; + if (*p == '\0') + break; + } + + if (*p == '\\') { + ++p; // skip the slash + switch (*p) { + case 'a': + dst.append(1, '\a'); + break; + case 'b': + dst.append(1, '\b'); + break; + case 'f': + dst.append(1, '\f'); + break; + case 'n': + dst.append(1, '\n'); + break; + case 'r': + dst.append(1, '\r'); + break; + case 't': + dst.append(1, '\t'); + break; + case 'v': + dst.append(1, '\v'); + break; + case '\\': + dst.append(1, '\\'); + break; + case '\'': + dst.append(1, '\''); + break; + case '"': + dst.append(1, '"'); + break; + case '0': + // 1 to 3 octal chars + { + // Make a string that can hold onto the initial zero char, + // up to 3 octal digits, and a terminating NULL. + char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'}; + + int i; + for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i) + oct_str[i] = p[i]; + + // We don't want to consume the last octal character since + // the main for loop will do this for us, so we advance p by + // one less than i (even if i is zero) + p += i - 1; + unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); + if (octal_value <= UINT8_MAX) { + dst.append(1, (char)octal_value); } - - if (*p == '\\') - { - ++p; // skip the slash - switch (*p) - { - case 'a' : dst.append(1, '\a'); break; - case 'b' : dst.append(1, '\b'); break; - case 'f' : dst.append(1, '\f'); break; - case 'n' : dst.append(1, '\n'); break; - case 'r' : dst.append(1, '\r'); break; - case 't' : dst.append(1, '\t'); break; - case 'v' : dst.append(1, '\v'); break; - case '\\': dst.append(1, '\\'); break; - case '\'': dst.append(1, '\''); break; - case '"' : dst.append(1, '"'); break; - case '0' : - // 1 to 3 octal chars - { - // Make a string that can hold onto the initial zero char, - // up to 3 octal digits, and a terminating NULL. - char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' }; - - int i; - for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) - oct_str[i] = p[i]; - - // We don't want to consume the last octal character since - // the main for loop will do this for us, so we advance p by - // one less than i (even if i is zero) - p += i - 1; - unsigned long octal_value = ::strtoul (oct_str, nullptr, 8); - if (octal_value <= UINT8_MAX) - { - dst.append(1, (char)octal_value); - } - } - break; - - case 'x': - // hex number in the format - if (isxdigit(p[1])) - { - ++p; // Skip the 'x' - - // Make a string that can hold onto two hex chars plus a - // NULL terminator - char hex_str[3] = { *p, '\0', '\0' }; - if (isxdigit(p[1])) - { - ++p; // Skip the first of the two hex chars - hex_str[1] = *p; - } - - unsigned long hex_value = strtoul (hex_str, nullptr, 16); - if (hex_value <= UINT8_MAX) - dst.append (1, (char)hex_value); - } - else - { - dst.append(1, 'x'); - } - break; - - default: - // Just desensitize any other character by just printing what - // came after the '\' - dst.append(1, *p); - break; - - } + } + break; + + case 'x': + // hex number in the format + if (isxdigit(p[1])) { + ++p; // Skip the 'x' + + // Make a string that can hold onto two hex chars plus a + // NULL terminator + char hex_str[3] = {*p, '\0', '\0'}; + if (isxdigit(p[1])) { + ++p; // Skip the first of the two hex chars + hex_str[1] = *p; } - } - } -} + unsigned long hex_value = strtoul(hex_str, nullptr, 16); + if (hex_value <= UINT8_MAX) + dst.append(1, (char)hex_value); + } else { + dst.append(1, 'x'); + } + break; -void -Args::ExpandEscapedCharacters (const char *src, std::string &dst) -{ - dst.clear(); - if (src) - { - for (const char *p = src; *p != '\0'; ++p) - { - if (isprint8(*p)) - dst.append(1, *p); - else - { - switch (*p) - { - case '\a': dst.append("\\a"); break; - case '\b': dst.append("\\b"); break; - case '\f': dst.append("\\f"); break; - case '\n': dst.append("\\n"); break; - case '\r': dst.append("\\r"); break; - case '\t': dst.append("\\t"); break; - case '\v': dst.append("\\v"); break; - case '\'': dst.append("\\'"); break; - case '"': dst.append("\\\""); break; - case '\\': dst.append("\\\\"); break; - default: - { - // Just encode as octal - dst.append("\\0"); - char octal_str[32]; - snprintf(octal_str, sizeof(octal_str), "%o", *p); - dst.append(octal_str); - } - break; - } - } + default: + // Just desensitize any other character by just printing what + // came after the '\' + dst.append(1, *p); + break; } + } } + } } -std::string -Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char) -{ - const char* chars_to_escape = nullptr; - switch (quote_char) - { - case '\0': - chars_to_escape = " \t\\'\"`"; - break; +void Args::ExpandEscapedCharacters(const char *src, std::string &dst) { + dst.clear(); + if (src) { + for (const char *p = src; *p != '\0'; ++p) { + if (isprint8(*p)) + dst.append(1, *p); + else { + switch (*p) { + case '\a': + dst.append("\\a"); + break; + case '\b': + dst.append("\\b"); + break; + case '\f': + dst.append("\\f"); + break; + case '\n': + dst.append("\\n"); + break; + case '\r': + dst.append("\\r"); + break; + case '\t': + dst.append("\\t"); + break; + case '\v': + dst.append("\\v"); + break; case '\'': - chars_to_escape = ""; - break; + dst.append("\\'"); + break; case '"': - chars_to_escape = "$\"`\\"; - break; - default: - assert(false && "Unhandled quote character"); - } - - std::string res; - res.reserve(arg.size()); - for (char c : arg) - { - if (::strchr(chars_to_escape, c)) - res.push_back('\\'); - res.push_back(c); + dst.append("\\\""); + break; + case '\\': + dst.append("\\\\"); + break; + default: { + // Just encode as octal + dst.append("\\0"); + char octal_str[32]; + snprintf(octal_str, sizeof(octal_str), "%o", *p); + dst.append(octal_str); + } break; + } + } } - return res; + } } +std::string Args::EscapeLLDBCommandArgument(const std::string &arg, + char quote_char) { + const char *chars_to_escape = nullptr; + switch (quote_char) { + case '\0': + chars_to_escape = " \t\\'\"`"; + break; + case '\'': + chars_to_escape = ""; + break; + case '"': + chars_to_escape = "$\"`\\"; + break; + default: + assert(false && "Unhandled quote character"); + } + + std::string res; + res.reserve(arg.size()); + for (char c : arg) { + if (::strchr(chars_to_escape, c)) + res.push_back('\\'); + res.push_back(c); + } + return res; +} diff --git a/lldb/source/Interpreter/CommandAlias.cpp b/lldb/source/Interpreter/CommandAlias.cpp index e796f292726..70b5394e158 100644 --- a/lldb/source/Interpreter/CommandAlias.cpp +++ b/lldb/source/Interpreter/CommandAlias.cpp @@ -1,4 +1,5 @@ -//===-- CommandAlias.cpp ------------------------------------------*- C++ -*-===// +//===-- CommandAlias.cpp ------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -20,291 +21,225 @@ using namespace lldb; using namespace lldb_private; -static bool -ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, - const char *options_args, - OptionArgVectorSP &option_arg_vector_sp) -{ - bool success = true; - OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); - - if (!options_args || (strlen (options_args) < 1)) - return true; - - std::string options_string (options_args); - Args args (options_args); - CommandReturnObject result; - // Check to see if the command being aliased can take any command options. - Options *options = cmd_obj_sp->GetOptions (); - if (options) - { - // See if any options were specified as part of the alias; if so, handle them appropriately. - ExecutionContext exe_ctx = - cmd_obj_sp->GetCommandInterpreter().GetExecutionContext(); - options->NotifyOptionParsingStarting(&exe_ctx); - args.Unshift ("dummy_arg"); - args.ParseAliasOptions (*options, result, option_arg_vector, options_string); - args.Shift (); - if (result.Succeeded()) - options->VerifyPartialOptions (result); - if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) - { - result.AppendError ("Unable to create requested alias.\n"); - return false; - } +static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp, + const char *options_args, + OptionArgVectorSP &option_arg_vector_sp) { + bool success = true; + OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); + + if (!options_args || (strlen(options_args) < 1)) + return true; + + std::string options_string(options_args); + Args args(options_args); + CommandReturnObject result; + // Check to see if the command being aliased can take any command options. + Options *options = cmd_obj_sp->GetOptions(); + if (options) { + // See if any options were specified as part of the alias; if so, handle + // them appropriately. + ExecutionContext exe_ctx = + cmd_obj_sp->GetCommandInterpreter().GetExecutionContext(); + options->NotifyOptionParsingStarting(&exe_ctx); + args.Unshift("dummy_arg"); + args.ParseAliasOptions(*options, result, option_arg_vector, options_string); + args.Shift(); + if (result.Succeeded()) + options->VerifyPartialOptions(result); + if (!result.Succeeded() && + result.GetStatus() != lldb::eReturnStatusStarted) { + result.AppendError("Unable to create requested alias.\n"); + return false; } - - if (!options_string.empty()) - { - if (cmd_obj_sp->WantsRawCommandString ()) - option_arg_vector->push_back (OptionArgPair ("", - OptionArgValue (-1, - options_string))); - else - { - const size_t argc = args.GetArgumentCount(); - for (size_t i = 0; i < argc; ++i) - if (strcmp (args.GetArgumentAtIndex (i), "") != 0) - option_arg_vector->push_back - (OptionArgPair ("", - OptionArgValue (-1, - std::string (args.GetArgumentAtIndex (i))))); - } + } + + if (!options_string.empty()) { + if (cmd_obj_sp->WantsRawCommandString()) + option_arg_vector->push_back( + OptionArgPair("", OptionArgValue(-1, options_string))); + else { + const size_t argc = args.GetArgumentCount(); + for (size_t i = 0; i < argc; ++i) + if (strcmp(args.GetArgumentAtIndex(i), "") != 0) + option_arg_vector->push_back(OptionArgPair( + "", + OptionArgValue(-1, std::string(args.GetArgumentAtIndex(i))))); } - - return success; -} - -CommandAlias::CommandAlias (CommandInterpreter &interpreter, - lldb::CommandObjectSP cmd_sp, - const char *options_args, - const char *name, - const char *help, - const char *syntax, - uint32_t flags) : - CommandObject(interpreter, - name, - help, - syntax, - flags), -m_underlying_command_sp(), -m_option_string(options_args ? options_args : ""), -m_option_args_sp(new OptionArgVector), -m_is_dashdash_alias(eLazyBoolCalculate), -m_did_set_help(false), -m_did_set_help_long(false) -{ - if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) - { - m_underlying_command_sp = cmd_sp; - for (int i = 0; - auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i); - i++) - { - m_arguments.push_back(*cmd_entry); - } - if (!help || !help[0]) - { - StreamString sstr; - StreamString translation_and_help; - GetAliasExpansion(sstr); - - translation_and_help.Printf ("(%s) %s", sstr.GetData(), GetUnderlyingCommand()->GetHelp()); - SetHelp(translation_and_help.GetData()); + } + + return success; +} + +CommandAlias::CommandAlias(CommandInterpreter &interpreter, + lldb::CommandObjectSP cmd_sp, + const char *options_args, const char *name, + const char *help, const char *syntax, uint32_t flags) + : CommandObject(interpreter, name, help, syntax, flags), + m_underlying_command_sp(), + m_option_string(options_args ? options_args : ""), + m_option_args_sp(new OptionArgVector), + m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false), + m_did_set_help_long(false) { + if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) { + m_underlying_command_sp = cmd_sp; + for (int i = 0; + auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i); + i++) { + m_arguments.push_back(*cmd_entry); + } + if (!help || !help[0]) { + StreamString sstr; + StreamString translation_and_help; + GetAliasExpansion(sstr); + + translation_and_help.Printf("(%s) %s", sstr.GetData(), + GetUnderlyingCommand()->GetHelp()); + SetHelp(translation_and_help.GetData()); + } + } +} + +bool CommandAlias::WantsRawCommandString() { + if (IsValid()) + return m_underlying_command_sp->WantsRawCommandString(); + return false; +} + +bool CommandAlias::WantsCompletion() { + if (IsValid()) + return m_underlying_command_sp->WantsCompletion(); + return false; +} + +int CommandAlias::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, bool &word_complete, + StringList &matches) { + if (IsValid()) + return m_underlying_command_sp->HandleCompletion( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + return -1; +} + +int CommandAlias::HandleArgumentCompletion( + Args &input, int &cursor_index, int &cursor_char_position, + OptionElementVector &opt_element_vector, int match_start_point, + int max_return_elements, bool &word_complete, StringList &matches) { + if (IsValid()) + return m_underlying_command_sp->HandleArgumentCompletion( + input, cursor_index, cursor_char_position, opt_element_vector, + match_start_point, max_return_elements, word_complete, matches); + return -1; +} + +Options *CommandAlias::GetOptions() { + if (IsValid()) + return m_underlying_command_sp->GetOptions(); + return nullptr; +} + +bool CommandAlias::Execute(const char *args_string, + CommandReturnObject &result) { + llvm_unreachable("CommandAlias::Execute is not to be called"); +} + +void CommandAlias::GetAliasExpansion(StreamString &help_string) { + const char *command_name = m_underlying_command_sp->GetCommandName(); + help_string.Printf("'%s", command_name); + + if (m_option_args_sp) { + OptionArgVector *options = m_option_args_sp.get(); + for (size_t i = 0; i < options->size(); ++i) { + OptionArgPair cur_option = (*options)[i]; + std::string opt = cur_option.first; + OptionArgValue value_pair = cur_option.second; + std::string value = value_pair.second; + if (opt.compare("") == 0) { + help_string.Printf(" %s", value.c_str()); + } else { + help_string.Printf(" %s", opt.c_str()); + if ((value.compare("") != 0) && + (value.compare("WantsRawCommandString(); - return false; -} - -bool -CommandAlias::WantsCompletion() -{ - if (IsValid()) - return m_underlying_command_sp->WantsCompletion(); - return false; -} - -int -CommandAlias::HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - if (IsValid()) - return m_underlying_command_sp->HandleCompletion(input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - return -1; -} + } -int -CommandAlias::HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - if (IsValid()) - return m_underlying_command_sp->HandleArgumentCompletion(input, - cursor_index, - cursor_char_position, - opt_element_vector, - match_start_point, - max_return_elements, - word_complete, - matches); - return -1; + help_string.Printf("'"); } -Options* -CommandAlias::GetOptions() -{ - if (IsValid()) - return m_underlying_command_sp->GetOptions(); - return nullptr; -} - -bool -CommandAlias::Execute(const char *args_string, CommandReturnObject &result) -{ - llvm_unreachable("CommandAlias::Execute is not to be called"); -} - -void -CommandAlias::GetAliasExpansion (StreamString &help_string) -{ - const char* command_name = m_underlying_command_sp->GetCommandName(); - help_string.Printf ("'%s", command_name); - - if (m_option_args_sp) - { - OptionArgVector *options = m_option_args_sp.get(); - for (size_t i = 0; i < options->size(); ++i) - { - OptionArgPair cur_option = (*options)[i]; - std::string opt = cur_option.first; - OptionArgValue value_pair = cur_option.second; - std::string value = value_pair.second; - if (opt.compare("") == 0) - { - help_string.Printf (" %s", value.c_str()); - } - else - { - help_string.Printf (" %s", opt.c_str()); - if ((value.compare ("") != 0) - && (value.compare ("" && !opt_arg.second.second.empty() && + llvm::StringRef(opt_arg.second.second).endswith("--")) { + m_is_dashdash_alias = eLazyBoolYes; + break; } + } + // if this is a nested alias, it may be adding arguments on top of an + // already dash-dash alias + if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias()) + m_is_dashdash_alias = + (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes + : eLazyBoolNo); } - - help_string.Printf ("'"); + } + return (m_is_dashdash_alias == eLazyBoolYes); } -bool -CommandAlias::IsDashDashCommand () -{ - if (m_is_dashdash_alias == eLazyBoolCalculate) - { - m_is_dashdash_alias = eLazyBoolNo; - if (IsValid()) - { - for (const OptionArgPair& opt_arg : *GetOptionArguments()) - { - if (opt_arg.first == "" && - !opt_arg.second.second.empty() && - llvm::StringRef(opt_arg.second.second).endswith("--")) - { - m_is_dashdash_alias = eLazyBoolYes; - break; - } - } - // if this is a nested alias, it may be adding arguments on top of an already dash-dash alias - if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias()) - m_is_dashdash_alias = (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes : eLazyBoolNo); - } - } - return (m_is_dashdash_alias == eLazyBoolYes); +bool CommandAlias::IsNestedAlias() { + if (GetUnderlyingCommand()) + return GetUnderlyingCommand()->IsAlias(); + return false; } -bool -CommandAlias::IsNestedAlias () -{ - if (GetUnderlyingCommand()) - return GetUnderlyingCommand()->IsAlias(); - return false; -} +std::pair CommandAlias::Desugar() { + auto underlying = GetUnderlyingCommand(); + if (!underlying) + return {nullptr, nullptr}; -std::pair -CommandAlias::Desugar () -{ - auto underlying = GetUnderlyingCommand(); - if (!underlying) - return {nullptr,nullptr}; - - if (underlying->IsAlias()) - { - auto desugared = ((CommandAlias*)underlying.get())->Desugar(); - auto options = GetOptionArguments(); - options->insert(options->begin(), desugared.second->begin(), desugared.second->end()); - return {desugared.first,options}; - } + if (underlying->IsAlias()) { + auto desugared = ((CommandAlias *)underlying.get())->Desugar(); + auto options = GetOptionArguments(); + options->insert(options->begin(), desugared.second->begin(), + desugared.second->end()); + return {desugared.first, options}; + } - return {underlying,GetOptionArguments()}; + return {underlying, GetOptionArguments()}; } -// allow CommandAlias objects to provide their own help, but fallback to the info +// allow CommandAlias objects to provide their own help, but fallback to the +// info // for the underlying command if no customization has been provided -void -CommandAlias::SetHelp (const char * str) -{ - this->CommandObject::SetHelp(str); - m_did_set_help = true; +void CommandAlias::SetHelp(const char *str) { + this->CommandObject::SetHelp(str); + m_did_set_help = true; } -void -CommandAlias::SetHelpLong (const char * str) -{ - this->CommandObject::SetHelpLong(str); - m_did_set_help_long = true; +void CommandAlias::SetHelpLong(const char *str) { + this->CommandObject::SetHelpLong(str); + m_did_set_help_long = true; } -const char* -CommandAlias::GetHelp () -{ - if (!m_cmd_help_short.empty() || m_did_set_help) - return m_cmd_help_short.c_str(); - if (IsValid()) - return m_underlying_command_sp->GetHelp(); - return nullptr; +const char *CommandAlias::GetHelp() { + if (!m_cmd_help_short.empty() || m_did_set_help) + return m_cmd_help_short.c_str(); + if (IsValid()) + return m_underlying_command_sp->GetHelp(); + return nullptr; } -const char* -CommandAlias::GetHelpLong () -{ - if (!m_cmd_help_long.empty() || m_did_set_help_long) - return m_cmd_help_long.c_str(); - if (IsValid()) - return m_underlying_command_sp->GetHelpLong(); - return nullptr; +const char *CommandAlias::GetHelpLong() { + if (!m_cmd_help_long.empty() || m_did_set_help_long) + return m_cmd_help_long.c_str(); + if (IsValid()) + return m_underlying_command_sp->GetHelpLong(); + return nullptr; } diff --git a/lldb/source/Interpreter/CommandHistory.cpp b/lldb/source/Interpreter/CommandHistory.cpp index ff87e528d36..09ee620a714 100644 --- a/lldb/source/Interpreter/CommandHistory.cpp +++ b/lldb/source/Interpreter/CommandHistory.cpp @@ -9,134 +9,101 @@ #include -#include "lldb/Interpreter/CommandHistory.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/CommandHistory.h" using namespace lldb; using namespace lldb_private; -CommandHistory::CommandHistory() : m_mutex(), m_history() -{} +CommandHistory::CommandHistory() : m_mutex(), m_history() {} -CommandHistory::~CommandHistory () -{} +CommandHistory::~CommandHistory() {} -size_t -CommandHistory::GetSize () const -{ - std::lock_guard guard(m_mutex); - return m_history.size(); +size_t CommandHistory::GetSize() const { + std::lock_guard guard(m_mutex); + return m_history.size(); } -bool -CommandHistory::IsEmpty () const -{ - std::lock_guard guard(m_mutex); - return m_history.empty(); +bool CommandHistory::IsEmpty() const { + std::lock_guard guard(m_mutex); + return m_history.empty(); } -const char* -CommandHistory::FindString (const char* input_str) const -{ - std::lock_guard guard(m_mutex); - if (!input_str) - return nullptr; - if (input_str[0] != g_repeat_char) - return nullptr; - if (input_str[1] == '-') - { - bool success; - size_t idx = StringConvert::ToUInt32 (input_str+2, 0, 0, &success); - if (!success) - return nullptr; - if (idx > m_history.size()) - return nullptr; - idx = m_history.size() - idx; - return m_history[idx].c_str(); - - } - else if (input_str[1] == g_repeat_char) - { - if (m_history.empty()) - return nullptr; - else - return m_history.back().c_str(); - } +const char *CommandHistory::FindString(const char *input_str) const { + std::lock_guard guard(m_mutex); + if (!input_str) + return nullptr; + if (input_str[0] != g_repeat_char) + return nullptr; + if (input_str[1] == '-') { + bool success; + size_t idx = StringConvert::ToUInt32(input_str + 2, 0, 0, &success); + if (!success) + return nullptr; + if (idx > m_history.size()) + return nullptr; + idx = m_history.size() - idx; + return m_history[idx].c_str(); + + } else if (input_str[1] == g_repeat_char) { + if (m_history.empty()) + return nullptr; else - { - bool success; - uint32_t idx = StringConvert::ToUInt32 (input_str+1, 0, 0, &success); - if (!success) - return nullptr; - if (idx >= m_history.size()) - return nullptr; - return m_history[idx].c_str(); - } + return m_history.back().c_str(); + } else { + bool success; + uint32_t idx = StringConvert::ToUInt32(input_str + 1, 0, 0, &success); + if (!success) + return nullptr; + if (idx >= m_history.size()) + return nullptr; + return m_history[idx].c_str(); + } } -const char* -CommandHistory::GetStringAtIndex (size_t idx) const -{ - std::lock_guard guard(m_mutex); - if (idx < m_history.size()) - return m_history[idx].c_str(); - return nullptr; +const char *CommandHistory::GetStringAtIndex(size_t idx) const { + std::lock_guard guard(m_mutex); + if (idx < m_history.size()) + return m_history[idx].c_str(); + return nullptr; } -const char* -CommandHistory::operator [] (size_t idx) const -{ - return GetStringAtIndex(idx); +const char *CommandHistory::operator[](size_t idx) const { + return GetStringAtIndex(idx); } -const char* -CommandHistory::GetRecentmostString () const -{ - std::lock_guard guard(m_mutex); - if (m_history.empty()) - return nullptr; - return m_history.back().c_str(); +const char *CommandHistory::GetRecentmostString() const { + std::lock_guard guard(m_mutex); + if (m_history.empty()) + return nullptr; + return m_history.back().c_str(); } -void -CommandHistory::AppendString (const std::string& str, - bool reject_if_dupe) -{ - std::lock_guard guard(m_mutex); - if (reject_if_dupe) - { - if (!m_history.empty()) - { - if (str == m_history.back()) - return; - } +void CommandHistory::AppendString(const std::string &str, bool reject_if_dupe) { + std::lock_guard guard(m_mutex); + if (reject_if_dupe) { + if (!m_history.empty()) { + if (str == m_history.back()) + return; } - m_history.push_back(std::string(str)); + } + m_history.push_back(std::string(str)); } -void -CommandHistory::Clear () -{ - std::lock_guard guard(m_mutex); - m_history.clear(); +void CommandHistory::Clear() { + std::lock_guard guard(m_mutex); + m_history.clear(); } -void -CommandHistory::Dump (Stream& stream, - size_t start_idx, - size_t stop_idx) const -{ - std::lock_guard guard(m_mutex); - stop_idx = std::min(stop_idx + 1, m_history.size()); - for (size_t counter = start_idx; - counter < stop_idx; - counter++) - { - const std::string hist_item = m_history[counter]; - if (!hist_item.empty()) - { - stream.Indent(); - stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str()); - } +void CommandHistory::Dump(Stream &stream, size_t start_idx, + size_t stop_idx) const { + std::lock_guard guard(m_mutex); + stop_idx = std::min(stop_idx + 1, m_history.size()); + for (size_t counter = start_idx; counter < stop_idx; counter++) { + const std::string hist_item = m_history[counter]; + if (!hist_item.empty()) { + stream.Indent(); + stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str()); } + } } diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 164881824fd..1bc5103793b 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include #include #include -#include #include "CommandObjectScript.h" #include "lldb/Interpreter/CommandObjectRegexCommand.h" @@ -18,11 +18,13 @@ #include "../Commands/CommandObjectArgs.h" #include "../Commands/CommandObjectBreakpoint.h" #include "../Commands/CommandObjectBugreport.h" +#include "../Commands/CommandObjectCommands.h" #include "../Commands/CommandObjectDisassemble.h" #include "../Commands/CommandObjectExpression.h" #include "../Commands/CommandObjectFrame.h" #include "../Commands/CommandObjectGUI.h" #include "../Commands/CommandObjectHelp.h" +#include "../Commands/CommandObjectLanguage.h" #include "../Commands/CommandObjectLog.h" #include "../Commands/CommandObjectMemory.h" #include "../Commands/CommandObjectPlatform.h" @@ -32,14 +34,12 @@ #include "../Commands/CommandObjectRegister.h" #include "../Commands/CommandObjectSettings.h" #include "../Commands/CommandObjectSource.h" -#include "../Commands/CommandObjectCommands.h" #include "../Commands/CommandObjectSyntax.h" #include "../Commands/CommandObjectTarget.h" #include "../Commands/CommandObjectThread.h" #include "../Commands/CommandObjectType.h" #include "../Commands/CommandObjectVersion.h" #include "../Commands/CommandObjectWatchpoint.h" -#include "../Commands/CommandObjectLanguage.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" @@ -59,19 +59,18 @@ #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/Property.h" - #include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/TargetList.h" +#include "lldb/Target/Thread.h" #include "lldb/Utility/CleanUp.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/Path.h" using namespace lldb; @@ -79,3235 +78,3020 @@ using namespace lldb_private; static const char *k_white_space = " \t\v"; -static PropertyDefinition -g_properties[] = -{ - { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, - { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, - { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, - { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." }, - { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr } -}; +static PropertyDefinition g_properties[] = { + {"expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, + nullptr, "If true, regular expression alias commands will show the " + "expanded command that will be executed. This can be used to " + "debug new regular expression alias commands."}, + {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + "If true, LLDB will prompt you before quitting if there are any live " + "processes being debugged. If false, LLDB will quit without asking in any " + "case."}, + {"stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, + nullptr, nullptr, "If true, LLDB will stop running a 'command source' " + "script upon encountering an error."}, + {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, + nullptr, + "If true, blank lines will be printed between between REPL submissions."}, + {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; -enum -{ - ePropertyExpandRegexAliases = 0, - ePropertyPromptOnQuit = 1, - ePropertyStopCmdSourceOnError = 2, - eSpaceReplPrompts = 3 +enum { + ePropertyExpandRegexAliases = 0, + ePropertyPromptOnQuit = 1, + ePropertyStopCmdSourceOnError = 2, + eSpaceReplPrompts = 3 }; -ConstString & -CommandInterpreter::GetStaticBroadcasterClass () -{ - static ConstString class_name ("lldb.commandInterpreter"); - return class_name; +ConstString &CommandInterpreter::GetStaticBroadcasterClass() { + static ConstString class_name("lldb.commandInterpreter"); + return class_name; } -CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution) - : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()), - Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), +CommandInterpreter::CommandInterpreter(Debugger &debugger, + ScriptLanguage script_language, + bool synchronous_execution) + : Broadcaster(debugger.GetBroadcasterManager(), + CommandInterpreter::GetStaticBroadcasterClass().AsCString()), + Properties(OptionValuePropertiesSP( + new OptionValueProperties(ConstString("interpreter")))), IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), - m_debugger(debugger), - m_synchronous_execution(synchronous_execution), - m_skip_lldbinit_files(false), - m_skip_app_init_files(false), - m_script_interpreter_sp(), - m_command_io_handler_sp(), - m_comment_char('#'), - m_batch_command_mode(false), - m_truncation_warning(eNoTruncation), - m_command_source_depth(0), - m_num_errors(0), - m_quit_requested(false), - m_stopped_for_crash(false) -{ - debugger.SetScriptLanguage (script_language); - SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); - SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); - SetEventName (eBroadcastBitQuitCommandReceived, "quit"); - CheckInWithManager (); - m_collection_sp->Initialize (g_properties); -} + m_debugger(debugger), m_synchronous_execution(synchronous_execution), + m_skip_lldbinit_files(false), m_skip_app_init_files(false), + m_script_interpreter_sp(), m_command_io_handler_sp(), m_comment_char('#'), + m_batch_command_mode(false), m_truncation_warning(eNoTruncation), + m_command_source_depth(0), m_num_errors(0), m_quit_requested(false), + m_stopped_for_crash(false) { + debugger.SetScriptLanguage(script_language); + SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit"); + SetEventName(eBroadcastBitResetPrompt, "reset-prompt"); + SetEventName(eBroadcastBitQuitCommandReceived, "quit"); + CheckInWithManager(); + m_collection_sp->Initialize(g_properties); +} + +bool CommandInterpreter::GetExpandRegexAliases() const { + const uint32_t idx = ePropertyExpandRegexAliases; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +bool CommandInterpreter::GetPromptOnQuit() const { + const uint32_t idx = ePropertyPromptOnQuit; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::SetPromptOnQuit(bool b) { + const uint32_t idx = ePropertyPromptOnQuit; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + +void CommandInterpreter::ResolveCommand(const char *command_line, + CommandReturnObject &result) { + std::string command = command_line; + if (ResolveCommandImpl(command, result) != nullptr) { + result.AppendMessageWithFormat("%s", command.c_str()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } +} + +bool CommandInterpreter::GetStopCmdSourceOnError() const { + const uint32_t idx = ePropertyStopCmdSourceOnError; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +bool CommandInterpreter::GetSpaceReplPrompts() const { + const uint32_t idx = eSpaceReplPrompts; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::Initialize() { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); + + CommandReturnObject result; + + LoadCommandDictionary(); + + // An alias arguments vector to reuse - reset it before use... + OptionArgVectorSP alias_arguments_vector_sp(new OptionArgVector); + + // Set up some initial aliases. + CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit", false); + if (cmd_obj_sp) { + AddAlias("q", cmd_obj_sp); + AddAlias("exit", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("_regexp-attach", false); + if (cmd_obj_sp) + AddAlias("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("process detach", false); + if (cmd_obj_sp) { + AddAlias("detach", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("process continue", false); + if (cmd_obj_sp) { + AddAlias("c", cmd_obj_sp); + AddAlias("continue", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("_regexp-break", false); + if (cmd_obj_sp) + AddAlias("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("_regexp-tbreak", false); + if (cmd_obj_sp) + AddAlias("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("thread step-inst", false); + if (cmd_obj_sp) { + AddAlias("stepi", cmd_obj_sp); + AddAlias("si", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("thread step-inst-over", false); + if (cmd_obj_sp) { + AddAlias("nexti", cmd_obj_sp); + AddAlias("ni", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("thread step-in", false); + if (cmd_obj_sp) { + AddAlias("s", cmd_obj_sp); + AddAlias("step", cmd_obj_sp); + CommandAlias *sif_alias = AddAlias( + "sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1"); + if (sif_alias) { + sif_alias->SetHelp("Step through the current block, stopping if you step " + "directly into a function whose name matches the " + "TargetFunctionName."); + sif_alias->SetSyntax("sif "); + } + } + + cmd_obj_sp = GetCommandSPExact("thread step-over", false); + if (cmd_obj_sp) { + AddAlias("n", cmd_obj_sp); + AddAlias("next", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("thread step-out", false); + if (cmd_obj_sp) { + AddAlias("finish", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("frame select", false); + if (cmd_obj_sp) { + AddAlias("f", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("thread select", false); + if (cmd_obj_sp) { + AddAlias("t", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("_regexp-jump", false); + if (cmd_obj_sp) { + AddAlias("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + AddAlias("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + } + + cmd_obj_sp = GetCommandSPExact("_regexp-list", false); + if (cmd_obj_sp) { + AddAlias("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + AddAlias("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + } + + cmd_obj_sp = GetCommandSPExact("_regexp-env", false); + if (cmd_obj_sp) + AddAlias("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("memory read", false); + if (cmd_obj_sp) + AddAlias("x", cmd_obj_sp); + + cmd_obj_sp = GetCommandSPExact("_regexp-up", false); + if (cmd_obj_sp) + AddAlias("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("_regexp-down", false); + if (cmd_obj_sp) + AddAlias("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("_regexp-display", false); + if (cmd_obj_sp) + AddAlias("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("disassemble", false); + if (cmd_obj_sp) + AddAlias("dis", cmd_obj_sp); + + cmd_obj_sp = GetCommandSPExact("disassemble", false); + if (cmd_obj_sp) + AddAlias("di", cmd_obj_sp); + + cmd_obj_sp = GetCommandSPExact("_regexp-undisplay", false); + if (cmd_obj_sp) + AddAlias("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("_regexp-bt", false); + if (cmd_obj_sp) + AddAlias("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + + cmd_obj_sp = GetCommandSPExact("target create", false); + if (cmd_obj_sp) + AddAlias("file", cmd_obj_sp); + + cmd_obj_sp = GetCommandSPExact("target modules", false); + if (cmd_obj_sp) + AddAlias("image", cmd_obj_sp); + + alias_arguments_vector_sp.reset(new OptionArgVector); + + cmd_obj_sp = GetCommandSPExact("expression", false); + if (cmd_obj_sp) { + AddAlias("p", cmd_obj_sp, "--")->SetHelpLong(""); + AddAlias("print", cmd_obj_sp, "--")->SetHelpLong(""); + AddAlias("call", cmd_obj_sp, "--")->SetHelpLong(""); + if (auto po = AddAlias("po", cmd_obj_sp, "-O --")) { + po->SetHelp("Evaluate an expression on the current thread. Displays any " + "returned value with formatting " + "controlled by the type's author."); + po->SetHelpLong(""); + } + AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong(""); + AddAlias("poarray", cmd_obj_sp, + "--object-description --element-count %1 --") + ->SetHelpLong(""); + } + + cmd_obj_sp = GetCommandSPExact("process kill", false); + if (cmd_obj_sp) { + AddAlias("kill", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("process launch", false); + if (cmd_obj_sp) { + alias_arguments_vector_sp.reset(new OptionArgVector); +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + AddAlias("r", cmd_obj_sp, "--"); + AddAlias("run", cmd_obj_sp, "--"); +#else +#if defined(__APPLE__) + std::string shell_option; + shell_option.append("--shell-expand-args"); + shell_option.append(" true"); + shell_option.append(" --"); + AddAlias("r", cmd_obj_sp, "--shell-expand-args true --"); + AddAlias("run", cmd_obj_sp, "--shell-expand-args true --"); +#else + StreamString defaultshell; + defaultshell.Printf("--shell=%s --", + HostInfo::GetDefaultShell().GetPath().c_str()); + AddAlias("r", cmd_obj_sp, defaultshell.GetData()); + AddAlias("run", cmd_obj_sp, defaultshell.GetData()); +#endif +#endif + } + + cmd_obj_sp = GetCommandSPExact("target symbols add", false); + if (cmd_obj_sp) { + AddAlias("add-dsym", cmd_obj_sp); + } + + cmd_obj_sp = GetCommandSPExact("breakpoint set", false); + if (cmd_obj_sp) { + AddAlias("rbreak", cmd_obj_sp, "--func-regex %1"); + } +} + +void CommandInterpreter::Clear() { + m_command_io_handler_sp.reset(); + + if (m_script_interpreter_sp) + m_script_interpreter_sp->Clear(); +} + +const char *CommandInterpreter::ProcessEmbeddedScriptCommands(const char *arg) { + // This function has not yet been implemented. + + // Look for any embedded script command + // If found, + // get interpreter object from the command dictionary, + // call execute_one_command on it, + // get the results as a string, + // substitute that string for current stuff. + + return arg; +} + +void CommandInterpreter::LoadCommandDictionary() { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); + + lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); + + m_command_dict["apropos"] = CommandObjectSP(new CommandObjectApropos(*this)); + m_command_dict["breakpoint"] = + CommandObjectSP(new CommandObjectMultiwordBreakpoint(*this)); + m_command_dict["bugreport"] = + CommandObjectSP(new CommandObjectMultiwordBugreport(*this)); + m_command_dict["command"] = + CommandObjectSP(new CommandObjectMultiwordCommands(*this)); + m_command_dict["disassemble"] = + CommandObjectSP(new CommandObjectDisassemble(*this)); + m_command_dict["expression"] = + CommandObjectSP(new CommandObjectExpression(*this)); + m_command_dict["frame"] = + CommandObjectSP(new CommandObjectMultiwordFrame(*this)); + m_command_dict["gui"] = CommandObjectSP(new CommandObjectGUI(*this)); + m_command_dict["help"] = CommandObjectSP(new CommandObjectHelp(*this)); + m_command_dict["log"] = CommandObjectSP(new CommandObjectLog(*this)); + m_command_dict["memory"] = CommandObjectSP(new CommandObjectMemory(*this)); + m_command_dict["platform"] = + CommandObjectSP(new CommandObjectPlatform(*this)); + m_command_dict["plugin"] = CommandObjectSP(new CommandObjectPlugin(*this)); + m_command_dict["process"] = + CommandObjectSP(new CommandObjectMultiwordProcess(*this)); + m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this)); + m_command_dict["register"] = + CommandObjectSP(new CommandObjectRegister(*this)); + m_command_dict["script"] = + CommandObjectSP(new CommandObjectScript(*this, script_language)); + m_command_dict["settings"] = + CommandObjectSP(new CommandObjectMultiwordSettings(*this)); + m_command_dict["source"] = + CommandObjectSP(new CommandObjectMultiwordSource(*this)); + m_command_dict["target"] = + CommandObjectSP(new CommandObjectMultiwordTarget(*this)); + m_command_dict["thread"] = + CommandObjectSP(new CommandObjectMultiwordThread(*this)); + m_command_dict["type"] = CommandObjectSP(new CommandObjectType(*this)); + m_command_dict["version"] = CommandObjectSP(new CommandObjectVersion(*this)); + m_command_dict["watchpoint"] = + CommandObjectSP(new CommandObjectMultiwordWatchpoint(*this)); + m_command_dict["language"] = + CommandObjectSP(new CommandObjectLanguage(*this)); + + const char *break_regexes[][2] = { + {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", + "breakpoint set --file '%1' --line %2"}, + {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, + {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, + {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, + {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", + "breakpoint set --name '%1'"}, + {"^(-.*)$", "breakpoint set %1"}, + {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", + "breakpoint set --name '%2' --shlib '%1'"}, + {"^\\&(.*[^[:space:]])[[:space:]]*$", + "breakpoint set --name '%1' --skip-prologue=0"}, + {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", + "breakpoint set --name '%1'"}}; + + size_t num_regexes = llvm::array_lengthof(break_regexes); + + std::unique_ptr break_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-break", + "Set a breakpoint using one of several shorthand formats.\n", + "\n" + "_regexp-break :\n" + " main.c:12 // Break at line 12 of " + "main.c\n\n" + "_regexp-break \n" + " 12 // Break at line 12 of current " + "file\n\n" + "_regexp-break 0x
\n" + " 0x1234000 // Break at address " + "0x1234000\n\n" + "_regexp-break \n" + " main // Break in 'main' after the " + "prologue\n\n" + "_regexp-break &\n" + " &main // Break at first instruction " + "in 'main'\n\n" + "_regexp-break `\n" + " libc.so`malloc // Break in 'malloc' from " + "'libc.so'\n\n" + "_regexp-break //\n" + " /break here/ // Break on source lines in " + "current file\n" + " // containing text 'break " + "here'.\n", + 2, CommandCompletions::eSymbolCompletion | + CommandCompletions::eSourceFileCompletion, + false)); + + if (break_regex_cmd_ap.get()) { + bool success = true; + for (size_t i = 0; i < num_regexes; i++) { + success = break_regex_cmd_ap->AddRegexCommand(break_regexes[i][0], + break_regexes[i][1]); + if (!success) + break; + } + success = + break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); + + if (success) { + CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); + m_command_dict[break_regex_cmd_sp->GetCommandName()] = break_regex_cmd_sp; + } + } + + std::unique_ptr tbreak_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-tbreak", + "Set a one-shot breakpoint using one of several shorthand formats.\n", + "\n" + "_regexp-break :\n" + " main.c:12 // Break at line 12 of " + "main.c\n\n" + "_regexp-break \n" + " 12 // Break at line 12 of current " + "file\n\n" + "_regexp-break 0x
\n" + " 0x1234000 // Break at address " + "0x1234000\n\n" + "_regexp-break \n" + " main // Break in 'main' after the " + "prologue\n\n" + "_regexp-break &\n" + " &main // Break at first instruction " + "in 'main'\n\n" + "_regexp-break `\n" + " libc.so`malloc // Break in 'malloc' from " + "'libc.so'\n\n" + "_regexp-break //\n" + " /break here/ // Break on source lines in " + "current file\n" + " // containing text 'break " + "here'.\n", + 2, CommandCompletions::eSymbolCompletion | + CommandCompletions::eSourceFileCompletion, + false)); + + if (tbreak_regex_cmd_ap.get()) { + bool success = true; + for (size_t i = 0; i < num_regexes; i++) { + // If you add a resultant command string longer than 1024 characters be + // sure to increase the size of this buffer. + char buffer[1024]; + int num_printed = + snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); + assert(num_printed < 1024); + UNUSED_IF_ASSERT_DISABLED(num_printed); + success = + tbreak_regex_cmd_ap->AddRegexCommand(break_regexes[i][0], buffer); + if (!success) + break; + } + success = + tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); + + if (success) { + CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); + m_command_dict[tbreak_regex_cmd_sp->GetCommandName()] = + tbreak_regex_cmd_sp; + } + } + + std::unique_ptr attach_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-attach", "Attach to process by ID or name.", + "_regexp-attach | ", 2, 0, false)); + if (attach_regex_cmd_ap.get()) { + if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", + "process attach --pid %1") && + attach_regex_cmd_ap->AddRegexCommand( + "^(-.*|.* -.*)$", "process attach %1") && // Any options that are + // specified get passed to + // 'process attach' + attach_regex_cmd_ap->AddRegexCommand("^(.+)$", + "process attach --name '%1'") && + attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) { + CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); + m_command_dict[attach_regex_cmd_sp->GetCommandName()] = + attach_regex_cmd_sp; + } + } + + std::unique_ptr down_regex_cmd_ap( + new CommandObjectRegexCommand(*this, "_regexp-down", + "Select a newer stack frame. Defaults to " + "moving one frame, a numeric argument can " + "specify an arbitrary number.", + "_regexp-down []", 2, 0, false)); + if (down_regex_cmd_ap.get()) { + if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && + down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", + "frame select -r -%1")) { + CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); + m_command_dict[down_regex_cmd_sp->GetCommandName()] = down_regex_cmd_sp; + } + } + + std::unique_ptr up_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-up", + "Select an older stack frame. Defaults to moving one " + "frame, a numeric argument can specify an arbitrary number.", + "_regexp-up []", 2, 0, false)); + if (up_regex_cmd_ap.get()) { + if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && + up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) { + CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); + m_command_dict[up_regex_cmd_sp->GetCommandName()] = up_regex_cmd_sp; + } + } + + std::unique_ptr display_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-display", + "Evaluate an expression at every stop (see 'help target stop-hook'.)", + "_regexp-display expression", 2, 0, false)); + if (display_regex_cmd_ap.get()) { + if (display_regex_cmd_ap->AddRegexCommand( + "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) { + CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); + m_command_dict[display_regex_cmd_sp->GetCommandName()] = + display_regex_cmd_sp; + } + } + + std::unique_ptr undisplay_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-undisplay", "Stop displaying expression at every " + "stop (specified by stop-hook index.)", + "_regexp-undisplay stop-hook-number", 2, 0, false)); + if (undisplay_regex_cmd_ap.get()) { + if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", + "target stop-hook delete %1")) { + CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); + m_command_dict[undisplay_regex_cmd_sp->GetCommandName()] = + undisplay_regex_cmd_sp; + } + } + + std::unique_ptr connect_gdb_remote_cmd_ap( + new CommandObjectRegexCommand( + *this, "gdb-remote", "Connect to a process via remote GDB server. " + "If no host is specifed, localhost is assumed.", + "gdb-remote [:]", 2, 0, false)); + if (connect_gdb_remote_cmd_ap.get()) { + if (connect_gdb_remote_cmd_ap->AddRegexCommand( + "^([^:]+:[[:digit:]]+)$", + "process connect --plugin gdb-remote connect://%1") && + connect_gdb_remote_cmd_ap->AddRegexCommand( + "^([[:digit:]]+)$", + "process connect --plugin gdb-remote connect://localhost:%1")) { + CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); + m_command_dict[command_sp->GetCommandName()] = command_sp; + } + } + + std::unique_ptr connect_kdp_remote_cmd_ap( + new CommandObjectRegexCommand( + *this, "kdp-remote", "Connect to a process via remote KDP server. " + "If no UDP port is specified, port 41139 is " + "assumed.", + "kdp-remote [:]", 2, 0, false)); + if (connect_kdp_remote_cmd_ap.get()) { + if (connect_kdp_remote_cmd_ap->AddRegexCommand( + "^([^:]+:[[:digit:]]+)$", + "process connect --plugin kdp-remote udp://%1") && + connect_kdp_remote_cmd_ap->AddRegexCommand( + "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) { + CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); + m_command_dict[command_sp->GetCommandName()] = command_sp; + } + } + + std::unique_ptr bt_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-bt", + "Show the current thread's call stack. Any numeric argument " + "displays at most that many " + "frames. The argument 'all' displays all threads.", + "bt [ | all]", 2, 0, false)); + if (bt_regex_cmd_ap.get()) { + // accept but don't document "bt -c " -- before bt was a regex + // command if you wanted to backtrace + // three frames you would do "bt -c 3" but the intention is to have this + // emulate the gdb "bt" command and + // so now "bt 3" is the preferred form, in line with gdb. + if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", + "thread backtrace -c %1") && + bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", + "thread backtrace -c %1") && + bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && + bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) { + CommandObjectSP command_sp(bt_regex_cmd_ap.release()); + m_command_dict[command_sp->GetCommandName()] = command_sp; + } + } + + std::unique_ptr list_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-list", + "List relevant source code using one of several shorthand formats.", + "\n" + "_regexp-list : // List around specific file/line\n" + "_regexp-list // List current file around specified " + "line\n" + "_regexp-list // List specified function\n" + "_regexp-list 0x
// List around specified address\n" + "_regexp-list -[] // List previous lines\n" + "_regexp-list // List subsequent lines", + 2, CommandCompletions::eSourceFileCompletion, false)); + if (list_regex_cmd_ap.get()) { + if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", + "source list --line %1") && + list_regex_cmd_ap->AddRegexCommand( + "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]" + "]*$", + "source list --file '%1' --line %2") && + list_regex_cmd_ap->AddRegexCommand( + "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", + "source list --address %1") && + list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", + "source list --reverse") && + list_regex_cmd_ap->AddRegexCommand( + "^-([[:digit:]]+)[[:space:]]*$", + "source list --reverse --count %1") && + list_regex_cmd_ap->AddRegexCommand("^(.+)$", + "source list --name \"%1\"") && + list_regex_cmd_ap->AddRegexCommand("^$", "source list")) { + CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); + m_command_dict[list_regex_cmd_sp->GetCommandName()] = list_regex_cmd_sp; + } + } + + std::unique_ptr env_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-env", + "Shorthand for viewing and setting environment variables.", + "\n" + "_regexp-env // Show enrivonment\n" + "_regexp-env = // Set an environment variable", + 2, 0, false)); + if (env_regex_cmd_ap.get()) { + if (env_regex_cmd_ap->AddRegexCommand("^$", + "settings show target.env-vars") && + env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", + "settings set target.env-vars %1")) { + CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); + m_command_dict[env_regex_cmd_sp->GetCommandName()] = env_regex_cmd_sp; + } + } + + std::unique_ptr jump_regex_cmd_ap( + new CommandObjectRegexCommand( + *this, "_regexp-jump", "Set the program counter to a new address.", + "\n" + "_regexp-jump \n" + "_regexp-jump + | -\n" + "_regexp-jump :\n" + "_regexp-jump *\n", + 2, 0, false)); + if (jump_regex_cmd_ap.get()) { + if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", + "thread jump --addr %1") && + jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", + "thread jump --line %1") && + jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", + "thread jump --file %1 --line %2") && + jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", + "thread jump --by %1")) { + CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release()); + m_command_dict[jump_regex_cmd_sp->GetCommandName()] = jump_regex_cmd_sp; + } + } +} + +int CommandInterpreter::GetCommandNamesMatchingPartialString( + const char *cmd_str, bool include_aliases, StringList &matches) { + AddNamesMatchingPartialString(m_command_dict, cmd_str, matches); + + if (include_aliases) { + AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches); + } + + return matches.GetSize(); +} + +CommandObjectSP CommandInterpreter::GetCommandSP(const char *cmd_cstr, + bool include_aliases, + bool exact, + StringList *matches) { + CommandObject::CommandMap::iterator pos; + CommandObjectSP command_sp; + + std::string cmd(cmd_cstr); + + if (HasCommands()) { + pos = m_command_dict.find(cmd); + if (pos != m_command_dict.end()) + command_sp = pos->second; + } -bool -CommandInterpreter::GetExpandRegexAliases () const -{ - const uint32_t idx = ePropertyExpandRegexAliases; - return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); -} + if (include_aliases && HasAliases()) { + auto alias_pos = m_alias_dict.find(cmd); + if (alias_pos != m_alias_dict.end()) + command_sp = alias_pos->second; + } -bool -CommandInterpreter::GetPromptOnQuit () const -{ - const uint32_t idx = ePropertyPromptOnQuit; - return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); -} + if (HasUserCommands()) { + pos = m_user_dict.find(cmd); + if (pos != m_user_dict.end()) + command_sp = pos->second; + } -void -CommandInterpreter::SetPromptOnQuit (bool b) -{ - const uint32_t idx = ePropertyPromptOnQuit; - m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, idx, b); -} + if (!exact && !command_sp) { + // We will only get into here if we didn't find any exact matches. -void -CommandInterpreter::ResolveCommand(const char *command_line, CommandReturnObject &result) -{ - std::string command = command_line; - if (ResolveCommandImpl(command, result) != nullptr) { - result.AppendMessageWithFormat("%s", command.c_str()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } -} + CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; + StringList local_matches; + if (matches == nullptr) + matches = &local_matches; -bool -CommandInterpreter::GetStopCmdSourceOnError () const -{ - const uint32_t idx = ePropertyStopCmdSourceOnError; - return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); -} + unsigned int num_cmd_matches = 0; + unsigned int num_alias_matches = 0; + unsigned int num_user_matches = 0; -bool -CommandInterpreter::GetSpaceReplPrompts () const -{ - const uint32_t idx = eSpaceReplPrompts; - return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); -} + // Look through the command dictionaries one by one, and if we get only one + // match from any of + // them in toto, then return that, otherwise return an empty CommandObjectSP + // and the list of matches. -void -CommandInterpreter::Initialize () -{ - Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); - - CommandReturnObject result; - - LoadCommandDictionary (); - - // An alias arguments vector to reuse - reset it before use... - OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); - - // Set up some initial aliases. - CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); - if (cmd_obj_sp) - { - AddAlias ("q", cmd_obj_sp); - AddAlias ("exit", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); - if (cmd_obj_sp) - AddAlias ("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - - cmd_obj_sp = GetCommandSPExact ("process detach",false); - if (cmd_obj_sp) - { - AddAlias ("detach", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("process continue", false); - if (cmd_obj_sp) - { - AddAlias ("c", cmd_obj_sp); - AddAlias ("continue", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); - if (cmd_obj_sp) - AddAlias ("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - - cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); - if (cmd_obj_sp) - AddAlias ("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - - cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); - if (cmd_obj_sp) - { - AddAlias ("stepi", cmd_obj_sp); - AddAlias ("si", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); - if (cmd_obj_sp) - { - AddAlias ("nexti", cmd_obj_sp); - AddAlias ("ni", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("thread step-in", false); - if (cmd_obj_sp) - { - AddAlias ("s", cmd_obj_sp); - AddAlias ("step", cmd_obj_sp); - CommandAlias *sif_alias = AddAlias ("sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1"); - if (sif_alias) - { - sif_alias->SetHelp("Step through the current block, stopping if you step " - "directly into a function whose name matches the TargetFunctionName."); - sif_alias->SetSyntax("sif "); - } + if (HasCommands()) { + num_cmd_matches = + AddNamesMatchingPartialString(m_command_dict, cmd_cstr, *matches); } - cmd_obj_sp = GetCommandSPExact ("thread step-over", false); - if (cmd_obj_sp) - { - AddAlias ("n", cmd_obj_sp); - AddAlias ("next", cmd_obj_sp); + if (num_cmd_matches == 1) { + cmd.assign(matches->GetStringAtIndex(0)); + pos = m_command_dict.find(cmd); + if (pos != m_command_dict.end()) + real_match_sp = pos->second; } - cmd_obj_sp = GetCommandSPExact ("thread step-out", false); - if (cmd_obj_sp) - { - AddAlias ("finish", cmd_obj_sp); + if (include_aliases && HasAliases()) { + num_alias_matches = + AddNamesMatchingPartialString(m_alias_dict, cmd_cstr, *matches); } - cmd_obj_sp = GetCommandSPExact ("frame select", false); - if (cmd_obj_sp) - { - AddAlias ("f", cmd_obj_sp); + if (num_alias_matches == 1) { + cmd.assign(matches->GetStringAtIndex(num_cmd_matches)); + auto alias_pos = m_alias_dict.find(cmd); + if (alias_pos != m_alias_dict.end()) + alias_match_sp = alias_pos->second; } - cmd_obj_sp = GetCommandSPExact ("thread select", false); - if (cmd_obj_sp) - { - AddAlias ("t", cmd_obj_sp); + if (HasUserCommands()) { + num_user_matches = + AddNamesMatchingPartialString(m_user_dict, cmd_cstr, *matches); } - cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false); - if (cmd_obj_sp) - { - AddAlias ("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - AddAlias ("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - } + if (num_user_matches == 1) { + cmd.assign( + matches->GetStringAtIndex(num_cmd_matches + num_alias_matches)); - cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); - if (cmd_obj_sp) - { - AddAlias ("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - AddAlias ("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + pos = m_user_dict.find(cmd); + if (pos != m_user_dict.end()) + user_match_sp = pos->second; } - cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); - if (cmd_obj_sp) - AddAlias ("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + // If we got exactly one match, return that, otherwise return the match + // list. - cmd_obj_sp = GetCommandSPExact ("memory read", false); - if (cmd_obj_sp) - AddAlias ("x", cmd_obj_sp); + if (num_user_matches + num_cmd_matches + num_alias_matches == 1) { + if (num_cmd_matches) + return real_match_sp; + else if (num_alias_matches) + return alias_match_sp; + else + return user_match_sp; + } + } else if (matches && command_sp) { + matches->AppendString(cmd_cstr); + } - cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); - if (cmd_obj_sp) - AddAlias ("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + return command_sp; +} - cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); - if (cmd_obj_sp) - AddAlias ("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); +bool CommandInterpreter::AddCommand(const char *name, + const lldb::CommandObjectSP &cmd_sp, + bool can_replace) { + if (cmd_sp.get()) + assert((this == &cmd_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); + + if (name && name[0]) { + std::string name_sstr(name); + bool found = (m_command_dict.find(name_sstr) != m_command_dict.end()); + if (found && !can_replace) + return false; + if (found && m_command_dict[name_sstr]->IsRemovable() == false) + return false; + m_command_dict[name_sstr] = cmd_sp; + return true; + } + return false; +} + +bool CommandInterpreter::AddUserCommand(std::string name, + const lldb::CommandObjectSP &cmd_sp, + bool can_replace) { + if (cmd_sp.get()) + assert((this == &cmd_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); + + if (!name.empty()) { + const char *name_cstr = name.c_str(); + + // do not allow replacement of internal commands + if (CommandExists(name_cstr)) { + if (can_replace == false) + return false; + if (m_command_dict[name]->IsRemovable() == false) + return false; + } - cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); - if (cmd_obj_sp) - AddAlias ("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); - - cmd_obj_sp = GetCommandSPExact ("disassemble", false); - if (cmd_obj_sp) - AddAlias ("dis", cmd_obj_sp); + if (UserCommandExists(name_cstr)) { + if (can_replace == false) + return false; + if (m_user_dict[name]->IsRemovable() == false) + return false; + } - cmd_obj_sp = GetCommandSPExact ("disassemble", false); - if (cmd_obj_sp) - AddAlias ("di", cmd_obj_sp); + m_user_dict[name] = cmd_sp; + return true; + } + return false; +} +CommandObjectSP CommandInterpreter::GetCommandSPExact(const char *cmd_cstr, + bool include_aliases) { + Args cmd_words(cmd_cstr); // Break up the command string into words, in case + // it's a multi-word command. + CommandObjectSP ret_val; // Possibly empty return value. + if (cmd_cstr == nullptr) + return ret_val; - cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); - if (cmd_obj_sp) - AddAlias ("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); + if (cmd_words.GetArgumentCount() == 1) + return GetCommandSP(cmd_cstr, include_aliases, true, nullptr); + else { + // We have a multi-word command (seemingly), so we need to do more work. + // First, get the cmd_obj_sp for the first word in the command. + CommandObjectSP cmd_obj_sp = GetCommandSP(cmd_words.GetArgumentAtIndex(0), + include_aliases, true, nullptr); + if (cmd_obj_sp.get() != nullptr) { + // Loop through the rest of the words in the command (everything passed in + // was supposed to be part of a + // command name), and find the appropriate sub-command SP for each command + // word.... + size_t end = cmd_words.GetArgumentCount(); + for (size_t j = 1; j < end; ++j) { + if (cmd_obj_sp->IsMultiwordObject()) { + cmd_obj_sp = + cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(j)); + if (cmd_obj_sp.get() == nullptr) + // The sub-command name was invalid. Fail and return the empty + // 'ret_val'. + return ret_val; + } else + // We have more words in the command name, but we don't have a + // multiword object. Fail and return + // empty 'ret_val'. + return ret_val; + } + // We successfully looped through all the command words and got valid + // command objects for them. Assign the + // last object retrieved to 'ret_val'. + ret_val = cmd_obj_sp; + } + } + return ret_val; +} + +CommandObject *CommandInterpreter::GetCommandObjectExact(const char *cmd_cstr, + bool include_aliases) { + return GetCommandSPExact(cmd_cstr, include_aliases).get(); +} + +CommandObject *CommandInterpreter::GetCommandObject(const char *cmd_cstr, + StringList *matches) { + CommandObject *command_obj = + GetCommandSP(cmd_cstr, false, true, matches).get(); + + // If we didn't find an exact match to the command string in the commands, + // look in + // the aliases. + + if (command_obj) + return command_obj; + + command_obj = GetCommandSP(cmd_cstr, true, true, matches).get(); + + if (command_obj) + return command_obj; + + // If there wasn't an exact match then look for an inexact one in just the + // commands + command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get(); + + // Finally, if there wasn't an inexact match among the commands, look for an + // inexact + // match in both the commands and aliases. + + if (command_obj) { + if (matches) + matches->AppendString(command_obj->GetCommandName()); + return command_obj; + } + + return GetCommandSP(cmd_cstr, true, false, matches).get(); +} + +bool CommandInterpreter::CommandExists(const char *cmd) { + return m_command_dict.find(cmd) != m_command_dict.end(); +} + +bool CommandInterpreter::GetAliasFullName(const char *cmd, + std::string &full_name) { + bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); + if (exact_match) { + full_name.assign(cmd); + return exact_match; + } else { + StringList matches; + size_t num_alias_matches; + num_alias_matches = + AddNamesMatchingPartialString(m_alias_dict, cmd, matches); + if (num_alias_matches == 1) { + // Make sure this isn't shadowing a command in the regular command space: + StringList regular_matches; + const bool include_aliases = false; + const bool exact = false; + CommandObjectSP cmd_obj_sp( + GetCommandSP(cmd, include_aliases, exact, ®ular_matches)); + if (cmd_obj_sp || regular_matches.GetSize() > 0) + return false; + else { + full_name.assign(matches.GetStringAtIndex(0)); + return true; + } + } else + return false; + } +} - cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); - if (cmd_obj_sp) - AddAlias ("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax()); +bool CommandInterpreter::AliasExists(const char *cmd) { + return m_alias_dict.find(cmd) != m_alias_dict.end(); +} + +bool CommandInterpreter::UserCommandExists(const char *cmd) { + return m_user_dict.find(cmd) != m_user_dict.end(); +} + +CommandAlias * +CommandInterpreter::AddAlias(const char *alias_name, + lldb::CommandObjectSP &command_obj_sp, + const char *args_string) { + if (command_obj_sp.get()) + assert((this == &command_obj_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); - cmd_obj_sp = GetCommandSPExact ("target create", false); - if (cmd_obj_sp) - AddAlias ("file", cmd_obj_sp); + std::unique_ptr command_alias_up( + new CommandAlias(*this, command_obj_sp, args_string, alias_name)); - cmd_obj_sp = GetCommandSPExact ("target modules", false); - if (cmd_obj_sp) - AddAlias ("image", cmd_obj_sp); + if (command_alias_up && command_alias_up->IsValid()) { + m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get()); + return command_alias_up.release(); + } + return nullptr; +} - alias_arguments_vector_sp.reset(new OptionArgVector); +bool CommandInterpreter::RemoveAlias(const char *alias_name) { + auto pos = m_alias_dict.find(alias_name); + if (pos != m_alias_dict.end()) { + m_alias_dict.erase(pos); + return true; + } + return false; +} - cmd_obj_sp = GetCommandSPExact ("expression", false); - if (cmd_obj_sp) - { - AddAlias ("p", cmd_obj_sp, "--")->SetHelpLong(""); - AddAlias ("print", cmd_obj_sp, "--")->SetHelpLong(""); - AddAlias ("call", cmd_obj_sp, "--")->SetHelpLong(""); - if (auto po = AddAlias ("po", cmd_obj_sp, "-O --")) - { - po->SetHelp("Evaluate an expression on the current thread. Displays any returned value with formatting " - "controlled by the type's author."); - po->SetHelpLong(""); - } - AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong(""); - AddAlias("poarray", cmd_obj_sp, "--object-description --element-count %1 --")->SetHelpLong(""); - } - - cmd_obj_sp = GetCommandSPExact ("process kill", false); - if (cmd_obj_sp) - { - AddAlias ("kill", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("process launch", false); - if (cmd_obj_sp) - { - alias_arguments_vector_sp.reset (new OptionArgVector); -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - AddAlias ("r", cmd_obj_sp, "--"); - AddAlias ("run", cmd_obj_sp, "--"); -#else - #if defined(__APPLE__) - std::string shell_option; - shell_option.append("--shell-expand-args"); - shell_option.append(" true"); - shell_option.append(" --"); - AddAlias ("r", cmd_obj_sp, "--shell-expand-args true --"); - AddAlias ("run", cmd_obj_sp, "--shell-expand-args true --"); - #else - StreamString defaultshell; - defaultshell.Printf("--shell=%s --", HostInfo::GetDefaultShell().GetPath().c_str()); - AddAlias ("r", cmd_obj_sp, defaultshell.GetData()); - AddAlias ("run", cmd_obj_sp, defaultshell.GetData()); - #endif -#endif - } - - cmd_obj_sp = GetCommandSPExact ("target symbols add", false); - if (cmd_obj_sp) - { - AddAlias ("add-dsym", cmd_obj_sp); - } - - cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); - if (cmd_obj_sp) - { - AddAlias ("rbreak", cmd_obj_sp, "--func-regex %1"); +bool CommandInterpreter::RemoveCommand(const char *cmd) { + auto pos = m_command_dict.find(cmd); + if (pos != m_command_dict.end()) { + if (pos->second->IsRemovable()) { + // Only regular expression objects or python commands are removable + m_command_dict.erase(pos); + return true; } + } + return false; } - -void -CommandInterpreter::Clear() -{ - m_command_io_handler_sp.reset(); - - if (m_script_interpreter_sp) - m_script_interpreter_sp->Clear(); +bool CommandInterpreter::RemoveUser(const char *alias_name) { + CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); + if (pos != m_user_dict.end()) { + m_user_dict.erase(pos); + return true; + } + return false; } -const char * -CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) -{ - // This function has not yet been implemented. - - // Look for any embedded script command - // If found, - // get interpreter object from the command dictionary, - // call execute_one_command on it, - // get the results as a string, - // substitute that string for current stuff. +void CommandInterpreter::GetHelp(CommandReturnObject &result, + uint32_t cmd_types) { + const char *help_prologue = GetDebugger().GetIOHandlerHelpPrologue(); + if (help_prologue != NULL) { + OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue); + } - return arg; -} + CommandObject::CommandMap::const_iterator pos; + size_t max_len = FindLongestCommandWord(m_command_dict); + if ((cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin) { + result.AppendMessage("Debugger commands:"); + result.AppendMessage(""); -void -CommandInterpreter::LoadCommandDictionary () -{ - Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); - - lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); - - m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); - m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); - m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this)); - m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); - m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); - m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); - m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); - m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this)); - m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); - m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); - m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); - m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); - m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); - m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); - m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); - m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); - m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); - m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); - m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); - m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); - m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); - m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); - m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); - m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); - m_command_dict["language"] = CommandObjectSP (new CommandObjectLanguage(*this)); - - const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, - {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, - {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, - {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, - {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, - {"^(-.*)$", "breakpoint set %1"}, - {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, - {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, - {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}}; - - size_t num_regexes = llvm::array_lengthof(break_regexes); - - std::unique_ptr break_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-break", "Set a breakpoint using one of several shorthand formats.\n", - "\n" - "_regexp-break :\n" - " main.c:12 // Break at line 12 of main.c\n\n" - "_regexp-break \n" - " 12 // Break at line 12 of current file\n\n" - "_regexp-break 0x
\n" - " 0x1234000 // Break at address 0x1234000\n\n" - "_regexp-break \n" - " main // Break in 'main' after the prologue\n\n" - "_regexp-break &\n" - " &main // Break at first instruction in 'main'\n\n" - "_regexp-break `\n" - " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n" - "_regexp-break //\n" - " /break here/ // Break on source lines in current file\n" - " // containing text 'break here'.\n", - 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false)); - - if (break_regex_cmd_ap.get()) - { - bool success = true; - for (size_t i = 0; i < num_regexes; i++) - { - success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); - if (!success) - break; - } - success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); + for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) { + if (!(cmd_types & eCommandTypesHidden) && + (pos->first.compare(0, 1, "_") == 0)) + continue; - if (success) - { - CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); - m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; - } + OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(), + "--", pos->second->GetHelp(), max_len); } + result.AppendMessage(""); + } - std::unique_ptr tbreak_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-tbreak", "Set a one-shot breakpoint using one of several shorthand formats.\n", - "\n" - "_regexp-break :\n" - " main.c:12 // Break at line 12 of main.c\n\n" - "_regexp-break \n" - " 12 // Break at line 12 of current file\n\n" - "_regexp-break 0x
\n" - " 0x1234000 // Break at address 0x1234000\n\n" - "_regexp-break \n" - " main // Break in 'main' after the prologue\n\n" - "_regexp-break &\n" - " &main // Break at first instruction in 'main'\n\n" - "_regexp-break `\n" - " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n" - "_regexp-break //\n" - " /break here/ // Break on source lines in current file\n" - " // containing text 'break here'.\n", - 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false)); - - if (tbreak_regex_cmd_ap.get()) - { - bool success = true; - for (size_t i = 0; i < num_regexes; i++) - { - // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. - char buffer[1024]; - int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); - assert (num_printed < 1024); - UNUSED_IF_ASSERT_DISABLED(num_printed); - success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); - if (!success) - break; - } - success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); + if (!m_alias_dict.empty() && + ((cmd_types & eCommandTypesAliases) == eCommandTypesAliases)) { + result.AppendMessageWithFormat( + "Current command abbreviations " + "(type '%shelp command alias' for more info):\n", + GetCommandPrefix()); + result.AppendMessage(""); + max_len = FindLongestCommandWord(m_alias_dict); - if (success) - { - CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); - m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; - } + for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); + ++alias_pos) { + OutputFormattedHelpText(result.GetOutputStream(), + alias_pos->first.c_str(), "--", + alias_pos->second->GetHelp(), max_len); } + result.AppendMessage(""); + } - std::unique_ptr attach_regex_cmd_ap( - new CommandObjectRegexCommand(*this, "_regexp-attach", "Attach to process by ID or name.", - "_regexp-attach | ", 2, 0, false)); - if (attach_regex_cmd_ap.get()) - { - if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && - attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' - attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && - attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) - { - CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); - m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; - } - } + if (!m_user_dict.empty() && + ((cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef)) { + result.AppendMessage("Current user-defined commands:"); + result.AppendMessage(""); + max_len = FindLongestCommandWord(m_user_dict); + for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) { + OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(), + "--", pos->second->GetHelp(), max_len); + } + result.AppendMessage(""); + } + + result.AppendMessageWithFormat( + "For more information on any command, type '%shelp '.\n", + GetCommandPrefix()); +} - std::unique_ptr down_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-down", "Select a newer stack frame. Defaults to moving one frame, a numeric argument can " - "specify an arbitrary number.", - "_regexp-down []", 2, 0, false)); - if (down_regex_cmd_ap.get()) - { - if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && - down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) - { - CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); - m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; - } - } +CommandObject * +CommandInterpreter::GetCommandObjectForCommand(std::string &command_string) { + // This function finds the final, lowest-level, alias-resolved command object + // whose 'Execute' function will + // eventually be invoked by the given command line. + + CommandObject *cmd_obj = nullptr; + size_t start = command_string.find_first_not_of(k_white_space); + size_t end = 0; + bool done = false; + while (!done) { + if (start != std::string::npos) { + // Get the next word from command_string. + end = command_string.find_first_of(k_white_space, start); + if (end == std::string::npos) + end = command_string.size(); + std::string cmd_word = command_string.substr(start, end - start); + + if (cmd_obj == nullptr) + // Since cmd_obj is NULL we are on our first time through this loop. + // Check to see if cmd_word is a valid + // command or alias. + cmd_obj = GetCommandObject(cmd_word.c_str()); + else if (cmd_obj->IsMultiwordObject()) { + // Our current object is a multi-word object; see if the cmd_word is a + // valid sub-command for our object. + CommandObject *sub_cmd_obj = + cmd_obj->GetSubcommandObject(cmd_word.c_str()); + if (sub_cmd_obj) + cmd_obj = sub_cmd_obj; + else // cmd_word was not a valid sub-command word, so we are done + done = true; + } else + // We have a cmd_obj and it is not a multi-word object, so we are done. + done = true; + + // If we didn't find a valid command object, or our command object is not + // a multi-word object, or + // we are at the end of the command_string, then we are done. Otherwise, + // find the start of the + // next word. + + if (!cmd_obj || !cmd_obj->IsMultiwordObject() || + end >= command_string.size()) + done = true; + else + start = command_string.find_first_not_of(k_white_space, end); + } else + // Unable to find any more words. + done = true; + } + + if (end == command_string.size()) + command_string.clear(); + else + command_string = command_string.substr(end); + + return cmd_obj; +} + +static const char *k_valid_command_chars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; +static void StripLeadingSpaces(std::string &s) { + if (!s.empty()) { + size_t pos = s.find_first_not_of(k_white_space); + if (pos == std::string::npos) + s.clear(); + else if (pos == 0) + return; + s.erase(0, pos); + } +} + +static size_t FindArgumentTerminator(const std::string &s) { + const size_t s_len = s.size(); + size_t offset = 0; + while (offset < s_len) { + size_t pos = s.find("--", offset); + if (pos == std::string::npos) + break; + if (pos > 0) { + if (isspace(s[pos - 1])) { + // Check if the string ends "\s--" (where \s is a space character) + // or if we have "\s--\s". + if ((pos + 2 >= s_len) || isspace(s[pos + 2])) { + return pos; + } + } + } + offset = pos + 2; + } + return std::string::npos; +} + +static bool ExtractCommand(std::string &command_string, std::string &command, + std::string &suffix, char "e_char) { + command.clear(); + suffix.clear(); + StripLeadingSpaces(command_string); + + bool result = false; + quote_char = '\0'; + + if (!command_string.empty()) { + const char first_char = command_string[0]; + if (first_char == '\'' || first_char == '"') { + quote_char = first_char; + const size_t end_quote_pos = command_string.find(quote_char, 1); + if (end_quote_pos == std::string::npos) { + command.swap(command_string); + command_string.erase(); + } else { + command.assign(command_string, 1, end_quote_pos - 1); + if (end_quote_pos + 1 < command_string.size()) + command_string.erase(0, command_string.find_first_not_of( + k_white_space, end_quote_pos + 1)); + else + command_string.erase(); + } + } else { + const size_t first_space_pos = + command_string.find_first_of(k_white_space); + if (first_space_pos == std::string::npos) { + command.swap(command_string); + command_string.erase(); + } else { + command.assign(command_string, 0, first_space_pos); + command_string.erase(0, command_string.find_first_not_of( + k_white_space, first_space_pos)); + } + } + result = true; + } + + if (!command.empty()) { + // actual commands can't start with '-' or '_' + if (command[0] != '-' && command[0] != '_') { + size_t pos = command.find_first_not_of(k_valid_command_chars); + if (pos > 0 && pos != std::string::npos) { + suffix.assign(command.begin() + pos, command.end()); + command.erase(pos); + } + } + } + + return result; +} + +CommandObject *CommandInterpreter::BuildAliasResult( + const char *alias_name, std::string &raw_input_string, + std::string &alias_result, CommandReturnObject &result) { + CommandObject *alias_cmd_obj = nullptr; + Args cmd_args(raw_input_string); + alias_cmd_obj = GetCommandObject(alias_name); + StreamString result_str; + + if (alias_cmd_obj && alias_cmd_obj->IsAlias()) { + std::pair desugared = + ((CommandAlias *)alias_cmd_obj)->Desugar(); + OptionArgVectorSP option_arg_vector_sp = desugared.second; + alias_cmd_obj = desugared.first.get(); + std::string alias_name_str = alias_name; + if ((cmd_args.GetArgumentCount() == 0) || + (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0)) + cmd_args.Unshift(alias_name); + + result_str.Printf("%s", alias_cmd_obj->GetCommandName()); + + if (option_arg_vector_sp.get()) { + OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); + + for (size_t i = 0; i < option_arg_vector->size(); ++i) { + OptionArgPair option_pair = (*option_arg_vector)[i]; + OptionArgValue value_pair = option_pair.second; + int value_type = value_pair.first; + std::string option = option_pair.first; + std::string value = value_pair.second; + if (option.compare("") == 0) + result_str.Printf(" %s", value.c_str()); + else { + result_str.Printf(" %s", option.c_str()); + if (value_type != OptionParser::eNoArgument) { + if (value_type != OptionParser::eOptionalArgument) + result_str.Printf(" "); + int index = GetOptionArgumentPosition(value.c_str()); + if (index == 0) + result_str.Printf("%s", value.c_str()); + else if (static_cast(index) >= + cmd_args.GetArgumentCount()) { + + result.AppendErrorWithFormat("Not enough arguments provided; you " + "need at least %d arguments to use " + "this alias.\n", + index); + result.SetStatus(eReturnStatusFailed); + return nullptr; + } else { + size_t strpos = + raw_input_string.find(cmd_args.GetArgumentAtIndex(index)); + if (strpos != std::string::npos) + raw_input_string = raw_input_string.erase( + strpos, strlen(cmd_args.GetArgumentAtIndex(index))); + result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index)); + } + } + } + } + } + + alias_result = result_str.GetData(); + } + return alias_cmd_obj; +} + +Error CommandInterpreter::PreprocessCommand(std::string &command) { + // The command preprocessor needs to do things to the command + // line before any parsing of arguments or anything else is done. + // The only current stuff that gets preprocessed is anything enclosed + // in backtick ('`') characters is evaluated as an expression and + // the result of the expression must be a scalar that can be substituted + // into the command. An example would be: + // (lldb) memory read `$rsp + 20` + Error error; // Error for any expressions that might not evaluate + size_t start_backtick; + size_t pos = 0; + while ((start_backtick = command.find('`', pos)) != std::string::npos) { + if (start_backtick > 0 && command[start_backtick - 1] == '\\') { + // The backtick was preceded by a '\' character, remove the slash + // and don't treat the backtick as the start of an expression + command.erase(start_backtick - 1, 1); + // No need to add one to start_backtick since we just deleted a char + pos = start_backtick; + } else { + const size_t expr_content_start = start_backtick + 1; + const size_t end_backtick = command.find('`', expr_content_start); + if (end_backtick == std::string::npos) + return error; + else if (end_backtick == expr_content_start) { + // Empty expression (two backticks in a row) + command.erase(start_backtick, 2); + } else { + std::string expr_str(command, expr_content_start, + end_backtick - expr_content_start); - std::unique_ptr up_regex_cmd_ap( - new CommandObjectRegexCommand(*this, "_regexp-up", "Select an older stack frame. Defaults to moving one " - "frame, a numeric argument can specify an arbitrary number.", - "_regexp-up []", 2, 0, false)); - if (up_regex_cmd_ap.get()) - { - if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && - up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) - { - CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); - m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; - } + ExecutionContext exe_ctx(GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + // Get a dummy target to allow for calculator mode while processing + // backticks. + // This also helps break the infinite loop caused when target is null. + if (!target) + target = m_debugger.GetDummyTarget(); + if (target) { + ValueObjectSP expr_result_valobj_sp; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetKeepInMemory(false); + options.SetTryAllThreads(true); + options.SetTimeoutUsec(0); + + ExpressionResults expr_result = target->EvaluateExpression( + expr_str.c_str(), exe_ctx.GetFramePtr(), expr_result_valobj_sp, + options); + + if (expr_result == eExpressionCompleted) { + Scalar scalar; + if (expr_result_valobj_sp) + expr_result_valobj_sp = + expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable( + expr_result_valobj_sp->GetDynamicValueType(), true); + if (expr_result_valobj_sp->ResolveValue(scalar)) { + command.erase(start_backtick, end_backtick - start_backtick + 1); + StreamString value_strm; + const bool show_type = false; + scalar.GetValue(&value_strm, show_type); + size_t value_string_size = value_strm.GetSize(); + if (value_string_size) { + command.insert(start_backtick, value_strm.GetData(), + value_string_size); + pos = start_backtick + value_string_size; + continue; + } else { + error.SetErrorStringWithFormat("expression value didn't result " + "in a scalar value for the " + "expression '%s'", + expr_str.c_str()); + } + } else { + error.SetErrorStringWithFormat("expression value didn't result " + "in a scalar value for the " + "expression '%s'", + expr_str.c_str()); + } + } else { + if (expr_result_valobj_sp) + error = expr_result_valobj_sp->GetError(); + if (error.Success()) { + + switch (expr_result) { + case eExpressionSetupError: + error.SetErrorStringWithFormat( + "expression setup error for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionParseError: + error.SetErrorStringWithFormat( + "expression parse error for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionResultUnavailable: + error.SetErrorStringWithFormat( + "expression error fetching result for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionCompleted: + break; + case eExpressionDiscarded: + error.SetErrorStringWithFormat( + "expression discarded for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionInterrupted: + error.SetErrorStringWithFormat( + "expression interrupted for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionHitBreakpoint: + error.SetErrorStringWithFormat( + "expression hit breakpoint for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionTimedOut: + error.SetErrorStringWithFormat( + "expression timed out for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionStoppedForDebug: + error.SetErrorStringWithFormat("expression stop at entry point " + "for debugging for the " + "expression '%s'", + expr_str.c_str()); + break; + } + } + } + } + } + if (error.Fail()) + break; + } + } + return error; +} + +bool CommandInterpreter::HandleCommand(const char *command_line, + LazyBool lazy_add_to_history, + CommandReturnObject &result, + ExecutionContext *override_context, + bool repeat_on_empty_command, + bool no_context_switching) + +{ + + std::string command_string(command_line); + std::string original_command_string(command_line); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS)); + Host::SetCrashDescriptionWithFormat("HandleCommand(command = \"%s\")", + command_line); + + // Make a scoped cleanup object that will clear the crash description string + // on exit of this function. + lldb_utility::CleanUp crash_description_cleanup( + nullptr, Host::SetCrashDescription); + + if (log) + log->Printf("Processing command: %s", command_line); + + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "Handling command: %s.", + command_line); + + if (!no_context_switching) + UpdateExecutionContext(override_context); + + bool add_to_history; + if (lazy_add_to_history == eLazyBoolCalculate) + add_to_history = (m_command_source_depth == 0); + else + add_to_history = (lazy_add_to_history == eLazyBoolYes); + + bool empty_command = false; + bool comment_command = false; + if (command_string.empty()) + empty_command = true; + else { + const char *k_space_characters = "\t\n\v\f\r "; + + size_t non_space = command_string.find_first_not_of(k_space_characters); + // Check for empty line or comment line (lines whose first + // non-space character is the comment character for this interpreter) + if (non_space == std::string::npos) + empty_command = true; + else if (command_string[non_space] == m_comment_char) + comment_command = true; + else if (command_string[non_space] == CommandHistory::g_repeat_char) { + const char *history_string = + m_command_history.FindString(command_string.c_str() + non_space); + if (history_string == nullptr) { + result.AppendErrorWithFormat("Could not find entry: %s in history", + command_string.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + add_to_history = false; + command_string = history_string; + original_command_string = history_string; } + } - std::unique_ptr display_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-display", "Evaluate an expression at every stop (see 'help target stop-hook'.)", - "_regexp-display expression", 2, 0, false)); - if (display_regex_cmd_ap.get()) - { - if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) - { - CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); - m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; - } - } + if (empty_command) { + if (repeat_on_empty_command) { + if (m_command_history.IsEmpty()) { + result.AppendError("empty command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + command_line = m_repeat_command.c_str(); + command_string = command_line; + original_command_string = command_line; + if (m_repeat_command.empty()) { + result.AppendErrorWithFormat("No auto repeat.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + add_to_history = false; + } else { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } + } else if (comment_command) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } + + Error error(PreprocessCommand(command_string)); + + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + // Phase 1. + + // Before we do ANY kind of argument processing, we need to figure out what + // the real/final command object is for the specified command. This gets + // complicated by the fact that the user could have specified an alias, and, + // in translating the alias, there may also be command options and/or even + // data (including raw text strings) that need to be found and inserted into + // the command line as part of the translation. So this first step is plain + // look-up and replacement, resulting in: + // 1. the command object whose Execute method will actually be called + // 2. a revised command string, with all substitutions and replacements + // taken care of + // From 1 above, we can determine whether the Execute function wants raw + // input or not. + + CommandObject *cmd_obj = ResolveCommandImpl(command_string, result); + + // Although the user may have abbreviated the command, the command_string now + // has the command expanded to the full name. For example, if the input + // was "br s -n main", command_string is now "breakpoint set -n main". + + if (log) { + log->Printf("HandleCommand, cmd_obj : '%s'", + cmd_obj ? cmd_obj->GetCommandName() : ""); + log->Printf("HandleCommand, (revised) command_string: '%s'", + command_string.c_str()); + const bool wants_raw_input = + (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false; + log->Printf("HandleCommand, wants_raw_input:'%s'", + wants_raw_input ? "True" : "False"); + } + + // Phase 2. + // Take care of things like setting up the history command & calling the + // appropriate Execute method on the + // CommandObject, with the appropriate arguments. + + if (cmd_obj != nullptr) { + if (add_to_history) { + Args command_args(command_string); + const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); + if (repeat_command != nullptr) + m_repeat_command.assign(repeat_command); + else + m_repeat_command.assign(original_command_string.c_str()); + + m_command_history.AppendString(original_command_string); + } + + std::string remainder; + const std::size_t actual_cmd_name_len = strlen(cmd_obj->GetCommandName()); + if (actual_cmd_name_len < command_string.length()) + remainder = command_string.substr(actual_cmd_name_len); + + // Remove any initial spaces + size_t pos = remainder.find_first_not_of(k_white_space); + if (pos != 0 && pos != std::string::npos) + remainder.erase(0, pos); - std::unique_ptr undisplay_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-undisplay", "Stop displaying expression at every stop (specified by stop-hook index.)", - "_regexp-undisplay stop-hook-number", 2, 0, false)); - if (undisplay_regex_cmd_ap.get()) - { - if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) - { - CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); - m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; - } - } + if (log) + log->Printf( + "HandleCommand, command line after removing command name(s): '%s'", + remainder.c_str()); + + cmd_obj->Execute(remainder.c_str(), result); + } else { + // We didn't find the first command object, so complete the first argument. + Args command_args(command_string); + StringList matches; + int num_matches; + int cursor_index = 0; + int cursor_char_position = strlen(command_args.GetArgumentAtIndex(0)); + bool word_complete; + num_matches = HandleCompletionMatches(command_args, cursor_index, + cursor_char_position, 0, -1, + word_complete, matches); + + if (num_matches > 0) { + std::string error_msg; + error_msg.assign("ambiguous command '"); + error_msg.append(command_args.GetArgumentAtIndex(0)); + error_msg.append("'."); + + error_msg.append(" Possible completions:"); + for (int i = 0; i < num_matches; i++) { + error_msg.append("\n\t"); + error_msg.append(matches.GetStringAtIndex(i)); + } + error_msg.append("\n"); + result.AppendRawError(error_msg.c_str()); + } else + result.AppendErrorWithFormat("Unrecognized command '%s'.\n", + command_args.GetArgumentAtIndex(0)); + + result.SetStatus(eReturnStatusFailed); + } + + if (log) + log->Printf("HandleCommand, command %s", + (result.Succeeded() ? "succeeded" : "did not succeed")); + + return result.Succeeded(); +} + +int CommandInterpreter::HandleCompletionMatches( + Args &parsed_line, int &cursor_index, int &cursor_char_position, + int match_start_point, int max_return_elements, bool &word_complete, + StringList &matches) { + int num_command_matches = 0; + bool look_for_subcommand = false; + + // For any of the command completions a unique match will be a complete word. + word_complete = true; + + if (cursor_index == -1) { + // We got nothing on the command line, so return the list of commands + bool include_aliases = true; + num_command_matches = + GetCommandNamesMatchingPartialString("", include_aliases, matches); + } else if (cursor_index == 0) { + // The cursor is in the first argument, so just do a lookup in the + // dictionary. + CommandObject *cmd_obj = + GetCommandObject(parsed_line.GetArgumentAtIndex(0), &matches); + num_command_matches = matches.GetSize(); + + if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() && + matches.GetStringAtIndex(0) != nullptr && + strcmp(parsed_line.GetArgumentAtIndex(0), + matches.GetStringAtIndex(0)) == 0) { + if (parsed_line.GetArgumentCount() == 1) { + word_complete = true; + } else { + look_for_subcommand = true; + num_command_matches = 0; + matches.DeleteStringAtIndex(0); + parsed_line.AppendArgument(""); + cursor_index++; + cursor_char_position = 0; + } + } + } + + if (cursor_index > 0 || look_for_subcommand) { + // We are completing further on into a commands arguments, so find the + // command and tell it + // to complete the command. + // First see if there is a matching initial command: + CommandObject *command_object = + GetCommandObject(parsed_line.GetArgumentAtIndex(0)); + if (command_object == nullptr) { + return 0; + } else { + parsed_line.Shift(); + cursor_index--; + num_command_matches = command_object->HandleCompletion( + parsed_line, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + } + } + + return num_command_matches; +} + +int CommandInterpreter::HandleCompletion( + const char *current_line, const char *cursor, const char *last_char, + int match_start_point, int max_return_elements, StringList &matches) { + // We parse the argument up to the cursor, so the last argument in parsed_line + // is + // the one containing the cursor, and the cursor is after the last character. + + Args parsed_line(llvm::StringRef(current_line, last_char - current_line)); + Args partial_parsed_line( + llvm::StringRef(current_line, cursor - current_line)); + + // Don't complete comments, and if the line we are completing is just the + // history repeat character, + // substitute the appropriate history line. + const char *first_arg = parsed_line.GetArgumentAtIndex(0); + if (first_arg) { + if (first_arg[0] == m_comment_char) + return 0; + else if (first_arg[0] == CommandHistory::g_repeat_char) { + const char *history_string = m_command_history.FindString(first_arg); + if (history_string != nullptr) { + matches.Clear(); + matches.InsertStringAtIndex(0, history_string); + return -2; + } else + return 0; + } + } + + int num_args = partial_parsed_line.GetArgumentCount(); + int cursor_index = partial_parsed_line.GetArgumentCount() - 1; + int cursor_char_position; + + if (cursor_index == -1) + cursor_char_position = 0; + else + cursor_char_position = + strlen(partial_parsed_line.GetArgumentAtIndex(cursor_index)); + + if (cursor > current_line && cursor[-1] == ' ') { + // We are just after a space. If we are in an argument, then we will + // continue + // parsing, but if we are between arguments, then we have to complete + // whatever the next + // element would be. + // We can distinguish the two cases because if we are in an argument (e.g. + // because the space is + // protected by a quote) then the space will also be in the parsed + // argument... + + const char *current_elem = + partial_parsed_line.GetArgumentAtIndex(cursor_index); + if (cursor_char_position == 0 || + current_elem[cursor_char_position - 1] != ' ') { + parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0'); + cursor_index++; + cursor_char_position = 0; + } + } + + int num_command_matches; + + matches.Clear(); + + // Only max_return_elements == -1 is supported at present: + assert(max_return_elements == -1); + bool word_complete; + num_command_matches = HandleCompletionMatches( + parsed_line, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + + if (num_command_matches <= 0) + return num_command_matches; - std::unique_ptr connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand( - *this, "gdb-remote", - "Connect to a process via remote GDB server. If no host is specifed, localhost is assumed.", - "gdb-remote [:]", 2, 0, false)); - if (connect_gdb_remote_cmd_ap.get()) - { - if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && - connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) - { - CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); - m_command_dict[command_sp->GetCommandName ()] = command_sp; - } - } + if (num_args == 0) { + // If we got an empty string, insert nothing. + matches.InsertStringAtIndex(0, ""); + } else { + // Now figure out if there is a common substring, and if so put that in + // element 0, otherwise + // put an empty string in element 0. + std::string command_partial_str; + if (cursor_index >= 0) + command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), + parsed_line.GetArgumentAtIndex(cursor_index) + + cursor_char_position); - std::unique_ptr connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand( - *this, "kdp-remote", - "Connect to a process via remote KDP server. If no UDP port is specified, port 41139 is assumed.", - "kdp-remote [:]", 2, 0, false)); - if (connect_kdp_remote_cmd_ap.get()) - { - if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && - connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) - { - CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); - m_command_dict[command_sp->GetCommandName ()] = command_sp; - } - } + std::string common_prefix; + matches.LongestCommonPrefix(common_prefix); + const size_t partial_name_len = command_partial_str.size(); + common_prefix.erase(0, partial_name_len); - std::unique_ptr bt_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-bt", "Show the current thread's call stack. Any numeric argument displays at most that many " - "frames. The argument 'all' displays all threads.", - "bt [ | all]", 2, 0, false)); - if (bt_regex_cmd_ap.get()) - { - // accept but don't document "bt -c " -- before bt was a regex command if you wanted to backtrace - // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and - // so now "bt 3" is the preferred form, in line with gdb. - if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && - bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && - bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && - bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) - { - CommandObjectSP command_sp(bt_regex_cmd_ap.release()); - m_command_dict[command_sp->GetCommandName ()] = command_sp; - } - } + // If we matched a unique single command, add a space... + // Only do this if the completer told us this was a complete word, + // however... + if (num_command_matches == 1 && word_complete) { + char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); + common_prefix = + Args::EscapeLLDBCommandArgument(common_prefix, quote_char); + if (quote_char != '\0') + common_prefix.push_back(quote_char); + common_prefix.push_back(' '); + } + matches.InsertStringAtIndex(0, common_prefix.c_str()); + } + return num_command_matches; +} + +CommandInterpreter::~CommandInterpreter() {} + +void CommandInterpreter::UpdatePrompt(const char *new_prompt) { + EventSP prompt_change_event_sp( + new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt))); + ; + BroadcastEvent(prompt_change_event_sp); + if (m_command_io_handler_sp) + m_command_io_handler_sp->SetPrompt(new_prompt); +} + +bool CommandInterpreter::Confirm(const char *message, bool default_answer) { + // Check AutoConfirm first: + if (m_debugger.GetAutoConfirm()) + return default_answer; + + IOHandlerConfirm *confirm = + new IOHandlerConfirm(m_debugger, message, default_answer); + IOHandlerSP io_handler_sp(confirm); + m_debugger.RunIOHandler(io_handler_sp); + return confirm->GetResponse(); +} + +CommandAlias *CommandInterpreter::GetAlias(const char *alias_name) { + OptionArgVectorSP ret_val; + + std::string alias(alias_name); + + auto pos = m_alias_dict.find(alias); + if (pos != m_alias_dict.end()) + return (CommandAlias *)pos->second.get(); + + return nullptr; +} + +bool CommandInterpreter::HasCommands() { return (!m_command_dict.empty()); } + +bool CommandInterpreter::HasAliases() { return (!m_alias_dict.empty()); } + +bool CommandInterpreter::HasUserCommands() { return (!m_user_dict.empty()); } + +bool CommandInterpreter::HasAliasOptions() { return HasAliases(); } + +void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, + const char *alias_name, + Args &cmd_args, + std::string &raw_input_string, + CommandReturnObject &result) { + OptionArgVectorSP option_arg_vector_sp = + GetAlias(alias_name)->GetOptionArguments(); + + bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); + + // Make sure that the alias name is the 0th element in cmd_args + std::string alias_name_str = alias_name; + if (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0) + cmd_args.Unshift(alias_name); + + Args new_args(alias_cmd_obj->GetCommandName()); + if (new_args.GetArgumentCount() == 2) + new_args.Shift(); + + if (option_arg_vector_sp.get()) { + if (wants_raw_input) { + // We have a command that both has command options and takes raw input. + // Make *sure* it has a + // " -- " in the right place in the raw_input_string. + size_t pos = raw_input_string.find(" -- "); + if (pos == std::string::npos) { + // None found; assume it goes at the beginning of the raw input string + raw_input_string.insert(0, " -- "); + } + } + + OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); + const size_t old_size = cmd_args.GetArgumentCount(); + std::vector used(old_size + 1, false); + + used[0] = true; + + for (size_t i = 0; i < option_arg_vector->size(); ++i) { + OptionArgPair option_pair = (*option_arg_vector)[i]; + OptionArgValue value_pair = option_pair.second; + int value_type = value_pair.first; + std::string option = option_pair.first; + std::string value = value_pair.second; + if (option.compare("") == 0) { + if (!wants_raw_input || (value.compare("--") != 0)) // Since we inserted + // this above, make + // sure we don't + // insert it twice + new_args.AppendArgument(value.c_str()); + } else { + if (value_type != OptionParser::eOptionalArgument) + new_args.AppendArgument(option.c_str()); + if (value.compare("") != 0) { + int index = GetOptionArgumentPosition(value.c_str()); + if (index == 0) { + // value was NOT a positional argument; must be a real value + if (value_type != OptionParser::eOptionalArgument) + new_args.AppendArgument(value.c_str()); + else { + char buffer[255]; + ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(), + value.c_str()); + new_args.AppendArgument(buffer); + } - std::unique_ptr list_regex_cmd_ap(new CommandObjectRegexCommand( - *this, "_regexp-list", "List relevant source code using one of several shorthand formats.", - "\n" - "_regexp-list : // List around specific file/line\n" - "_regexp-list // List current file around specified line\n" - "_regexp-list // List specified function\n" - "_regexp-list 0x
// List around specified address\n" - "_regexp-list -[] // List previous lines\n" - "_regexp-list // List subsequent lines", - 2, CommandCompletions::eSourceFileCompletion, false)); - if (list_regex_cmd_ap.get()) - { - if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && - list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && - list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && - list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && - list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && - list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && - list_regex_cmd_ap->AddRegexCommand("^$", "source list")) - { - CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); - m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; - } - } + } else if (static_cast(index) >= + cmd_args.GetArgumentCount()) { + result.AppendErrorWithFormat("Not enough arguments provided; you " + "need at least %d arguments to use " + "this alias.\n", + index); + result.SetStatus(eReturnStatusFailed); + return; + } else { + // Find and remove cmd_args.GetArgumentAtIndex(i) from + // raw_input_string + size_t strpos = + raw_input_string.find(cmd_args.GetArgumentAtIndex(index)); + if (strpos != std::string::npos) { + raw_input_string = raw_input_string.erase( + strpos, strlen(cmd_args.GetArgumentAtIndex(index))); + } - std::unique_ptr env_regex_cmd_ap( - new CommandObjectRegexCommand(*this, "_regexp-env", "Shorthand for viewing and setting environment variables.", - "\n" - "_regexp-env // Show enrivonment\n" - "_regexp-env = // Set an environment variable", - 2, 0, false)); - if (env_regex_cmd_ap.get()) - { - if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && - env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) - { - CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); - m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; + if (value_type != OptionParser::eOptionalArgument) + new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index)); + else { + char buffer[255]; + ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(), + cmd_args.GetArgumentAtIndex(index)); + new_args.AppendArgument(buffer); + } + used[index] = true; + } } + } } - std::unique_ptr jump_regex_cmd_ap( - new CommandObjectRegexCommand(*this, "_regexp-jump", "Set the program counter to a new address.", - "\n" - "_regexp-jump \n" - "_regexp-jump + | -\n" - "_regexp-jump :\n" - "_regexp-jump *\n", - 2, 0, false)); - if (jump_regex_cmd_ap.get()) - { - if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && - jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") && - jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") && - jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1")) - { - CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release()); - m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp; - } + for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) { + if (!used[j] && !wants_raw_input) + new_args.AppendArgument(cmd_args.GetArgumentAtIndex(j)); } -} - -int -CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, - StringList &matches) -{ - AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); - - if (include_aliases) - { - AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); + cmd_args.Clear(); + cmd_args.SetArguments(new_args.GetArgumentCount(), + new_args.GetConstArgumentVector()); + } else { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + // This alias was not created with any options; nothing further needs to be + // done, unless it is a command that + // wants raw input, in which case we need to clear the rest of the data from + // cmd_args, since its in the raw + // input string. + if (wants_raw_input) { + cmd_args.Clear(); + cmd_args.SetArguments(new_args.GetArgumentCount(), + new_args.GetConstArgumentVector()); } + return; + } - return matches.GetSize(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return; } -CommandObjectSP -CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) -{ - CommandObject::CommandMap::iterator pos; - CommandObjectSP command_sp; - - std::string cmd(cmd_cstr); - - if (HasCommands()) - { - pos = m_command_dict.find(cmd); - if (pos != m_command_dict.end()) - command_sp = pos->second; - } - - if (include_aliases && HasAliases()) - { - auto alias_pos = m_alias_dict.find(cmd); - if (alias_pos != m_alias_dict.end()) - command_sp = alias_pos->second; - } - - if (HasUserCommands()) - { - pos = m_user_dict.find(cmd); - if (pos != m_user_dict.end()) - command_sp = pos->second; - } - - if (!exact && !command_sp) - { - // We will only get into here if we didn't find any exact matches. - - CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; - - StringList local_matches; - if (matches == nullptr) - matches = &local_matches; - - unsigned int num_cmd_matches = 0; - unsigned int num_alias_matches = 0; - unsigned int num_user_matches = 0; - - // Look through the command dictionaries one by one, and if we get only one match from any of - // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. - - if (HasCommands()) - { - num_cmd_matches = AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); - } - - if (num_cmd_matches == 1) - { - cmd.assign(matches->GetStringAtIndex(0)); - pos = m_command_dict.find(cmd); - if (pos != m_command_dict.end()) - real_match_sp = pos->second; - } - - if (include_aliases && HasAliases()) - { - num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); - - } - - if (num_alias_matches == 1) - { - cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); - auto alias_pos = m_alias_dict.find(cmd); - if (alias_pos != m_alias_dict.end()) - alias_match_sp = alias_pos->second; - } - - if (HasUserCommands()) - { - num_user_matches = AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); - } - - if (num_user_matches == 1) - { - cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); - - pos = m_user_dict.find (cmd); - if (pos != m_user_dict.end()) - user_match_sp = pos->second; - } - - // If we got exactly one match, return that, otherwise return the match list. - - if (num_user_matches + num_cmd_matches + num_alias_matches == 1) - { - if (num_cmd_matches) - return real_match_sp; - else if (num_alias_matches) - return alias_match_sp; - else - return user_match_sp; - } - } - else if (matches && command_sp) - { - matches->AppendString (cmd_cstr); - } +int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) { + int position = 0; // Any string that isn't an argument position, i.e. '%' + // followed by an integer, gets a position + // of zero. + const char *cptr = in_string; - return command_sp; -} + // Does it start with '%' + if (cptr[0] == '%') { + ++cptr; -bool -CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) -{ - if (cmd_sp.get()) - assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); - - if (name && name[0]) - { - std::string name_sstr(name); - bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); - if (found && !can_replace) - return false; - if (found && m_command_dict[name_sstr]->IsRemovable() == false) - return false; - m_command_dict[name_sstr] = cmd_sp; - return true; - } - return false; -} + // Is the rest of it entirely digits? + if (isdigit(cptr[0])) { + const char *start = cptr; + while (isdigit(cptr[0])) + ++cptr; -bool -CommandInterpreter::AddUserCommand (std::string name, - const lldb::CommandObjectSP &cmd_sp, - bool can_replace) -{ - if (cmd_sp.get()) - assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); - - if (!name.empty()) - { - const char* name_cstr = name.c_str(); - - // do not allow replacement of internal commands - if (CommandExists(name_cstr)) - { - if (can_replace == false) - return false; - if (m_command_dict[name]->IsRemovable() == false) - return false; - } - - if (UserCommandExists(name_cstr)) - { - if (can_replace == false) - return false; - if (m_user_dict[name]->IsRemovable() == false) - return false; - } - - m_user_dict[name] = cmd_sp; - return true; + // We've gotten to the end of the digits; are we at the end of the string? + if (cptr[0] == '\0') + position = atoi(start); } - return false; -} + } -CommandObjectSP -CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) -{ - Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. - CommandObjectSP ret_val; // Possibly empty return value. - - if (cmd_cstr == nullptr) - return ret_val; - - if (cmd_words.GetArgumentCount() == 1) - return GetCommandSP(cmd_cstr, include_aliases, true, nullptr); - else - { - // We have a multi-word command (seemingly), so we need to do more work. - // First, get the cmd_obj_sp for the first word in the command. - CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr); - if (cmd_obj_sp.get() != nullptr) - { - // Loop through the rest of the words in the command (everything passed in was supposed to be part of a - // command name), and find the appropriate sub-command SP for each command word.... - size_t end = cmd_words.GetArgumentCount(); - for (size_t j= 1; j < end; ++j) - { - if (cmd_obj_sp->IsMultiwordObject()) - { - cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); - if (cmd_obj_sp.get() == nullptr) - // The sub-command name was invalid. Fail and return the empty 'ret_val'. - return ret_val; - } - else - // We have more words in the command name, but we don't have a multiword object. Fail and return - // empty 'ret_val'. - return ret_val; - } - // We successfully looped through all the command words and got valid command objects for them. Assign the - // last object retrieved to 'ret_val'. - ret_val = cmd_obj_sp; - } - } - return ret_val; + return position; } -CommandObject * -CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) -{ - return GetCommandSPExact (cmd_cstr, include_aliases).get(); -} +void CommandInterpreter::SourceInitFile(bool in_cwd, + CommandReturnObject &result) { + FileSpec init_file; + if (in_cwd) { + ExecutionContext exe_ctx(GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + // In the current working directory we don't load any program specific + // .lldbinit files, we only look for a ".lldbinit" file. + if (m_skip_lldbinit_files) + return; -CommandObject * -CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) -{ - CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); + LoadCWDlldbinitFile should_load = + target->TargetProperties::GetLoadCWDlldbinitFile(); + if (should_load == eLoadCWDlldbinitWarn) { + FileSpec dot_lldb(".lldbinit", true); + llvm::SmallString<64> home_dir_path; + llvm::sys::path::home_directory(home_dir_path); + FileSpec homedir_dot_lldb(home_dir_path.c_str(), false); + homedir_dot_lldb.AppendPathComponent(".lldbinit"); + homedir_dot_lldb.ResolvePath(); + if (dot_lldb.Exists() && + dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) { + result.AppendErrorWithFormat( + "There is a .lldbinit file in the current directory which is not " + "being read.\n" + "To silence this warning without sourcing in the local " + ".lldbinit,\n" + "add the following to the lldbinit file in your home directory:\n" + " settings set target.load-cwd-lldbinit false\n" + "To allow lldb to source .lldbinit files in the current working " + "directory,\n" + "set the value of this variable to true. Only do so if you " + "understand and\n" + "accept the security risk."); + result.SetStatus(eReturnStatusFailed); + return; + } + } else if (should_load == eLoadCWDlldbinitTrue) { + init_file.SetFile("./.lldbinit", true); + } + } + } else { + // If we aren't looking in the current working directory we are looking + // in the home directory. We will first see if there is an application + // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a + // "-" and the name of the program. If this file doesn't exist, we fall + // back to just the "~/.lldbinit" file. We also obey any requests to not + // load the init files. + llvm::SmallString<64> home_dir_path; + llvm::sys::path::home_directory(home_dir_path); + FileSpec profilePath(home_dir_path.c_str(), false); + profilePath.AppendPathComponent(".lldbinit"); + std::string init_file_path = profilePath.GetPath(); + + if (m_skip_app_init_files == false) { + FileSpec program_file_spec(HostInfo::GetProgramFileSpec()); + const char *program_name = program_file_spec.GetFilename().AsCString(); + + if (program_name) { + char program_init_file_name[PATH_MAX]; + ::snprintf(program_init_file_name, sizeof(program_init_file_name), + "%s-%s", init_file_path.c_str(), program_name); + init_file.SetFile(program_init_file_name, true); + if (!init_file.Exists()) + init_file.Clear(); + } + } + + if (!init_file && !m_skip_lldbinit_files) + init_file.SetFile(init_file_path.c_str(), false); + } + + // If the file exists, tell HandleCommand to 'source' it; this will do the + // actual broadcasting + // of the commands back to any appropriate listener (see + // CommandObjectSource::Execute for more details). + + if (init_file.Exists()) { + const bool saved_batch = SetBatchCommandMode(true); + CommandInterpreterRunOptions options; + options.SetSilent(true); + options.SetStopOnError(false); + options.SetStopOnContinue(true); + + HandleCommandsFromFile(init_file, + nullptr, // Execution context + options, result); + SetBatchCommandMode(saved_batch); + } else { + // nothing to be done if the file doesn't exist + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } +} + +const char *CommandInterpreter::GetCommandPrefix() { + const char *prefix = GetDebugger().GetIOHandlerCommandPrefix(); + return prefix == NULL ? "" : prefix; +} + +PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) { + PlatformSP platform_sp; + if (prefer_target_platform) { + ExecutionContext exe_ctx(GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) + platform_sp = target->GetPlatform(); + } + + if (!platform_sp) + platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); + return platform_sp; +} + +void CommandInterpreter::HandleCommands(const StringList &commands, + ExecutionContext *override_context, + CommandInterpreterRunOptions &options, + CommandReturnObject &result) { + size_t num_lines = commands.GetSize(); + + // If we are going to continue past a "continue" then we need to run the + // commands synchronously. + // Make sure you reset this value anywhere you return from the function. + + bool old_async_execution = m_debugger.GetAsyncExecution(); + + // If we've been given an execution context, set it at the start, but don't + // keep resetting it or we will + // cause series of commands that change the context, then do an operation that + // relies on that context to fail. + + if (override_context != nullptr) + UpdateExecutionContext(override_context); + + if (!options.GetStopOnContinue()) { + m_debugger.SetAsyncExecution(false); + } + + for (size_t idx = 0; idx < num_lines; idx++) { + const char *cmd = commands.GetStringAtIndex(idx); + if (cmd[0] == '\0') + continue; + + if (options.GetEchoCommands()) { + result.AppendMessageWithFormat("%s %s\n", m_debugger.GetPrompt(), cmd); + } + + CommandReturnObject tmp_result; + // If override_context is not NULL, pass no_context_switching = true for + // HandleCommand() since we updated our context already. + + // We might call into a regex or alias command, in which case the + // add_to_history will get lost. This + // m_command_source_depth dingus is the way we turn off adding to the + // history in that case, so set it up here. + if (!options.GetAddToHistory()) + m_command_source_depth++; + bool success = + HandleCommand(cmd, options.m_add_to_history, tmp_result, + nullptr, /* override_context */ + true, /* repeat_on_empty_command */ + override_context != nullptr /* no_context_switching */); + if (!options.GetAddToHistory()) + m_command_source_depth--; + + if (options.GetPrintResults()) { + if (tmp_result.Succeeded()) + result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); + } + + if (!success || !tmp_result.Succeeded()) { + const char *error_msg = tmp_result.GetErrorData(); + if (error_msg == nullptr || error_msg[0] == '\0') + error_msg = ".\n"; + if (options.GetStopOnError()) { + result.AppendErrorWithFormat( + "Aborting reading of commands after command #%" PRIu64 + ": '%s' failed with %s", + (uint64_t)idx, cmd, error_msg); + result.SetStatus(eReturnStatusFailed); + m_debugger.SetAsyncExecution(old_async_execution); + return; + } else if (options.GetPrintResults()) { + result.AppendMessageWithFormat("Command #%" PRIu64 + " '%s' failed with %s", + (uint64_t)idx + 1, cmd, error_msg); + } + } + + if (result.GetImmediateOutputStream()) + result.GetImmediateOutputStream()->Flush(); + + if (result.GetImmediateErrorStream()) + result.GetImmediateErrorStream()->Flush(); + + // N.B. Can't depend on DidChangeProcessState, because the state coming into + // the command execution + // could be running (for instance in Breakpoint Commands. + // So we check the return value to see if it is has running in it. + if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) || + (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) { + if (options.GetStopOnContinue()) { + // If we caused the target to proceed, and we're going to stop in that + // case, set the + // status in our real result before returning. This is an error if the + // continue was not the + // last command in the set of commands to be run. + if (idx != num_lines - 1) + result.AppendErrorWithFormat( + "Aborting reading of commands after command #%" PRIu64 + ": '%s' continued the target.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat("Command #%" PRIu64 + " '%s' continued the target.\n", + (uint64_t)idx + 1, cmd); - // If we didn't find an exact match to the command string in the commands, look in - // the aliases. - - if (command_obj) - return command_obj; + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution(old_async_execution); - command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); + return; + } + } + + // Also check for "stop on crash here: + bool should_stop = false; + if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) { + TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) { + ProcessSP process_sp(target_sp->GetProcessSP()); + if (process_sp) { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || + reason == eStopReasonInstrumentation) { + should_stop = true; + break; + } + } + } + } + if (should_stop) { + if (idx != num_lines - 1) + result.AppendErrorWithFormat( + "Aborting reading of commands after command #%" PRIu64 + ": '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat( + "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); - if (command_obj) - return command_obj; - - // If there wasn't an exact match then look for an inexact one in just the commands - command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get(); + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution(old_async_execution); - // Finally, if there wasn't an inexact match among the commands, look for an inexact - // match in both the commands and aliases. - - if (command_obj) - { - if (matches) - matches->AppendString(command_obj->GetCommandName()); - return command_obj; + return; + } } - - return GetCommandSP(cmd_cstr, true, false, matches).get(); -} + } -bool -CommandInterpreter::CommandExists (const char *cmd) -{ - return m_command_dict.find(cmd) != m_command_dict.end(); -} + result.SetStatus(eReturnStatusSuccessFinishResult); + m_debugger.SetAsyncExecution(old_async_execution); -bool -CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) -{ - bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); - if (exact_match) - { - full_name.assign(cmd); - return exact_match; - } - else - { - StringList matches; - size_t num_alias_matches; - num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd, matches); - if (num_alias_matches == 1) - { - // Make sure this isn't shadowing a command in the regular command space: - StringList regular_matches; - const bool include_aliases = false; - const bool exact = false; - CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); - if (cmd_obj_sp || regular_matches.GetSize() > 0) - return false; - else - { - full_name.assign (matches.GetStringAtIndex(0)); - return true; - } - } - else - return false; - } + return; } -bool -CommandInterpreter::AliasExists (const char *cmd) -{ - return m_alias_dict.find(cmd) != m_alias_dict.end(); -} +// Make flags that we can pass into the IOHandler so our delegates can do the +// right thing +enum { + eHandleCommandFlagStopOnContinue = (1u << 0), + eHandleCommandFlagStopOnError = (1u << 1), + eHandleCommandFlagEchoCommand = (1u << 2), + eHandleCommandFlagPrintResult = (1u << 3), + eHandleCommandFlagStopOnCrash = (1u << 4) +}; -bool -CommandInterpreter::UserCommandExists (const char *cmd) -{ - return m_user_dict.find(cmd) != m_user_dict.end(); +void CommandInterpreter::HandleCommandsFromFile( + FileSpec &cmd_file, ExecutionContext *context, + CommandInterpreterRunOptions &options, CommandReturnObject &result) { + if (cmd_file.Exists()) { + StreamFileSP input_file_sp(new StreamFile()); + + std::string cmd_file_path = cmd_file.GetPath(); + Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), + File::eOpenOptionRead); + + if (error.Success()) { + Debugger &debugger = GetDebugger(); + + uint32_t flags = 0; + + if (options.m_stop_on_continue == eLazyBoolCalculate) { + if (m_command_source_flags.empty()) { + // Stop on continue by default + flags |= eHandleCommandFlagStopOnContinue; + } else if (m_command_source_flags.back() & + eHandleCommandFlagStopOnContinue) { + flags |= eHandleCommandFlagStopOnContinue; + } + } else if (options.m_stop_on_continue == eLazyBoolYes) { + flags |= eHandleCommandFlagStopOnContinue; + } + + if (options.m_stop_on_error == eLazyBoolCalculate) { + if (m_command_source_flags.empty()) { + if (GetStopCmdSourceOnError()) + flags |= eHandleCommandFlagStopOnError; + } else if (m_command_source_flags.back() & + eHandleCommandFlagStopOnError) { + flags |= eHandleCommandFlagStopOnError; + } + } else if (options.m_stop_on_error == eLazyBoolYes) { + flags |= eHandleCommandFlagStopOnError; + } + + if (options.GetStopOnCrash()) { + if (m_command_source_flags.empty()) { + // Echo command by default + flags |= eHandleCommandFlagStopOnCrash; + } else if (m_command_source_flags.back() & + eHandleCommandFlagStopOnCrash) { + flags |= eHandleCommandFlagStopOnCrash; + } + } + + if (options.m_echo_commands == eLazyBoolCalculate) { + if (m_command_source_flags.empty()) { + // Echo command by default + flags |= eHandleCommandFlagEchoCommand; + } else if (m_command_source_flags.back() & + eHandleCommandFlagEchoCommand) { + flags |= eHandleCommandFlagEchoCommand; + } + } else if (options.m_echo_commands == eLazyBoolYes) { + flags |= eHandleCommandFlagEchoCommand; + } + + if (options.m_print_results == eLazyBoolCalculate) { + if (m_command_source_flags.empty()) { + // Print output by default + flags |= eHandleCommandFlagPrintResult; + } else if (m_command_source_flags.back() & + eHandleCommandFlagPrintResult) { + flags |= eHandleCommandFlagPrintResult; + } + } else if (options.m_print_results == eLazyBoolYes) { + flags |= eHandleCommandFlagPrintResult; + } + + if (flags & eHandleCommandFlagPrintResult) { + debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", + cmd_file_path.c_str()); + } + + // Used for inheriting the right settings when "command source" might have + // nested "command source" commands + lldb::StreamFileSP empty_stream_sp; + m_command_source_flags.push_back(flags); + IOHandlerSP io_handler_sp(new IOHandlerEditline( + debugger, IOHandler::Type::CommandInterpreter, input_file_sp, + empty_stream_sp, // Pass in an empty stream so we inherit the top + // input reader output stream + empty_stream_sp, // Pass in an empty stream so we inherit the top + // input reader error stream + flags, + nullptr, // Pass in NULL for "editline_name" so no history is saved, + // or written + debugger.GetPrompt(), NULL, + false, // Not multi-line + debugger.GetUseColor(), 0, *this)); + const bool old_async_execution = debugger.GetAsyncExecution(); + + // Set synchronous execution if we are not stopping on continue + if ((flags & eHandleCommandFlagStopOnContinue) == 0) + debugger.SetAsyncExecution(false); + + m_command_source_depth++; + + debugger.RunIOHandler(io_handler_sp); + if (!m_command_source_flags.empty()) + m_command_source_flags.pop_back(); + m_command_source_depth--; + result.SetStatus(eReturnStatusSuccessFinishNoResult); + debugger.SetAsyncExecution(old_async_execution); + } else { + result.AppendErrorWithFormat( + "error: an error occurred read file '%s': %s\n", + cmd_file_path.c_str(), error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + + } else { + result.AppendErrorWithFormat( + "Error reading commands from file %s - file not found.\n", + cmd_file.GetFilename().AsCString("")); + result.SetStatus(eReturnStatusFailed); + return; + } } -CommandAlias* -CommandInterpreter::AddAlias (const char *alias_name, - lldb::CommandObjectSP& command_obj_sp, - const char *args_string) -{ - if (command_obj_sp.get()) - assert((this == &command_obj_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); - - std::unique_ptr command_alias_up(new CommandAlias(*this, - command_obj_sp, - args_string, - alias_name)); - - if (command_alias_up && command_alias_up->IsValid()) - { - m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get()); - return command_alias_up.release(); - } - +ScriptInterpreter *CommandInterpreter::GetScriptInterpreter(bool can_create) { + if (m_script_interpreter_sp) + return m_script_interpreter_sp.get(); + + if (!can_create) return nullptr; -} -bool -CommandInterpreter::RemoveAlias (const char *alias_name) -{ - auto pos = m_alias_dict.find(alias_name); - if (pos != m_alias_dict.end()) - { - m_alias_dict.erase(pos); - return true; - } - return false; + lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); + m_script_interpreter_sp = + PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); + return m_script_interpreter_sp.get(); +} + +bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution; } + +void CommandInterpreter::SetSynchronous(bool value) { + m_synchronous_execution = value; +} + +void CommandInterpreter::OutputFormattedHelpText(Stream &strm, + const char *prefix, + const char *help_text) { + const uint32_t max_columns = m_debugger.GetTerminalWidth(); + if (prefix == NULL) + prefix = ""; + + size_t prefix_width = strlen(prefix); + size_t line_width_max = max_columns - prefix_width; + const char *help_text_end = help_text + strlen(help_text); + const char *line_start = help_text; + if (line_width_max < 16) + line_width_max = help_text_end - help_text + prefix_width; + + strm.IndentMore(prefix_width); + while (line_start < help_text_end) { + // Break each line at the first newline or last space/tab before + // the maximum number of characters that fit on a line. Lines with no + // natural break are left unbroken to wrap. + const char *line_end = help_text_end; + const char *line_scan = line_start; + const char *line_scan_end = help_text_end; + while (line_scan < line_scan_end) { + char next = *line_scan; + if (next == '\t' || next == ' ') { + line_end = line_scan; + line_scan_end = line_start + line_width_max; + } else if (next == '\n' || next == '\0') { + line_end = line_scan; + break; + } + ++line_scan; + } + + // Prefix the first line, indent subsequent lines to line up + if (line_start == help_text) + strm.Write(prefix, prefix_width); + else + strm.Indent(); + strm.Write(line_start, line_end - line_start); + strm.EOL(); + + // When a line breaks at whitespace consume it before continuing + line_start = line_end; + char next = *line_start; + if (next == '\n') + ++line_start; + else + while (next == ' ' || next == '\t') + next = *(++line_start); + } + strm.IndentLess(prefix_width); } -bool -CommandInterpreter::RemoveCommand (const char *cmd) -{ - auto pos = m_command_dict.find(cmd); - if (pos != m_command_dict.end()) - { - if (pos->second->IsRemovable()) - { - // Only regular expression objects or python commands are removable - m_command_dict.erase(pos); - return true; - } - } - return false; +void CommandInterpreter::OutputFormattedHelpText(Stream &strm, + const char *word_text, + const char *separator, + const char *help_text, + size_t max_word_len) { + StreamString prefix_stream; + prefix_stream.Printf(" %-*s %s ", (int)max_word_len, word_text, separator); + OutputFormattedHelpText(strm, prefix_stream.GetData(), help_text); } -bool -CommandInterpreter::RemoveUser (const char *alias_name) -{ - CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); - if (pos != m_user_dict.end()) - { - m_user_dict.erase(pos); - return true; - } - return false; + +void CommandInterpreter::OutputHelpText(Stream &strm, const char *word_text, + const char *separator, + const char *help_text, + uint32_t max_word_len) { + int indent_size = max_word_len + strlen(separator) + 2; + + strm.IndentMore(indent_size); + + StreamString text_strm; + text_strm.Printf("%-*s %s %s", max_word_len, word_text, separator, help_text); + + const uint32_t max_columns = m_debugger.GetTerminalWidth(); + + size_t len = text_strm.GetSize(); + const char *text = text_strm.GetData(); + + uint32_t chars_left = max_columns; + + for (uint32_t i = 0; i < len; i++) { + if ((text[i] == ' ' && ::strchr((text + i + 1), ' ') && + chars_left < ::strchr((text + i + 1), ' ') - (text + i)) || + text[i] == '\n') { + chars_left = max_columns - indent_size; + strm.EOL(); + strm.Indent(); + } else { + strm.PutChar(text[i]); + chars_left--; + } + } + + strm.EOL(); + strm.IndentLess(indent_size); +} + +void CommandInterpreter::FindCommandsForApropos( + const char *search_word, StringList &commands_found, + StringList &commands_help, CommandObject::CommandMap &command_map) { + CommandObject::CommandMap::const_iterator pos; + + for (pos = command_map.begin(); pos != command_map.end(); ++pos) { + const char *command_name = pos->first.c_str(); + CommandObject *cmd_obj = pos->second.get(); + + const bool search_short_help = true; + const bool search_long_help = false; + const bool search_syntax = false; + const bool search_options = false; + if (strcasestr(command_name, search_word) || + cmd_obj->HelpTextContainsWord(search_word, search_short_help, + search_long_help, search_syntax, + search_options)) { + commands_found.AppendString(cmd_obj->GetCommandName()); + commands_help.AppendString(cmd_obj->GetHelp()); + } + + if (cmd_obj->IsMultiwordObject()) { + CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand(); + FindCommandsForApropos(search_word, commands_found, commands_help, + cmd_multiword->GetSubcommandDictionary()); + } + } +} + +void CommandInterpreter::FindCommandsForApropos(const char *search_word, + StringList &commands_found, + StringList &commands_help, + bool search_builtin_commands, + bool search_user_commands, + bool search_alias_commands) { + CommandObject::CommandMap::const_iterator pos; + + if (search_builtin_commands) + FindCommandsForApropos(search_word, commands_found, commands_help, + m_command_dict); + + if (search_user_commands) + FindCommandsForApropos(search_word, commands_found, commands_help, + m_user_dict); + + if (search_alias_commands) + FindCommandsForApropos(search_word, commands_found, commands_help, + m_alias_dict); +} + +void CommandInterpreter::UpdateExecutionContext( + ExecutionContext *override_context) { + if (override_context != nullptr) { + m_exe_ctx_ref = *override_context; + } else { + const bool adopt_selected = true; + m_exe_ctx_ref.SetTargetPtr(m_debugger.GetSelectedTarget().get(), + adopt_selected); + } +} + +size_t CommandInterpreter::GetProcessOutput() { + // The process has stuff waiting for stderr; get it and write it out to the + // appropriate place. + char stdio_buffer[1024]; + size_t len; + size_t total_bytes = 0; + Error error; + TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) { + ProcessSP process_sp(target_sp->GetProcessSP()); + if (process_sp) { + while ((len = process_sp->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), + error)) > 0) { + size_t bytes_written = len; + m_debugger.GetOutputFile()->Write(stdio_buffer, bytes_written); + total_bytes += len; + } + while ((len = process_sp->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), + error)) > 0) { + size_t bytes_written = len; + m_debugger.GetErrorFile()->Write(stdio_buffer, bytes_written); + total_bytes += len; + } + } + } + return total_bytes; +} + +void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) { + const bool is_interactive = io_handler.GetIsInteractive(); + if (is_interactive == false) { + // When we are not interactive, don't execute blank lines. This will happen + // sourcing a commands file. We don't want blank lines to repeat the + // previous + // command and cause any errors to occur (like redefining an alias, get an + // error + // and stop parsing the commands file). + if (line.empty()) + return; + + // When using a non-interactive file handle (like when sourcing commands + // from a file) + // we need to echo the command out so we don't just see the command output + // and no + // command... + if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) + io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), + line.c_str()); + } + + lldb_private::CommandReturnObject result; + HandleCommand(line.c_str(), eLazyBoolCalculate, result); + + // Now emit the command output text from the command we just executed + if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) { + // Display any STDOUT/STDERR _prior_ to emitting the command result text + GetProcessOutput(); + + if (!result.GetImmediateOutputStream()) { + const char *output = result.GetOutputData(); + if (output && output[0]) + io_handler.GetOutputStreamFile()->PutCString(output); + } + + // Now emit the command error text from the command we just executed + if (!result.GetImmediateErrorStream()) { + const char *error = result.GetErrorData(); + if (error && error[0]) + io_handler.GetErrorStreamFile()->PutCString(error); + } + } + + switch (result.GetStatus()) { + case eReturnStatusInvalid: + case eReturnStatusSuccessFinishNoResult: + case eReturnStatusSuccessFinishResult: + case eReturnStatusStarted: + break; + + case eReturnStatusSuccessContinuingNoResult: + case eReturnStatusSuccessContinuingResult: + if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue)) + io_handler.SetIsDone(true); + break; + + case eReturnStatusFailed: + m_num_errors++; + if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) + io_handler.SetIsDone(true); + break; + + case eReturnStatusQuit: + m_quit_requested = true; + io_handler.SetIsDone(true); + break; + } + + // Finally, if we're going to stop on crash, check that here: + if (!m_quit_requested && result.GetDidChangeProcessState() && + io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) { + bool should_stop = false; + TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) { + ProcessSP process_sp(target_sp->GetProcessSP()); + if (process_sp) { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) { + StopReason reason = thread_sp->GetStopReason(); + if ((reason == eStopReasonSignal || reason == eStopReasonException || + reason == eStopReasonInstrumentation) && + !result.GetAbnormalStopWasExpected()) { + should_stop = true; + break; + } + } + } + } + if (should_stop) { + io_handler.SetIsDone(true); + m_stopped_for_crash = true; + } + } +} + +bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) { + ExecutionContext exe_ctx(GetExecutionContext()); + Process *process = exe_ctx.GetProcessPtr(); + + if (process) { + StateType state = process->GetState(); + if (StateIsRunningState(state)) { + process->Halt(); + return true; // Don't do any updating when we are running + } + } + + ScriptInterpreter *script_interpreter = GetScriptInterpreter(false); + if (script_interpreter) { + if (script_interpreter->Interrupt()) + return true; + } + return false; +} + +void CommandInterpreter::GetLLDBCommandsFromIOHandler( + const char *prompt, IOHandlerDelegate &delegate, bool asynchronously, + void *baton) { + Debugger &debugger = GetDebugger(); + IOHandlerSP io_handler_sp( + new IOHandlerEditline(debugger, IOHandler::Type::CommandList, + "lldb", // Name of input reader for history + prompt, // Prompt + NULL, // Continuation prompt + true, // Get multiple lines + debugger.GetUseColor(), + 0, // Don't show line numbers + delegate)); // IOHandlerDelegate + + if (io_handler_sp) { + io_handler_sp->SetUserData(baton); + if (asynchronously) + debugger.PushIOHandler(io_handler_sp); + else + debugger.RunIOHandler(io_handler_sp); + } +} + +void CommandInterpreter::GetPythonCommandsFromIOHandler( + const char *prompt, IOHandlerDelegate &delegate, bool asynchronously, + void *baton) { + Debugger &debugger = GetDebugger(); + IOHandlerSP io_handler_sp( + new IOHandlerEditline(debugger, IOHandler::Type::PythonCode, + "lldb-python", // Name of input reader for history + prompt, // Prompt + NULL, // Continuation prompt + true, // Get multiple lines + debugger.GetUseColor(), + 0, // Don't show line numbers + delegate)); // IOHandlerDelegate + + if (io_handler_sp) { + io_handler_sp->SetUserData(baton); + if (asynchronously) + debugger.PushIOHandler(io_handler_sp); + else + debugger.RunIOHandler(io_handler_sp); + } } -void -CommandInterpreter::GetHelp (CommandReturnObject &result, - uint32_t cmd_types) -{ - const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue(); - if (help_prologue != NULL) - { - OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue); - } - - CommandObject::CommandMap::const_iterator pos; - size_t max_len = FindLongestCommandWord (m_command_dict); - - if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) - { - result.AppendMessage("Debugger commands:"); - result.AppendMessage(""); - - for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) - { - if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0)) - continue; - - OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), - max_len); - } - result.AppendMessage(""); - - } - - if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) - { - result.AppendMessageWithFormat("Current command abbreviations " - "(type '%shelp command alias' for more info):\n", - GetCommandPrefix()); - result.AppendMessage(""); - max_len = FindLongestCommandWord (m_alias_dict); +bool CommandInterpreter::IsActive() { + return m_debugger.IsTopIOHandler(m_command_io_handler_sp); +} - for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); ++alias_pos) - { - OutputFormattedHelpText (result.GetOutputStream(), alias_pos->first.c_str(), "--", alias_pos->second->GetHelp(), - max_len); - } - result.AppendMessage(""); - } - - if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) - { - result.AppendMessage ("Current user-defined commands:"); - result.AppendMessage(""); - max_len = FindLongestCommandWord (m_user_dict); - for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) - { - OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), - max_len); - } - result.AppendMessage(""); - } +lldb::IOHandlerSP +CommandInterpreter::GetIOHandler(bool force_create, + CommandInterpreterRunOptions *options) { + // Always re-create the IOHandlerEditline in case the input + // changed. The old instance might have had a non-interactive + // input and now it does or vice versa. + if (force_create || !m_command_io_handler_sp) { + // Always re-create the IOHandlerEditline in case the input + // changed. The old instance might have had a non-interactive + // input and now it does or vice versa. + uint32_t flags = 0; + + if (options) { + if (options->m_stop_on_continue == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnContinue; + if (options->m_stop_on_error == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnError; + if (options->m_stop_on_crash == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnCrash; + if (options->m_echo_commands != eLazyBoolNo) + flags |= eHandleCommandFlagEchoCommand; + if (options->m_print_results != eLazyBoolNo) + flags |= eHandleCommandFlagPrintResult; + } else { + flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; + } + + m_command_io_handler_sp.reset(new IOHandlerEditline( + m_debugger, IOHandler::Type::CommandInterpreter, + m_debugger.GetInputFile(), m_debugger.GetOutputFile(), + m_debugger.GetErrorFile(), flags, "lldb", m_debugger.GetPrompt(), + NULL, // Continuation prompt + false, // Don't enable multiple line input, just single line commands + m_debugger.GetUseColor(), + 0, // Don't show line numbers + *this)); + } + return m_command_io_handler_sp; +} + +void CommandInterpreter::RunCommandInterpreter( + bool auto_handle_events, bool spawn_thread, + CommandInterpreterRunOptions &options) { + // Always re-create the command interpreter when we run it in case + // any file handles have changed. + bool force_create = true; + m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); + m_stopped_for_crash = false; + + if (auto_handle_events) + m_debugger.StartEventHandlerThread(); + + if (spawn_thread) { + m_debugger.StartIOHandlerThread(); + } else { + m_debugger.ExecuteIOHandlers(); - result.AppendMessageWithFormat("For more information on any command, type '%shelp '.\n", - GetCommandPrefix()); + if (auto_handle_events) + m_debugger.StopEventHandlerThread(); + } } CommandObject * -CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) -{ - // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will - // eventually be invoked by the given command line. - - CommandObject *cmd_obj = nullptr; - size_t start = command_string.find_first_not_of (k_white_space); - size_t end = 0; - bool done = false; - while (!done) - { - if (start != std::string::npos) - { - // Get the next word from command_string. - end = command_string.find_first_of (k_white_space, start); - if (end == std::string::npos) - end = command_string.size(); - std::string cmd_word = command_string.substr (start, end - start); - - if (cmd_obj == nullptr) - // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid - // command or alias. - cmd_obj = GetCommandObject (cmd_word.c_str()); - else if (cmd_obj->IsMultiwordObject ()) - { - // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. - CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); - if (sub_cmd_obj) - cmd_obj = sub_cmd_obj; - else // cmd_word was not a valid sub-command word, so we are done - done = true; - } - else - // We have a cmd_obj and it is not a multi-word object, so we are done. - done = true; - - // If we didn't find a valid command object, or our command object is not a multi-word object, or - // we are at the end of the command_string, then we are done. Otherwise, find the start of the - // next word. - - if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) - done = true; - else - start = command_string.find_first_not_of (k_white_space, end); - } +CommandInterpreter::ResolveCommandImpl(std::string &command_line, + CommandReturnObject &result) { + std::string scratch_command(command_line); // working copy so we don't modify + // command_line unless we succeed + CommandObject *cmd_obj = nullptr; + StreamString revised_command_line; + bool wants_raw_input = false; + size_t actual_cmd_name_len = 0; + std::string next_word; + StringList matches; + bool done = false; + while (!done) { + char quote_char = '\0'; + std::string suffix; + ExtractCommand(scratch_command, next_word, suffix, quote_char); + if (cmd_obj == nullptr) { + std::string full_name; + bool is_alias = GetAliasFullName(next_word.c_str(), full_name); + cmd_obj = GetCommandObject(next_word.c_str(), &matches); + bool is_real_command = + (is_alias == false) || + (cmd_obj != nullptr && cmd_obj->IsAlias() == false); + if (!is_real_command) { + matches.Clear(); + std::string alias_result; + cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, + alias_result, result); + revised_command_line.Printf("%s", alias_result.c_str()); + if (cmd_obj) { + wants_raw_input = cmd_obj->WantsRawCommandString(); + actual_cmd_name_len = strlen(cmd_obj->GetCommandName()); + } + } else { + if (!cmd_obj) + cmd_obj = GetCommandObject(next_word.c_str(), &matches); + if (cmd_obj) { + actual_cmd_name_len += strlen(cmd_obj->GetCommandName()); + revised_command_line.Printf("%s", cmd_obj->GetCommandName()); + wants_raw_input = cmd_obj->WantsRawCommandString(); + } else { + revised_command_line.Printf("%s", next_word.c_str()); + } + } + } else { + if (cmd_obj->IsMultiwordObject()) { + CommandObject *sub_cmd_obj = + cmd_obj->GetSubcommandObject(next_word.c_str()); + if (sub_cmd_obj) { + // The subcommand's name includes the parent command's name, + // so restart rather than append to the revised_command_line. + actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1; + revised_command_line.Clear(); + revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName()); + cmd_obj = sub_cmd_obj; + wants_raw_input = cmd_obj->WantsRawCommandString(); + } else { + if (quote_char) + revised_command_line.Printf(" %c%s%s%c", quote_char, + next_word.c_str(), suffix.c_str(), + quote_char); + else + revised_command_line.Printf(" %s%s", next_word.c_str(), + suffix.c_str()); + done = true; + } + } else { + if (quote_char) + revised_command_line.Printf(" %c%s%s%c", quote_char, + next_word.c_str(), suffix.c_str(), + quote_char); else - // Unable to find any more words. - done = true; - } - - if (end == command_string.size()) - command_string.clear(); - else - command_string = command_string.substr(end); - - return cmd_obj; -} - -static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; -static void -StripLeadingSpaces (std::string &s) -{ - if (!s.empty()) - { - size_t pos = s.find_first_not_of (k_white_space); - if (pos == std::string::npos) - s.clear(); - else if (pos == 0) - return; - s.erase (0, pos); - } -} - -static size_t -FindArgumentTerminator (const std::string &s) -{ - const size_t s_len = s.size(); - size_t offset = 0; - while (offset < s_len) - { - size_t pos = s.find ("--", offset); - if (pos == std::string::npos) - break; - if (pos > 0) - { - if (isspace(s[pos-1])) - { - // Check if the string ends "\s--" (where \s is a space character) - // or if we have "\s--\s". - if ((pos + 2 >= s_len) || isspace(s[pos+2])) - { - return pos; - } - } - } - offset = pos + 2; - } - return std::string::npos; -} - -static bool -ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) -{ - command.clear(); - suffix.clear(); - StripLeadingSpaces (command_string); - - bool result = false; - quote_char = '\0'; - - if (!command_string.empty()) - { - const char first_char = command_string[0]; - if (first_char == '\'' || first_char == '"') - { - quote_char = first_char; - const size_t end_quote_pos = command_string.find (quote_char, 1); - if (end_quote_pos == std::string::npos) - { - command.swap (command_string); - command_string.erase (); - } - else - { - command.assign (command_string, 1, end_quote_pos - 1); - if (end_quote_pos + 1 < command_string.size()) - command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); - else - command_string.erase (); - } - } - else - { - const size_t first_space_pos = command_string.find_first_of (k_white_space); - if (first_space_pos == std::string::npos) - { - command.swap (command_string); - command_string.erase(); - } - else - { - command.assign (command_string, 0, first_space_pos); - command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); - } - } - result = true; - } - - - if (!command.empty()) - { - // actual commands can't start with '-' or '_' - if (command[0] != '-' && command[0] != '_') - { - size_t pos = command.find_first_not_of(k_valid_command_chars); - if (pos > 0 && pos != std::string::npos) - { - suffix.assign (command.begin() + pos, command.end()); - command.erase (pos); - } - } - } - - return result; -} - -CommandObject * -CommandInterpreter::BuildAliasResult (const char *alias_name, - std::string &raw_input_string, - std::string &alias_result, - CommandReturnObject &result) -{ - CommandObject *alias_cmd_obj = nullptr; - Args cmd_args (raw_input_string); - alias_cmd_obj = GetCommandObject (alias_name); - StreamString result_str; - - if (alias_cmd_obj && alias_cmd_obj->IsAlias()) - { - std::pair desugared = ((CommandAlias*)alias_cmd_obj)->Desugar(); - OptionArgVectorSP option_arg_vector_sp = desugared.second; - alias_cmd_obj = desugared.first.get(); - std::string alias_name_str = alias_name; - if ((cmd_args.GetArgumentCount() == 0) - || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) - cmd_args.Unshift (alias_name); - - result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); - - if (option_arg_vector_sp.get()) - { - OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); - - for (size_t i = 0; i < option_arg_vector->size(); ++i) - { - OptionArgPair option_pair = (*option_arg_vector)[i]; - OptionArgValue value_pair = option_pair.second; - int value_type = value_pair.first; - std::string option = option_pair.first; - std::string value = value_pair.second; - if (option.compare ("") == 0) - result_str.Printf (" %s", value.c_str()); - else - { - result_str.Printf (" %s", option.c_str()); - if (value_type != OptionParser::eNoArgument) - { - if (value_type != OptionParser::eOptionalArgument) - result_str.Printf (" "); - int index = GetOptionArgumentPosition (value.c_str()); - if (index == 0) - result_str.Printf ("%s", value.c_str()); - else if (static_cast(index) >= cmd_args.GetArgumentCount()) - { - - result.AppendErrorWithFormat - ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", - index); - result.SetStatus (eReturnStatusFailed); - return nullptr; - } - else - { - size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); - if (strpos != std::string::npos) - raw_input_string = raw_input_string.erase (strpos, - strlen (cmd_args.GetArgumentAtIndex (index))); - result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); - } - } - } - } - } - - alias_result = result_str.GetData(); - } - return alias_cmd_obj; -} - -Error -CommandInterpreter::PreprocessCommand (std::string &command) -{ - // The command preprocessor needs to do things to the command - // line before any parsing of arguments or anything else is done. - // The only current stuff that gets preprocessed is anything enclosed - // in backtick ('`') characters is evaluated as an expression and - // the result of the expression must be a scalar that can be substituted - // into the command. An example would be: - // (lldb) memory read `$rsp + 20` - Error error; // Error for any expressions that might not evaluate - size_t start_backtick; - size_t pos = 0; - while ((start_backtick = command.find ('`', pos)) != std::string::npos) - { - if (start_backtick > 0 && command[start_backtick-1] == '\\') - { - // The backtick was preceded by a '\' character, remove the slash - // and don't treat the backtick as the start of an expression - command.erase(start_backtick-1, 1); - // No need to add one to start_backtick since we just deleted a char - pos = start_backtick; - } - else - { - const size_t expr_content_start = start_backtick + 1; - const size_t end_backtick = command.find ('`', expr_content_start); - if (end_backtick == std::string::npos) - return error; - else if (end_backtick == expr_content_start) - { - // Empty expression (two backticks in a row) - command.erase (start_backtick, 2); - } - else - { - std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); - - ExecutionContext exe_ctx(GetExecutionContext()); - Target *target = exe_ctx.GetTargetPtr(); - // Get a dummy target to allow for calculator mode while processing backticks. - // This also helps break the infinite loop caused when target is null. - if (!target) - target = m_debugger.GetDummyTarget(); - if (target) - { - ValueObjectSP expr_result_valobj_sp; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetKeepInMemory(false); - options.SetTryAllThreads(true); - options.SetTimeoutUsec(0); - - ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), - exe_ctx.GetFramePtr(), - expr_result_valobj_sp, - options); - - if (expr_result == eExpressionCompleted) - { - Scalar scalar; - if (expr_result_valobj_sp) - expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true); - if (expr_result_valobj_sp->ResolveValue (scalar)) - { - command.erase (start_backtick, end_backtick - start_backtick + 1); - StreamString value_strm; - const bool show_type = false; - scalar.GetValue (&value_strm, show_type); - size_t value_string_size = value_strm.GetSize(); - if (value_string_size) - { - command.insert (start_backtick, value_strm.GetData(), value_string_size); - pos = start_backtick + value_string_size; - continue; - } - else - { - error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); - } - } - else - { - error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); - } - } - else - { - if (expr_result_valobj_sp) - error = expr_result_valobj_sp->GetError(); - if (error.Success()) - { - - switch (expr_result) - { - case eExpressionSetupError: - error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); - break; - case eExpressionParseError: - error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str()); - break; - case eExpressionResultUnavailable: - error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str()); - break; - case eExpressionCompleted: - break; - case eExpressionDiscarded: - error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); - break; - case eExpressionInterrupted: - error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); - break; - case eExpressionHitBreakpoint: - error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); - break; - case eExpressionTimedOut: - error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); - break; - case eExpressionStoppedForDebug: - error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str()); - break; - } - } - } - } - } - if (error.Fail()) - break; - } - } - return error; -} - - -bool -CommandInterpreter::HandleCommand (const char *command_line, - LazyBool lazy_add_to_history, - CommandReturnObject &result, - ExecutionContext *override_context, - bool repeat_on_empty_command, - bool no_context_switching) - -{ - - std::string command_string (command_line); - std::string original_command_string (command_line); - - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); - Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); - - // Make a scoped cleanup object that will clear the crash description string - // on exit of this function. - lldb_utility::CleanUp crash_description_cleanup(nullptr, Host::SetCrashDescription); - - if (log) - log->Printf ("Processing command: %s", command_line); - - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "Handling command: %s.", command_line); - - if (!no_context_switching) - UpdateExecutionContext (override_context); - - bool add_to_history; - if (lazy_add_to_history == eLazyBoolCalculate) - add_to_history = (m_command_source_depth == 0); - else - add_to_history = (lazy_add_to_history == eLazyBoolYes); - - bool empty_command = false; - bool comment_command = false; - if (command_string.empty()) - empty_command = true; - else - { - const char *k_space_characters = "\t\n\v\f\r "; - - size_t non_space = command_string.find_first_not_of (k_space_characters); - // Check for empty line or comment line (lines whose first - // non-space character is the comment character for this interpreter) - if (non_space == std::string::npos) - empty_command = true; - else if (command_string[non_space] == m_comment_char) - comment_command = true; - else if (command_string[non_space] == CommandHistory::g_repeat_char) - { - const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); - if (history_string == nullptr) - { - result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - add_to_history = false; - command_string = history_string; - original_command_string = history_string; - } - } - - if (empty_command) - { - if (repeat_on_empty_command) - { - if (m_command_history.IsEmpty()) - { - result.AppendError ("empty command"); - result.SetStatus(eReturnStatusFailed); - return false; - } - else - { - command_line = m_repeat_command.c_str(); - command_string = command_line; - original_command_string = command_line; - if (m_repeat_command.empty()) - { - result.AppendErrorWithFormat("No auto repeat.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - add_to_history = false; - } - else - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } - } - else if (comment_command) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } - - - Error error (PreprocessCommand (command_string)); - - if (error.Fail()) - { - result.AppendError (error.AsCString()); + revised_command_line.Printf(" %s%s", next_word.c_str(), + suffix.c_str()); + done = true; + } + } + + if (cmd_obj == nullptr) { + const size_t num_matches = matches.GetSize(); + if (matches.GetSize() > 1) { + StreamString error_msg; + error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", + next_word.c_str()); + + for (uint32_t i = 0; i < num_matches; ++i) { + error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i)); + } + result.AppendRawError(error_msg.GetString().c_str()); + } else { + // We didn't have only one match, otherwise we wouldn't get here. + assert(num_matches == 0); + result.AppendErrorWithFormat("'%s' is not a valid command.\n", + next_word.c_str()); + } + result.SetStatus(eReturnStatusFailed); + return nullptr; + } + + if (cmd_obj->IsMultiwordObject()) { + if (!suffix.empty()) { + result.AppendErrorWithFormat( + "command '%s' did not recognize '%s%s%s' as valid (subcommand " + "might be invalid).\n", + cmd_obj->GetCommandName(), + next_word.empty() ? "" : next_word.c_str(), + next_word.empty() ? " -- " : " ", suffix.c_str()); result.SetStatus(eReturnStatusFailed); - return false; - } - - // Phase 1. - - // Before we do ANY kind of argument processing, we need to figure out what - // the real/final command object is for the specified command. This gets - // complicated by the fact that the user could have specified an alias, and, - // in translating the alias, there may also be command options and/or even - // data (including raw text strings) that need to be found and inserted into - // the command line as part of the translation. So this first step is plain - // look-up and replacement, resulting in: - // 1. the command object whose Execute method will actually be called - // 2. a revised command string, with all substitutions and replacements - // taken care of - // From 1 above, we can determine whether the Execute function wants raw - // input or not. - - CommandObject *cmd_obj = ResolveCommandImpl(command_string, result); - - // Although the user may have abbreviated the command, the command_string now - // has the command expanded to the full name. For example, if the input - // was "br s -n main", command_string is now "breakpoint set -n main". - - if (log) - { - log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : ""); - log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str()); - const bool wants_raw_input = (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false; - log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); - } - - // Phase 2. - // Take care of things like setting up the history command & calling the appropriate Execute method on the - // CommandObject, with the appropriate arguments. - - if (cmd_obj != nullptr) - { - if (add_to_history) - { - Args command_args (command_string); - const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); - if (repeat_command != nullptr) - m_repeat_command.assign(repeat_command); - else - m_repeat_command.assign(original_command_string.c_str()); - - m_command_history.AppendString (original_command_string); - } - - std::string remainder; - const std::size_t actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); - if (actual_cmd_name_len < command_string.length()) - remainder = command_string.substr (actual_cmd_name_len); - - // Remove any initial spaces - size_t pos = remainder.find_first_not_of (k_white_space); - if (pos != 0 && pos != std::string::npos) - remainder.erase(0, pos); - - if (log) - log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); - - cmd_obj->Execute (remainder.c_str(), result); - } - else - { - // We didn't find the first command object, so complete the first argument. - Args command_args (command_string); - StringList matches; - int num_matches; - int cursor_index = 0; - int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); - bool word_complete; - num_matches = HandleCompletionMatches (command_args, - cursor_index, - cursor_char_position, - 0, - -1, - word_complete, - matches); - - if (num_matches > 0) - { - std::string error_msg; - error_msg.assign ("ambiguous command '"); - error_msg.append(command_args.GetArgumentAtIndex(0)); - error_msg.append ("'."); - - error_msg.append (" Possible completions:"); - for (int i = 0; i < num_matches; i++) - { - error_msg.append ("\n\t"); - error_msg.append (matches.GetStringAtIndex (i)); - } - error_msg.append ("\n"); - result.AppendRawError (error_msg.c_str()); - } - else - result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0)); - - result.SetStatus (eReturnStatusFailed); - } - - if (log) - log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); - - return result.Succeeded(); -} - -int -CommandInterpreter::HandleCompletionMatches (Args &parsed_line, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - int num_command_matches = 0; - bool look_for_subcommand = false; - - // For any of the command completions a unique match will be a complete word. - word_complete = true; - - if (cursor_index == -1) - { - // We got nothing on the command line, so return the list of commands - bool include_aliases = true; - num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); - } - else if (cursor_index == 0) - { - // The cursor is in the first argument, so just do a lookup in the dictionary. - CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); - num_command_matches = matches.GetSize(); - - if (num_command_matches == 1 - && cmd_obj && cmd_obj->IsMultiwordObject() - && matches.GetStringAtIndex(0) != nullptr - && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) - { - if (parsed_line.GetArgumentCount() == 1) - { - word_complete = true; - } - else - { - look_for_subcommand = true; - num_command_matches = 0; - matches.DeleteStringAtIndex(0); - parsed_line.AppendArgument (""); - cursor_index++; - cursor_char_position = 0; - } - } - } - - if (cursor_index > 0 || look_for_subcommand) - { - // We are completing further on into a commands arguments, so find the command and tell it - // to complete the command. - // First see if there is a matching initial command: - CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); - if (command_object == nullptr) - { - return 0; - } - else - { - parsed_line.Shift(); - cursor_index--; - num_command_matches = command_object->HandleCompletion (parsed_line, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } - } - - return num_command_matches; - -} - -int -CommandInterpreter::HandleCompletion (const char *current_line, - const char *cursor, - const char *last_char, - int match_start_point, - int max_return_elements, - StringList &matches) -{ - // We parse the argument up to the cursor, so the last argument in parsed_line is - // the one containing the cursor, and the cursor is after the last character. - - Args parsed_line(llvm::StringRef(current_line, last_char - current_line)); - Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line)); - - // Don't complete comments, and if the line we are completing is just the history repeat character, - // substitute the appropriate history line. - const char *first_arg = parsed_line.GetArgumentAtIndex(0); - if (first_arg) - { - if (first_arg[0] == m_comment_char) - return 0; - else if (first_arg[0] == CommandHistory::g_repeat_char) - { - const char *history_string = m_command_history.FindString (first_arg); - if (history_string != nullptr) - { - matches.Clear(); - matches.InsertStringAtIndex(0, history_string); - return -2; - } - else - return 0; - - } - } - - - int num_args = partial_parsed_line.GetArgumentCount(); - int cursor_index = partial_parsed_line.GetArgumentCount() - 1; - int cursor_char_position; - - if (cursor_index == -1) - cursor_char_position = 0; - else - cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); - - if (cursor > current_line && cursor[-1] == ' ') - { - // We are just after a space. If we are in an argument, then we will continue - // parsing, but if we are between arguments, then we have to complete whatever the next - // element would be. - // We can distinguish the two cases because if we are in an argument (e.g. because the space is - // protected by a quote) then the space will also be in the parsed argument... - - const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index); - if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ') - { - parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0'); - cursor_index++; - cursor_char_position = 0; - } - } - - int num_command_matches; - - matches.Clear(); - - // Only max_return_elements == -1 is supported at present: - assert (max_return_elements == -1); - bool word_complete; - num_command_matches = HandleCompletionMatches (parsed_line, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - - if (num_command_matches <= 0) - return num_command_matches; - - if (num_args == 0) - { - // If we got an empty string, insert nothing. - matches.InsertStringAtIndex(0, ""); - } - else - { - // Now figure out if there is a common substring, and if so put that in element 0, otherwise - // put an empty string in element 0. - std::string command_partial_str; - if (cursor_index >= 0) - command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), - parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); - - std::string common_prefix; - matches.LongestCommonPrefix (common_prefix); - const size_t partial_name_len = command_partial_str.size(); - common_prefix.erase (0, partial_name_len); - - // If we matched a unique single command, add a space... - // Only do this if the completer told us this was a complete word, however... - if (num_command_matches == 1 && word_complete) - { - char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); - common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); - if (quote_char != '\0') - common_prefix.push_back(quote_char); - common_prefix.push_back(' '); - } - matches.InsertStringAtIndex(0, common_prefix.c_str()); - } - return num_command_matches; -} - - -CommandInterpreter::~CommandInterpreter () -{ -} - -void -CommandInterpreter::UpdatePrompt (const char *new_prompt) -{ - EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; - BroadcastEvent (prompt_change_event_sp); - if (m_command_io_handler_sp) - m_command_io_handler_sp->SetPrompt(new_prompt); -} - - -bool -CommandInterpreter::Confirm (const char *message, bool default_answer) -{ - // Check AutoConfirm first: - if (m_debugger.GetAutoConfirm()) - return default_answer; - - IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger, - message, - default_answer); - IOHandlerSP io_handler_sp (confirm); - m_debugger.RunIOHandler (io_handler_sp); - return confirm->GetResponse(); -} - -CommandAlias* -CommandInterpreter::GetAlias (const char *alias_name) -{ - OptionArgVectorSP ret_val; - - std::string alias (alias_name); - - auto pos = m_alias_dict.find(alias); - if (pos != m_alias_dict.end()) - return (CommandAlias*)pos->second.get(); - - return nullptr; -} - -bool -CommandInterpreter::HasCommands () -{ - return (!m_command_dict.empty()); -} - -bool -CommandInterpreter::HasAliases () -{ - return (!m_alias_dict.empty()); -} - -bool -CommandInterpreter::HasUserCommands () -{ - return (!m_user_dict.empty()); -} - -bool -CommandInterpreter::HasAliasOptions () -{ - return HasAliases(); -} - -void -CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, - const char *alias_name, - Args &cmd_args, - std::string &raw_input_string, - CommandReturnObject &result) -{ - OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments(); - - bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); - - // Make sure that the alias name is the 0th element in cmd_args - std::string alias_name_str = alias_name; - if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) - cmd_args.Unshift (alias_name); - - Args new_args (alias_cmd_obj->GetCommandName()); - if (new_args.GetArgumentCount() == 2) - new_args.Shift(); - - if (option_arg_vector_sp.get()) - { - if (wants_raw_input) - { - // We have a command that both has command options and takes raw input. Make *sure* it has a - // " -- " in the right place in the raw_input_string. - size_t pos = raw_input_string.find(" -- "); - if (pos == std::string::npos) - { - // None found; assume it goes at the beginning of the raw input string - raw_input_string.insert (0, " -- "); - } - } - - OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); - const size_t old_size = cmd_args.GetArgumentCount(); - std::vector used (old_size + 1, false); - - used[0] = true; - - for (size_t i = 0; i < option_arg_vector->size(); ++i) - { - OptionArgPair option_pair = (*option_arg_vector)[i]; - OptionArgValue value_pair = option_pair.second; - int value_type = value_pair.first; - std::string option = option_pair.first; - std::string value = value_pair.second; - if (option.compare ("") == 0) - { - if (!wants_raw_input - || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice - new_args.AppendArgument (value.c_str()); - } - else - { - if (value_type != OptionParser::eOptionalArgument) - new_args.AppendArgument (option.c_str()); - if (value.compare ("") != 0) - { - int index = GetOptionArgumentPosition (value.c_str()); - if (index == 0) - { - // value was NOT a positional argument; must be a real value - if (value_type != OptionParser::eOptionalArgument) - new_args.AppendArgument (value.c_str()); - else - { - char buffer[255]; - ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); - new_args.AppendArgument (buffer); - } - - } - else if (static_cast(index) >= cmd_args.GetArgumentCount()) - { - result.AppendErrorWithFormat - ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", - index); - result.SetStatus (eReturnStatusFailed); - return; - } - else - { - // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string - size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); - if (strpos != std::string::npos) - { - raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); - } - - if (value_type != OptionParser::eOptionalArgument) - new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); - else - { - char buffer[255]; - ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), - cmd_args.GetArgumentAtIndex (index)); - new_args.AppendArgument (buffer); - } - used[index] = true; - } - } - } - } - - for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) - { - if (!used[j] && !wants_raw_input) - new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); - } - - cmd_args.Clear(); - cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); - } - else - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - // This alias was not created with any options; nothing further needs to be done, unless it is a command that - // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw - // input string. - if (wants_raw_input) - { - cmd_args.Clear(); - cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); - } - return; - } - - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return; -} - - -int -CommandInterpreter::GetOptionArgumentPosition (const char *in_string) -{ - int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position - // of zero. - - const char *cptr = in_string; - - // Does it start with '%' - if (cptr[0] == '%') - { - ++cptr; - - // Is the rest of it entirely digits? - if (isdigit (cptr[0])) - { - const char *start = cptr; - while (isdigit (cptr[0])) - ++cptr; - - // We've gotten to the end of the digits; are we at the end of the string? - if (cptr[0] == '\0') - position = atoi (start); - } - } - - return position; -} - -void -CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) -{ - FileSpec init_file; - if (in_cwd) - { - ExecutionContext exe_ctx(GetExecutionContext()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - // In the current working directory we don't load any program specific - // .lldbinit files, we only look for a ".lldbinit" file. - if (m_skip_lldbinit_files) - return; - - LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile (); - if (should_load == eLoadCWDlldbinitWarn) - { - FileSpec dot_lldb (".lldbinit", true); - llvm::SmallString<64> home_dir_path; - llvm::sys::path::home_directory (home_dir_path); - FileSpec homedir_dot_lldb (home_dir_path.c_str(), false); - homedir_dot_lldb.AppendPathComponent (".lldbinit"); - homedir_dot_lldb.ResolvePath (); - if (dot_lldb.Exists () - && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) - { - result.AppendErrorWithFormat ( - "There is a .lldbinit file in the current directory which is not being read.\n" - "To silence this warning without sourcing in the local .lldbinit,\n" - "add the following to the lldbinit file in your home directory:\n" - " settings set target.load-cwd-lldbinit false\n" - "To allow lldb to source .lldbinit files in the current working directory,\n" - "set the value of this variable to true. Only do so if you understand and\n" - "accept the security risk."); - result.SetStatus (eReturnStatusFailed); - return; - } - } - else if (should_load == eLoadCWDlldbinitTrue) - { - init_file.SetFile ("./.lldbinit", true); - } - } - } - else - { - // If we aren't looking in the current working directory we are looking - // in the home directory. We will first see if there is an application - // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a - // "-" and the name of the program. If this file doesn't exist, we fall - // back to just the "~/.lldbinit" file. We also obey any requests to not - // load the init files. - llvm::SmallString<64> home_dir_path; - llvm::sys::path::home_directory(home_dir_path); - FileSpec profilePath(home_dir_path.c_str(), false); - profilePath.AppendPathComponent(".lldbinit"); - std::string init_file_path = profilePath.GetPath(); - - if (m_skip_app_init_files == false) - { - FileSpec program_file_spec(HostInfo::GetProgramFileSpec()); - const char *program_name = program_file_spec.GetFilename().AsCString(); - - if (program_name) - { - char program_init_file_name[PATH_MAX]; - ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name); - init_file.SetFile (program_init_file_name, true); - if (!init_file.Exists()) - init_file.Clear(); - } - } - - if (!init_file && !m_skip_lldbinit_files) - init_file.SetFile (init_file_path.c_str(), false); - } - - // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting - // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). - - if (init_file.Exists()) - { - const bool saved_batch = SetBatchCommandMode (true); - CommandInterpreterRunOptions options; - options.SetSilent (true); - options.SetStopOnError (false); - options.SetStopOnContinue (true); - - HandleCommandsFromFile (init_file, - nullptr, // Execution context - options, - result); - SetBatchCommandMode (saved_batch); - } - else - { - // nothing to be done if the file doesn't exist - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } -} - -const char * -CommandInterpreter::GetCommandPrefix() -{ - const char * prefix = GetDebugger().GetIOHandlerCommandPrefix(); - return prefix == NULL ? "" : prefix; -} - -PlatformSP -CommandInterpreter::GetPlatform (bool prefer_target_platform) -{ - PlatformSP platform_sp; - if (prefer_target_platform) - { - ExecutionContext exe_ctx(GetExecutionContext()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - platform_sp = target->GetPlatform(); - } - - if (!platform_sp) - platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); - return platform_sp; -} - -void -CommandInterpreter::HandleCommands (const StringList &commands, - ExecutionContext *override_context, - CommandInterpreterRunOptions &options, - CommandReturnObject &result) -{ - size_t num_lines = commands.GetSize(); - - // If we are going to continue past a "continue" then we need to run the commands synchronously. - // Make sure you reset this value anywhere you return from the function. - - bool old_async_execution = m_debugger.GetAsyncExecution(); - - // If we've been given an execution context, set it at the start, but don't keep resetting it or we will - // cause series of commands that change the context, then do an operation that relies on that context to fail. - - if (override_context != nullptr) - UpdateExecutionContext (override_context); - - if (!options.GetStopOnContinue()) - { - m_debugger.SetAsyncExecution (false); - } - - for (size_t idx = 0; idx < num_lines; idx++) - { - const char *cmd = commands.GetStringAtIndex(idx); - if (cmd[0] == '\0') - continue; - - if (options.GetEchoCommands()) - { - result.AppendMessageWithFormat ("%s %s\n", - m_debugger.GetPrompt(), - cmd); - } - - CommandReturnObject tmp_result; - // If override_context is not NULL, pass no_context_switching = true for - // HandleCommand() since we updated our context already. - - // We might call into a regex or alias command, in which case the add_to_history will get lost. This - // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. - if (!options.GetAddToHistory()) - m_command_source_depth++; - bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result, - nullptr, /* override_context */ - true, /* repeat_on_empty_command */ - override_context != nullptr /* no_context_switching */); - if (!options.GetAddToHistory()) - m_command_source_depth--; - - if (options.GetPrintResults()) - { - if (tmp_result.Succeeded()) - result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); - } - - if (!success || !tmp_result.Succeeded()) - { - const char *error_msg = tmp_result.GetErrorData(); - if (error_msg == nullptr || error_msg[0] == '\0') - error_msg = ".\n"; - if (options.GetStopOnError()) - { - result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", - (uint64_t)idx, cmd, error_msg); - result.SetStatus (eReturnStatusFailed); - m_debugger.SetAsyncExecution (old_async_execution); - return; - } - else if (options.GetPrintResults()) - { - result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", - (uint64_t)idx + 1, - cmd, - error_msg); - } - } - - if (result.GetImmediateOutputStream()) - result.GetImmediateOutputStream()->Flush(); - - if (result.GetImmediateErrorStream()) - result.GetImmediateErrorStream()->Flush(); - - // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution - // could be running (for instance in Breakpoint Commands. - // So we check the return value to see if it is has running in it. - if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) - || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) - { - if (options.GetStopOnContinue()) - { - // If we caused the target to proceed, and we're going to stop in that case, set the - // status in our real result before returning. This is an error if the continue was not the - // last command in the set of commands to be run. - if (idx != num_lines - 1) - result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n", - (uint64_t)idx + 1, cmd); - else - result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd); - - result.SetStatus(tmp_result.GetStatus()); - m_debugger.SetAsyncExecution (old_async_execution); - - return; - } - } - - // Also check for "stop on crash here: - bool should_stop = false; - if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) - { - TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) - { - ProcessSP process_sp (target_sp->GetProcessSP()); - if (process_sp) - { - for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) - { - StopReason reason = thread_sp->GetStopReason(); - if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) - { - should_stop = true; - break; - } - } - } - } - if (should_stop) - { - if (idx != num_lines - 1) - result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", - (uint64_t)idx + 1, cmd); - else - result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); - - result.SetStatus(tmp_result.GetStatus()); - m_debugger.SetAsyncExecution (old_async_execution); - - return; - } - } - - } - - result.SetStatus (eReturnStatusSuccessFinishResult); - m_debugger.SetAsyncExecution (old_async_execution); - - return; -} - -// Make flags that we can pass into the IOHandler so our delegates can do the right thing -enum { - eHandleCommandFlagStopOnContinue = (1u << 0), - eHandleCommandFlagStopOnError = (1u << 1), - eHandleCommandFlagEchoCommand = (1u << 2), - eHandleCommandFlagPrintResult = (1u << 3), - eHandleCommandFlagStopOnCrash = (1u << 4) -}; - -void -CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, - ExecutionContext *context, - CommandInterpreterRunOptions &options, - CommandReturnObject &result) -{ - if (cmd_file.Exists()) - { - StreamFileSP input_file_sp (new StreamFile()); - - std::string cmd_file_path = cmd_file.GetPath(); - Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead); - - if (error.Success()) - { - Debugger &debugger = GetDebugger(); - - uint32_t flags = 0; - - if (options.m_stop_on_continue == eLazyBoolCalculate) - { - if (m_command_source_flags.empty()) - { - // Stop on continue by default - flags |= eHandleCommandFlagStopOnContinue; - } - else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue) - { - flags |= eHandleCommandFlagStopOnContinue; - } - } - else if (options.m_stop_on_continue == eLazyBoolYes) - { - flags |= eHandleCommandFlagStopOnContinue; - } - - if (options.m_stop_on_error == eLazyBoolCalculate) - { - if (m_command_source_flags.empty()) - { - if (GetStopCmdSourceOnError()) - flags |= eHandleCommandFlagStopOnError; - } - else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError) - { - flags |= eHandleCommandFlagStopOnError; - } - } - else if (options.m_stop_on_error == eLazyBoolYes) - { - flags |= eHandleCommandFlagStopOnError; - } - - if (options.GetStopOnCrash()) - { - if (m_command_source_flags.empty()) - { - // Echo command by default - flags |= eHandleCommandFlagStopOnCrash; - } - else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) - { - flags |= eHandleCommandFlagStopOnCrash; - } - } - - if (options.m_echo_commands == eLazyBoolCalculate) - { - if (m_command_source_flags.empty()) - { - // Echo command by default - flags |= eHandleCommandFlagEchoCommand; - } - else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand) - { - flags |= eHandleCommandFlagEchoCommand; - } - } - else if (options.m_echo_commands == eLazyBoolYes) - { - flags |= eHandleCommandFlagEchoCommand; - } - - if (options.m_print_results == eLazyBoolCalculate) - { - if (m_command_source_flags.empty()) - { - // Print output by default - flags |= eHandleCommandFlagPrintResult; - } - else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult) - { - flags |= eHandleCommandFlagPrintResult; - } - } - else if (options.m_print_results == eLazyBoolYes) - { - flags |= eHandleCommandFlagPrintResult; - } - - if (flags & eHandleCommandFlagPrintResult) - { - debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str()); - } - - // Used for inheriting the right settings when "command source" might have - // nested "command source" commands - lldb::StreamFileSP empty_stream_sp; - m_command_source_flags.push_back(flags); - IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, - IOHandler::Type::CommandInterpreter, - input_file_sp, - empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream - empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream - flags, - nullptr, // Pass in NULL for "editline_name" so no history is saved, or written - debugger.GetPrompt(), - NULL, - false, // Not multi-line - debugger.GetUseColor(), - 0, - *this)); - const bool old_async_execution = debugger.GetAsyncExecution(); - - // Set synchronous execution if we are not stopping on continue - if ((flags & eHandleCommandFlagStopOnContinue) == 0) - debugger.SetAsyncExecution (false); - - m_command_source_depth++; - - debugger.RunIOHandler(io_handler_sp); - if (!m_command_source_flags.empty()) - m_command_source_flags.pop_back(); - m_command_source_depth--; - result.SetStatus (eReturnStatusSuccessFinishNoResult); - debugger.SetAsyncExecution (old_async_execution); - } - else - { - result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - - - } - else - { - result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", - cmd_file.GetFilename().AsCString("")); - result.SetStatus (eReturnStatusFailed); - return; - } -} - -ScriptInterpreter * -CommandInterpreter::GetScriptInterpreter(bool can_create) -{ - if (m_script_interpreter_sp) - return m_script_interpreter_sp.get(); - - if (!can_create) return nullptr; - - lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); - m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); - return m_script_interpreter_sp.get(); -} - -bool -CommandInterpreter::GetSynchronous () -{ - return m_synchronous_execution; -} - -void -CommandInterpreter::SetSynchronous (bool value) -{ - m_synchronous_execution = value; -} - -void -CommandInterpreter::OutputFormattedHelpText (Stream &strm, - const char *prefix, - const char *help_text) -{ - const uint32_t max_columns = m_debugger.GetTerminalWidth(); - if (prefix == NULL) - prefix = ""; - - size_t prefix_width = strlen(prefix); - size_t line_width_max = max_columns - prefix_width; - const char *help_text_end = help_text + strlen(help_text); - const char *line_start = help_text; - if (line_width_max < 16) - line_width_max = help_text_end - help_text + prefix_width; - - strm.IndentMore (prefix_width); - while (line_start < help_text_end) - { - // Break each line at the first newline or last space/tab before - // the maximum number of characters that fit on a line. Lines with no - // natural break are left unbroken to wrap. - const char *line_end = help_text_end; - const char *line_scan = line_start; - const char *line_scan_end = help_text_end; - while (line_scan < line_scan_end) - { - char next = *line_scan; - if (next == '\t' || next == ' ') - { - line_end = line_scan; - line_scan_end = line_start + line_width_max; - } - else if (next == '\n' || next == '\0') - { - line_end = line_scan; - break; - } - ++line_scan; - } - - // Prefix the first line, indent subsequent lines to line up - if (line_start == help_text) - strm.Write (prefix, prefix_width); - else - strm.Indent(); - strm.Write (line_start, line_end - line_start); - strm.EOL(); - - // When a line breaks at whitespace consume it before continuing - line_start = line_end; - char next = *line_start; - if (next == '\n') - ++line_start; - else while (next == ' ' || next == '\t') - next = *(++line_start); - } - strm.IndentLess (prefix_width); -} - -void -CommandInterpreter::OutputFormattedHelpText (Stream &strm, - const char *word_text, - const char *separator, - const char *help_text, - size_t max_word_len) -{ - StreamString prefix_stream; - prefix_stream.Printf (" %-*s %s ", (int)max_word_len, word_text, separator); - OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text); -} - -void -CommandInterpreter::OutputHelpText (Stream &strm, - const char *word_text, - const char *separator, - const char *help_text, - uint32_t max_word_len) -{ - int indent_size = max_word_len + strlen (separator) + 2; - - strm.IndentMore (indent_size); - - StreamString text_strm; - text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); - - const uint32_t max_columns = m_debugger.GetTerminalWidth(); - - size_t len = text_strm.GetSize(); - const char *text = text_strm.GetData(); - - uint32_t chars_left = max_columns; - - for (uint32_t i = 0; i < len; i++) - { - if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') - { - chars_left = max_columns - indent_size; - strm.EOL(); - strm.Indent(); - } - else - { - strm.PutChar(text[i]); - chars_left--; - } - - } - - strm.EOL(); - strm.IndentLess(indent_size); -} - -void -CommandInterpreter::FindCommandsForApropos (const char *search_word, - StringList &commands_found, - StringList &commands_help, - CommandObject::CommandMap &command_map) -{ - CommandObject::CommandMap::const_iterator pos; - - for (pos = command_map.begin(); pos != command_map.end(); ++pos) - { - const char *command_name = pos->first.c_str(); - CommandObject *cmd_obj = pos->second.get(); - - const bool search_short_help = true; - const bool search_long_help = false; - const bool search_syntax = false; - const bool search_options = false; - if (strcasestr(command_name, search_word) || - cmd_obj->HelpTextContainsWord (search_word, - search_short_help, - search_long_help, - search_syntax, - search_options)) - { - commands_found.AppendString (cmd_obj->GetCommandName()); - commands_help.AppendString (cmd_obj->GetHelp()); - } - - if (cmd_obj->IsMultiwordObject()) - { - CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand(); - FindCommandsForApropos(search_word, - commands_found, - commands_help, - cmd_multiword->GetSubcommandDictionary()); - } - } -} - - -void -CommandInterpreter::FindCommandsForApropos (const char *search_word, - StringList &commands_found, - StringList &commands_help, - bool search_builtin_commands, - bool search_user_commands, - bool search_alias_commands) -{ - CommandObject::CommandMap::const_iterator pos; - - if (search_builtin_commands) - FindCommandsForApropos(search_word, commands_found, commands_help, m_command_dict); - - if (search_user_commands) - FindCommandsForApropos(search_word, commands_found, commands_help, m_user_dict); - - if (search_alias_commands) - FindCommandsForApropos(search_word, commands_found, commands_help, m_alias_dict); -} - -void -CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context) -{ - if (override_context != nullptr) - { - m_exe_ctx_ref = *override_context; - } - else - { - const bool adopt_selected = true; - m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected); - } -} - - -size_t -CommandInterpreter::GetProcessOutput () -{ - // The process has stuff waiting for stderr; get it and write it out to the appropriate place. - char stdio_buffer[1024]; - size_t len; - size_t total_bytes = 0; - Error error; - TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) - { - ProcessSP process_sp (target_sp->GetProcessSP()); - if (process_sp) - { - while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) - { - size_t bytes_written = len; - m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written); - total_bytes += len; - } - while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) - { - size_t bytes_written = len; - m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written); - total_bytes += len; - } - } - } - return total_bytes; -} - -void -CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) -{ - const bool is_interactive = io_handler.GetIsInteractive(); - if (is_interactive == false) - { - // When we are not interactive, don't execute blank lines. This will happen - // sourcing a commands file. We don't want blank lines to repeat the previous - // command and cause any errors to occur (like redefining an alias, get an error - // and stop parsing the commands file). - if (line.empty()) - return; - - // When using a non-interactive file handle (like when sourcing commands from a file) - // we need to echo the command out so we don't just see the command output and no - // command... - if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) - io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str()); - } - - lldb_private::CommandReturnObject result; - HandleCommand(line.c_str(), eLazyBoolCalculate, result); - - // Now emit the command output text from the command we just executed - if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) - { - // Display any STDOUT/STDERR _prior_ to emitting the command result text - GetProcessOutput (); - - if (!result.GetImmediateOutputStream()) - { - const char *output = result.GetOutputData(); - if (output && output[0]) - io_handler.GetOutputStreamFile()->PutCString(output); - } - - // Now emit the command error text from the command we just executed - if (!result.GetImmediateErrorStream()) - { - const char *error = result.GetErrorData(); - if (error && error[0]) - io_handler.GetErrorStreamFile()->PutCString(error); - } - } - - switch (result.GetStatus()) - { - case eReturnStatusInvalid: - case eReturnStatusSuccessFinishNoResult: - case eReturnStatusSuccessFinishResult: - case eReturnStatusStarted: - break; - - case eReturnStatusSuccessContinuingNoResult: - case eReturnStatusSuccessContinuingResult: - if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue)) - io_handler.SetIsDone(true); - break; - - case eReturnStatusFailed: - m_num_errors++; - if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) - io_handler.SetIsDone(true); - break; - - case eReturnStatusQuit: - m_quit_requested = true; - io_handler.SetIsDone(true); - break; - } - - // Finally, if we're going to stop on crash, check that here: - if (!m_quit_requested - && result.GetDidChangeProcessState() - && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) - { - bool should_stop = false; - TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) - { - ProcessSP process_sp (target_sp->GetProcessSP()); - if (process_sp) - { - for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) - { - StopReason reason = thread_sp->GetStopReason(); - if ((reason == eStopReasonSignal - || reason == eStopReasonException - || reason == eStopReasonInstrumentation) - && !result.GetAbnormalStopWasExpected()) - { - should_stop = true; - break; - } - } - } - } - if (should_stop) - { - io_handler.SetIsDone(true); - m_stopped_for_crash = true; - } - } -} - -bool -CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler) -{ - ExecutionContext exe_ctx (GetExecutionContext()); - Process *process = exe_ctx.GetProcessPtr(); - - if (process) - { - StateType state = process->GetState(); - if (StateIsRunningState(state)) - { - process->Halt(); - return true; // Don't do any updating when we are running - } - } - - ScriptInterpreter *script_interpreter = GetScriptInterpreter (false); - if (script_interpreter) - { - if (script_interpreter->Interrupt()) - return true; - } - return false; -} - -void -CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, - IOHandlerDelegate &delegate, - bool asynchronously, - void *baton) -{ - Debugger &debugger = GetDebugger(); - IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, - IOHandler::Type::CommandList, - "lldb", // Name of input reader for history - prompt, // Prompt - NULL, // Continuation prompt - true, // Get multiple lines - debugger.GetUseColor(), - 0, // Don't show line numbers - delegate)); // IOHandlerDelegate - - if (io_handler_sp) - { - io_handler_sp->SetUserData (baton); - if (asynchronously) - debugger.PushIOHandler(io_handler_sp); - else - debugger.RunIOHandler(io_handler_sp); - } - -} - - -void -CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, - IOHandlerDelegate &delegate, - bool asynchronously, - void *baton) -{ - Debugger &debugger = GetDebugger(); - IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, - IOHandler::Type::PythonCode, - "lldb-python", // Name of input reader for history - prompt, // Prompt - NULL, // Continuation prompt - true, // Get multiple lines - debugger.GetUseColor(), - 0, // Don't show line numbers - delegate)); // IOHandlerDelegate - - if (io_handler_sp) - { - io_handler_sp->SetUserData (baton); - if (asynchronously) - debugger.PushIOHandler(io_handler_sp); - else - debugger.RunIOHandler(io_handler_sp); - } - -} - -bool -CommandInterpreter::IsActive () -{ - return m_debugger.IsTopIOHandler (m_command_io_handler_sp); -} - -lldb::IOHandlerSP -CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options) -{ - // Always re-create the IOHandlerEditline in case the input - // changed. The old instance might have had a non-interactive - // input and now it does or vice versa. - if (force_create || !m_command_io_handler_sp) - { - // Always re-create the IOHandlerEditline in case the input - // changed. The old instance might have had a non-interactive - // input and now it does or vice versa. - uint32_t flags = 0; - - if (options) - { - if (options->m_stop_on_continue == eLazyBoolYes) - flags |= eHandleCommandFlagStopOnContinue; - if (options->m_stop_on_error == eLazyBoolYes) - flags |= eHandleCommandFlagStopOnError; - if (options->m_stop_on_crash == eLazyBoolYes) - flags |= eHandleCommandFlagStopOnCrash; - if (options->m_echo_commands != eLazyBoolNo) - flags |= eHandleCommandFlagEchoCommand; - if (options->m_print_results != eLazyBoolNo) - flags |= eHandleCommandFlagPrintResult; - } - else - { - flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; - } - - m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, - IOHandler::Type::CommandInterpreter, - m_debugger.GetInputFile(), - m_debugger.GetOutputFile(), - m_debugger.GetErrorFile(), - flags, - "lldb", - m_debugger.GetPrompt(), - NULL, // Continuation prompt - false, // Don't enable multiple line input, just single line commands - m_debugger.GetUseColor(), - 0, // Don't show line numbers - *this)); - } - return m_command_io_handler_sp; -} - -void -CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, - bool spawn_thread, - CommandInterpreterRunOptions &options) -{ - // Always re-create the command interpreter when we run it in case - // any file handles have changed. - bool force_create = true; - m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); - m_stopped_for_crash = false; - - if (auto_handle_events) - m_debugger.StartEventHandlerThread(); - - if (spawn_thread) - { - m_debugger.StartIOHandlerThread(); - } - else - { - m_debugger.ExecuteIOHandlers(); - - if (auto_handle_events) - m_debugger.StopEventHandlerThread(); - } - -} - -CommandObject * -CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnObject &result) -{ - std::string scratch_command(command_line); // working copy so we don't modify command_line unless we succeed - CommandObject *cmd_obj = nullptr; - StreamString revised_command_line; - bool wants_raw_input = false; - size_t actual_cmd_name_len = 0; - std::string next_word; - StringList matches; - bool done = false; - while (!done) - { - char quote_char = '\0'; - std::string suffix; - ExtractCommand(scratch_command, next_word, suffix, quote_char); - if (cmd_obj == nullptr) - { - std::string full_name; - bool is_alias = GetAliasFullName(next_word.c_str(), full_name); - cmd_obj = GetCommandObject(next_word.c_str(), &matches); - bool is_real_command = (is_alias == false) || (cmd_obj != nullptr && cmd_obj->IsAlias() == false); - if (!is_real_command) - { - matches.Clear(); - std::string alias_result; - cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result); - revised_command_line.Printf("%s", alias_result.c_str()); - if (cmd_obj) - { - wants_raw_input = cmd_obj->WantsRawCommandString(); - actual_cmd_name_len = strlen(cmd_obj->GetCommandName()); - } - } - else - { - if (!cmd_obj) - cmd_obj = GetCommandObject(next_word.c_str(), &matches); - if (cmd_obj) - { - actual_cmd_name_len += strlen(cmd_obj->GetCommandName()); - revised_command_line.Printf("%s", cmd_obj->GetCommandName()); - wants_raw_input = cmd_obj->WantsRawCommandString(); - } - else - { - revised_command_line.Printf ("%s", next_word.c_str()); - } - } - } - else - { - if (cmd_obj->IsMultiwordObject ()) - { - CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject(next_word.c_str()); - if (sub_cmd_obj) - { - // The subcommand's name includes the parent command's name, - // so restart rather than append to the revised_command_line. - actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1; - revised_command_line.Clear(); - revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName()); - cmd_obj = sub_cmd_obj; - wants_raw_input = cmd_obj->WantsRawCommandString(); - } - else - { - if (quote_char) - revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); - else - revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); - done = true; - } - } - else - { - if (quote_char) - revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); - else - revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); - done = true; - } - } - - if (cmd_obj == nullptr) - { - const size_t num_matches = matches.GetSize(); - if (matches.GetSize() > 1) { - StreamString error_msg; - error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); - - for (uint32_t i = 0; i < num_matches; ++i) { - error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i)); - } - result.AppendRawError(error_msg.GetString().c_str()); + } + } else { + // If we found a normal command, we are done + done = true; + if (!suffix.empty()) { + switch (suffix[0]) { + case '/': + // GDB format suffixes + { + Options *command_options = cmd_obj->GetOptions(); + if (command_options && + command_options->SupportsLongOption("gdb-format")) { + std::string gdb_format_option("--gdb-format="); + gdb_format_option += (suffix.c_str() + 1); + + bool inserted = false; + std::string &cmd = revised_command_line.GetString(); + size_t arg_terminator_idx = FindArgumentTerminator(cmd); + if (arg_terminator_idx != std::string::npos) { + // Insert the gdb format option before the "--" that terminates + // options + gdb_format_option.append(1, ' '); + cmd.insert(arg_terminator_idx, gdb_format_option); + inserted = true; + } + + if (!inserted) + revised_command_line.Printf(" %s", gdb_format_option.c_str()); + + if (wants_raw_input && + FindArgumentTerminator(cmd) == std::string::npos) + revised_command_line.PutCString(" --"); } else { - // We didn't have only one match, otherwise we wouldn't get here. - assert(num_matches == 0); - result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str()); + result.AppendErrorWithFormat( + "the '%s' command doesn't support the --gdb-format option\n", + cmd_obj->GetCommandName()); + result.SetStatus(eReturnStatusFailed); + return nullptr; } - result.SetStatus(eReturnStatusFailed); - return nullptr; - } + } + break; - if (cmd_obj->IsMultiwordObject()) - { - if (!suffix.empty()) - { - result.AppendErrorWithFormat("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", - cmd_obj->GetCommandName(), - next_word.empty() ? "" : next_word.c_str(), - next_word.empty() ? " -- " : " ", - suffix.c_str()); - result.SetStatus(eReturnStatusFailed); - return nullptr; - } - } - else - { - // If we found a normal command, we are done - done = true; - if (!suffix.empty()) - { - switch (suffix[0]) - { - case '/': - // GDB format suffixes - { - Options *command_options = cmd_obj->GetOptions(); - if (command_options && command_options->SupportsLongOption("gdb-format")) - { - std::string gdb_format_option("--gdb-format="); - gdb_format_option += (suffix.c_str() + 1); - - bool inserted = false; - std::string &cmd = revised_command_line.GetString(); - size_t arg_terminator_idx = FindArgumentTerminator(cmd); - if (arg_terminator_idx != std::string::npos) - { - // Insert the gdb format option before the "--" that terminates options - gdb_format_option.append(1,' '); - cmd.insert(arg_terminator_idx, gdb_format_option); - inserted = true; - } - - if (!inserted) - revised_command_line.Printf(" %s", gdb_format_option.c_str()); - - if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) - revised_command_line.PutCString(" --"); - } - else - { - result.AppendErrorWithFormat("the '%s' command doesn't support the --gdb-format option\n", - cmd_obj->GetCommandName()); - result.SetStatus(eReturnStatusFailed); - return nullptr; - } - } - break; - - default: - result.AppendErrorWithFormat("unknown command shorthand suffix: '%s'\n", - suffix.c_str()); - result.SetStatus(eReturnStatusFailed); - return nullptr; - } - } + default: + result.AppendErrorWithFormat( + "unknown command shorthand suffix: '%s'\n", suffix.c_str()); + result.SetStatus(eReturnStatusFailed); + return nullptr; } - if (scratch_command.empty()) - done = true; + } } + if (scratch_command.empty()) + done = true; + } - if (!scratch_command.empty()) - revised_command_line.Printf(" %s", scratch_command.c_str()); + if (!scratch_command.empty()) + revised_command_line.Printf(" %s", scratch_command.c_str()); - if (cmd_obj != NULL) - command_line = revised_command_line.GetData(); + if (cmd_obj != NULL) + command_line = revised_command_line.GetData(); - return cmd_obj; + return cmd_obj; } diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 3fd2d375357..d42d3c7f111 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -9,12 +9,12 @@ #include "lldb/Interpreter/CommandObject.h" -#include -#include #include +#include +#include -#include #include +#include #include "lldb/Core/Address.h" #include "lldb/Core/ArchSpec.h" @@ -22,9 +22,9 @@ // These are for the Sourcename completers. // FIXME: Make a separate file for the completers. -#include "lldb/Host/FileSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -40,1079 +40,1012 @@ using namespace lldb_private; // CommandObject //------------------------------------------------------------------------- -CommandObject::CommandObject -( - CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t flags -) : - m_interpreter (interpreter), - m_cmd_name (name ? name : ""), - m_cmd_help_short (), - m_cmd_help_long (), - m_cmd_syntax (), - m_flags (flags), - m_arguments(), - m_deprecated_command_override_callback (nullptr), - m_command_override_callback (nullptr), - m_command_override_baton (nullptr) -{ - if (help && help[0]) - m_cmd_help_short = help; - if (syntax && syntax[0]) - m_cmd_syntax = syntax; +CommandObject::CommandObject(CommandInterpreter &interpreter, const char *name, + const char *help, const char *syntax, + uint32_t flags) + : m_interpreter(interpreter), m_cmd_name(name ? name : ""), + m_cmd_help_short(), m_cmd_help_long(), m_cmd_syntax(), m_flags(flags), + m_arguments(), m_deprecated_command_override_callback(nullptr), + m_command_override_callback(nullptr), m_command_override_baton(nullptr) { + if (help && help[0]) + m_cmd_help_short = help; + if (syntax && syntax[0]) + m_cmd_syntax = syntax; } -CommandObject::~CommandObject () -{ -} +CommandObject::~CommandObject() {} -const char * -CommandObject::GetHelp () -{ - return m_cmd_help_short.c_str(); -} +const char *CommandObject::GetHelp() { return m_cmd_help_short.c_str(); } -const char * -CommandObject::GetHelpLong () -{ - return m_cmd_help_long.c_str(); -} +const char *CommandObject::GetHelpLong() { return m_cmd_help_long.c_str(); } -const char * -CommandObject::GetSyntax () -{ - if (m_cmd_syntax.length() == 0) - { - StreamString syntax_str; - syntax_str.Printf ("%s", GetCommandName()); - if (!IsDashDashCommand() && GetOptions() != nullptr) - syntax_str.Printf (" "); - if (m_arguments.size() > 0) - { - syntax_str.Printf (" "); - if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions()) - syntax_str.Printf("-- "); - GetFormattedCommandArguments (syntax_str); - } - m_cmd_syntax = syntax_str.GetData (); +const char *CommandObject::GetSyntax() { + if (m_cmd_syntax.length() == 0) { + StreamString syntax_str; + syntax_str.Printf("%s", GetCommandName()); + if (!IsDashDashCommand() && GetOptions() != nullptr) + syntax_str.Printf(" "); + if (m_arguments.size() > 0) { + syntax_str.Printf(" "); + if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && + GetOptions()->NumCommandOptions()) + syntax_str.Printf("-- "); + GetFormattedCommandArguments(syntax_str); } + m_cmd_syntax = syntax_str.GetData(); + } - return m_cmd_syntax.c_str(); + return m_cmd_syntax.c_str(); } -const char * -CommandObject::GetCommandName () -{ - return m_cmd_name.c_str(); -} +const char *CommandObject::GetCommandName() { return m_cmd_name.c_str(); } -void -CommandObject::SetCommandName (const char *name) -{ - m_cmd_name = name; -} +void CommandObject::SetCommandName(const char *name) { m_cmd_name = name; } -void -CommandObject::SetHelp (const char *cstr) -{ - if (cstr) - m_cmd_help_short = cstr; - else - m_cmd_help_short.assign(""); +void CommandObject::SetHelp(const char *cstr) { + if (cstr) + m_cmd_help_short = cstr; + else + m_cmd_help_short.assign(""); } -void -CommandObject::SetHelpLong (const char *cstr) -{ - if (cstr) - m_cmd_help_long = cstr; - else - m_cmd_help_long.assign(""); +void CommandObject::SetHelpLong(const char *cstr) { + if (cstr) + m_cmd_help_long = cstr; + else + m_cmd_help_long.assign(""); } -void -CommandObject::SetSyntax (const char *cstr) -{ - m_cmd_syntax = cstr; -} +void CommandObject::SetSyntax(const char *cstr) { m_cmd_syntax = cstr; } -Options * -CommandObject::GetOptions () -{ - // By default commands don't have options unless this virtual function - // is overridden by base classes. - return nullptr; +Options *CommandObject::GetOptions() { + // By default commands don't have options unless this virtual function + // is overridden by base classes. + return nullptr; } -bool -CommandObject::ParseOptions -( - Args& args, - CommandReturnObject &result -) -{ - // See if the subclass has options? - Options *options = GetOptions(); - if (options != nullptr) - { - Error error; - - auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); - options->NotifyOptionParsingStarting(&exe_ctx); - - // ParseOptions calls getopt_long_only, which always skips the zero'th item in the array and starts at position 1, - // so we need to push a dummy value into position zero. - args.Unshift("dummy_string"); - const bool require_validation = true; - error = args.ParseOptions(*options, &exe_ctx, - GetCommandInterpreter().GetPlatform(true), - require_validation); - - // The "dummy_string" will have already been removed by ParseOptions, - // so no need to remove it. - - if (error.Success()) - error = options->NotifyOptionParsingFinished(&exe_ctx); - - if (error.Success()) - { - if (options->VerifyOptions (result)) - return true; - } - else - { - const char *error_cstr = error.AsCString(); - if (error_cstr) - { - // We got an error string, lets use that - result.AppendError(error_cstr); - } - else - { - // No error string, output the usage information into result - options->GenerateOptionUsage(result.GetErrorStream(), this, - GetCommandInterpreter() - .GetDebugger() - .GetTerminalWidth()); - } - } - result.SetStatus (eReturnStatusFailed); - return false; - } - return true; -} +bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) { + // See if the subclass has options? + Options *options = GetOptions(); + if (options != nullptr) { + Error error; + + auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); + options->NotifyOptionParsingStarting(&exe_ctx); + // ParseOptions calls getopt_long_only, which always skips the zero'th item + // in the array and starts at position 1, + // so we need to push a dummy value into position zero. + args.Unshift("dummy_string"); + const bool require_validation = true; + error = args.ParseOptions(*options, &exe_ctx, + GetCommandInterpreter().GetPlatform(true), + require_validation); + // The "dummy_string" will have already been removed by ParseOptions, + // so no need to remove it. -bool -CommandObject::CheckRequirements (CommandReturnObject &result) -{ + if (error.Success()) + error = options->NotifyOptionParsingFinished(&exe_ctx); + + if (error.Success()) { + if (options->VerifyOptions(result)) + return true; + } else { + const char *error_cstr = error.AsCString(); + if (error_cstr) { + // We got an error string, lets use that + result.AppendError(error_cstr); + } else { + // No error string, output the usage information into result + options->GenerateOptionUsage( + result.GetErrorStream(), this, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + } + } + result.SetStatus(eReturnStatusFailed); + return false; + } + return true; +} + +bool CommandObject::CheckRequirements(CommandReturnObject &result) { #ifdef LLDB_CONFIGURATION_DEBUG - // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx - // has shared pointers to the target, process, thread and frame and we don't - // want any CommandObject instances to keep any of these objects around - // longer than for a single command. Every command should call - // CommandObject::Cleanup() after it has completed - assert (m_exe_ctx.GetTargetPtr() == NULL); - assert (m_exe_ctx.GetProcessPtr() == NULL); - assert (m_exe_ctx.GetThreadPtr() == NULL); - assert (m_exe_ctx.GetFramePtr() == NULL); + // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx + // has shared pointers to the target, process, thread and frame and we don't + // want any CommandObject instances to keep any of these objects around + // longer than for a single command. Every command should call + // CommandObject::Cleanup() after it has completed + assert(m_exe_ctx.GetTargetPtr() == NULL); + assert(m_exe_ctx.GetProcessPtr() == NULL); + assert(m_exe_ctx.GetThreadPtr() == NULL); + assert(m_exe_ctx.GetFramePtr() == NULL); #endif - // Lock down the interpreter's execution context prior to running the - // command so we guarantee the selected target, process, thread and frame - // can't go away during the execution - m_exe_ctx = m_interpreter.GetExecutionContext(); - - const uint32_t flags = GetFlags().Get(); - if (flags & (eCommandRequiresTarget | - eCommandRequiresProcess | - eCommandRequiresThread | - eCommandRequiresFrame | - eCommandTryTargetAPILock )) - { - - if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) - { - result.AppendError (GetInvalidTargetDescription()); - return false; - } + // Lock down the interpreter's execution context prior to running the + // command so we guarantee the selected target, process, thread and frame + // can't go away during the execution + m_exe_ctx = m_interpreter.GetExecutionContext(); - if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) - { - if (!m_exe_ctx.HasTargetScope()) - result.AppendError (GetInvalidTargetDescription()); - else - result.AppendError (GetInvalidProcessDescription()); - return false; - } - - if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) - { - if (!m_exe_ctx.HasTargetScope()) - result.AppendError (GetInvalidTargetDescription()); - else if (!m_exe_ctx.HasProcessScope()) - result.AppendError (GetInvalidProcessDescription()); - else - result.AppendError (GetInvalidThreadDescription()); - return false; - } - - if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) - { - if (!m_exe_ctx.HasTargetScope()) - result.AppendError (GetInvalidTargetDescription()); - else if (!m_exe_ctx.HasProcessScope()) - result.AppendError (GetInvalidProcessDescription()); - else if (!m_exe_ctx.HasThreadScope()) - result.AppendError (GetInvalidThreadDescription()); - else - result.AppendError (GetInvalidFrameDescription()); - return false; - } - - if ((flags & eCommandRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr)) - { - result.AppendError (GetInvalidRegContextDescription()); - return false; - } + const uint32_t flags = GetFlags().Get(); + if (flags & (eCommandRequiresTarget | eCommandRequiresProcess | + eCommandRequiresThread | eCommandRequiresFrame | + eCommandTryTargetAPILock)) { - if (flags & eCommandTryTargetAPILock) - { - Target *target = m_exe_ctx.GetTargetPtr(); - if (target) - m_api_locker = std::unique_lock(target->GetAPIMutex()); - } + if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) { + result.AppendError(GetInvalidTargetDescription()); + return false; } - if (GetFlags().AnySet (eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)) - { - Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process == nullptr) - { - // A process that is not running is considered paused. - if (GetFlags().Test(eCommandProcessMustBeLaunched)) - { - result.AppendError ("Process must exist."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) { + if (!m_exe_ctx.HasTargetScope()) + result.AppendError(GetInvalidTargetDescription()); + else + result.AppendError(GetInvalidProcessDescription()); + return false; + } + + if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) { + if (!m_exe_ctx.HasTargetScope()) + result.AppendError(GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError(GetInvalidProcessDescription()); + else + result.AppendError(GetInvalidThreadDescription()); + return false; + } + + if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) { + if (!m_exe_ctx.HasTargetScope()) + result.AppendError(GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError(GetInvalidProcessDescription()); + else if (!m_exe_ctx.HasThreadScope()) + result.AppendError(GetInvalidThreadDescription()); + else + result.AppendError(GetInvalidFrameDescription()); + return false; + } + + if ((flags & eCommandRequiresRegContext) && + (m_exe_ctx.GetRegisterContext() == nullptr)) { + result.AppendError(GetInvalidRegContextDescription()); + return false; + } + + if (flags & eCommandTryTargetAPILock) { + Target *target = m_exe_ctx.GetTargetPtr(); + if (target) + m_api_locker = + std::unique_lock(target->GetAPIMutex()); + } + } + + if (GetFlags().AnySet(eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused)) { + Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process == nullptr) { + // A process that is not running is considered paused. + if (GetFlags().Test(eCommandProcessMustBeLaunched)) { + result.AppendError("Process must exist."); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + StateType state = process->GetState(); + switch (state) { + case eStateInvalid: + case eStateSuspended: + case eStateCrashed: + case eStateStopped: + break; + + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateDetached: + case eStateExited: + case eStateUnloaded: + if (GetFlags().Test(eCommandProcessMustBeLaunched)) { + result.AppendError("Process must be launched."); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - StateType state = process->GetState(); - switch (state) - { - case eStateInvalid: - case eStateSuspended: - case eStateCrashed: - case eStateStopped: - break; - - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateDetached: - case eStateExited: - case eStateUnloaded: - if (GetFlags().Test(eCommandProcessMustBeLaunched)) - { - result.AppendError ("Process must be launched."); - result.SetStatus (eReturnStatusFailed); - return false; - } - break; - - case eStateRunning: - case eStateStepping: - if (GetFlags().Test(eCommandProcessMustBePaused)) - { - result.AppendError ("Process is running. Use 'process interrupt' to pause execution."); - result.SetStatus (eReturnStatusFailed); - return false; - } - } + break; + + case eStateRunning: + case eStateStepping: + if (GetFlags().Test(eCommandProcessMustBePaused)) { + result.AppendError("Process is running. Use 'process interrupt' to " + "pause execution."); + result.SetStatus(eReturnStatusFailed); + return false; } + } } - return true; + } + return true; } -void -CommandObject::Cleanup () -{ - m_exe_ctx.Clear(); - if (m_api_locker.owns_lock()) - m_api_locker.unlock(); +void CommandObject::Cleanup() { + m_exe_ctx.Clear(); + if (m_api_locker.owns_lock()) + m_api_locker.unlock(); } -int -CommandObject::HandleCompletion -( - Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches -) -{ - // Default implementation of WantsCompletion() is !WantsRawCommandString(). - // Subclasses who want raw command string but desire, for example, - // argument completion should override WantsCompletion() to return true, - // instead. - if (WantsRawCommandString() && !WantsCompletion()) - { - // FIXME: Abstract telling the completion to insert the completion character. - matches.Clear(); - return -1; +int CommandObject::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, StringList &matches) { + // Default implementation of WantsCompletion() is !WantsRawCommandString(). + // Subclasses who want raw command string but desire, for example, + // argument completion should override WantsCompletion() to return true, + // instead. + if (WantsRawCommandString() && !WantsCompletion()) { + // FIXME: Abstract telling the completion to insert the completion + // character. + matches.Clear(); + return -1; + } else { + // Can we do anything generic with the options? + Options *cur_options = GetOptions(); + CommandReturnObject result; + OptionElementVector opt_element_vector; + + if (cur_options != nullptr) { + // Re-insert the dummy command name string which will have been + // stripped off: + input.Unshift("dummy-string"); + cursor_index++; + + // I stick an element on the end of the input, because if the last element + // is + // option that requires an argument, getopt_long_only will freak out. + + input.AppendArgument(""); + + input.ParseArgsForCompletion(*cur_options, opt_element_vector, + cursor_index); + + input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1); + + bool handled_by_options; + handled_by_options = cur_options->HandleOptionCompletion( + input, opt_element_vector, cursor_index, cursor_char_position, + match_start_point, max_return_elements, GetCommandInterpreter(), + word_complete, matches); + if (handled_by_options) + return matches.GetSize(); } - else - { - // Can we do anything generic with the options? - Options *cur_options = GetOptions(); - CommandReturnObject result; - OptionElementVector opt_element_vector; - - if (cur_options != nullptr) - { - // Re-insert the dummy command name string which will have been - // stripped off: - input.Unshift ("dummy-string"); - cursor_index++; - - - // I stick an element on the end of the input, because if the last element is - // option that requires an argument, getopt_long_only will freak out. - - input.AppendArgument (""); - - input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index); - - input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1); - - bool handled_by_options; - handled_by_options = cur_options->HandleOptionCompletion (input, - opt_element_vector, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - GetCommandInterpreter(), - word_complete, - matches); - if (handled_by_options) - return matches.GetSize(); - } - // If we got here, the last word is not an option or an option argument. - return HandleArgumentCompletion (input, - cursor_index, - cursor_char_position, - opt_element_vector, - match_start_point, - max_return_elements, - word_complete, - matches); - } + // If we got here, the last word is not an option or an option argument. + return HandleArgumentCompletion( + input, cursor_index, cursor_char_position, opt_element_vector, + match_start_point, max_return_elements, word_complete, matches); + } } -bool -CommandObject::HelpTextContainsWord (const char *search_word, - bool search_short_help, - bool search_long_help, - bool search_syntax, - bool search_options) -{ - std::string options_usage_help; - - bool found_word = false; - - const char *short_help = GetHelp(); - const char *long_help = GetHelpLong(); - const char *syntax_help = GetSyntax(); - - if (search_short_help && short_help && strcasestr (short_help, search_word)) - found_word = true; - else if (search_long_help && long_help && strcasestr (long_help, search_word)) +bool CommandObject::HelpTextContainsWord(const char *search_word, + bool search_short_help, + bool search_long_help, + bool search_syntax, + bool search_options) { + std::string options_usage_help; + + bool found_word = false; + + const char *short_help = GetHelp(); + const char *long_help = GetHelpLong(); + const char *syntax_help = GetSyntax(); + + if (search_short_help && short_help && strcasestr(short_help, search_word)) + found_word = true; + else if (search_long_help && long_help && strcasestr(long_help, search_word)) + found_word = true; + else if (search_syntax && syntax_help && strcasestr(syntax_help, search_word)) + found_word = true; + + if (!found_word && search_options && GetOptions() != nullptr) { + StreamString usage_help; + GetOptions()->GenerateOptionUsage( + usage_help, this, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + if (usage_help.GetSize() > 0) { + const char *usage_text = usage_help.GetData(); + if (strcasestr(usage_text, search_word)) found_word = true; - else if (search_syntax && syntax_help && strcasestr (syntax_help, search_word)) - found_word = true; - - if (!found_word - && search_options - && GetOptions() != nullptr) - { - StreamString usage_help; - GetOptions()->GenerateOptionUsage(usage_help, this, - GetCommandInterpreter() - .GetDebugger().GetTerminalWidth()); - if (usage_help.GetSize() > 0) - { - const char *usage_text = usage_help.GetData(); - if (strcasestr (usage_text, search_word)) - found_word = true; - } } + } - return found_word; + return found_word; } -int -CommandObject::GetNumArgumentEntries () -{ - return m_arguments.size(); -} +int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); } CommandObject::CommandArgumentEntry * -CommandObject::GetArgumentEntryAtIndex (int idx) -{ - if (static_cast(idx) < m_arguments.size()) - return &(m_arguments[idx]); +CommandObject::GetArgumentEntryAtIndex(int idx) { + if (static_cast(idx) < m_arguments.size()) + return &(m_arguments[idx]); - return nullptr; + return nullptr; } const CommandObject::ArgumentTableEntry * -CommandObject::FindArgumentDataByType (CommandArgumentType arg_type) -{ - const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); +CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) { + const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); - for (int i = 0; i < eArgTypeLastArg; ++i) - if (table[i].arg_type == arg_type) - return &(table[i]); + for (int i = 0; i < eArgTypeLastArg; ++i) + if (table[i].arg_type == arg_type) + return &(table[i]); - return nullptr; + return nullptr; } -void -CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter) -{ - const ArgumentTableEntry* table = CommandObject::GetArgumentTable(); - const ArgumentTableEntry *entry = &(table[arg_type]); - - // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up... - - if (entry->arg_type != arg_type) - entry = CommandObject::FindArgumentDataByType (arg_type); - - if (!entry) - return; - - StreamString name_str; - name_str.Printf ("<%s>", entry->arg_name); - - if (entry->help_function) - { - const char* help_text = entry->help_function(); - if (!entry->help_function.self_formatting) - { - interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text, - name_str.GetSize()); - } - else - { - interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text, - name_str.GetSize()); - } +void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type, + CommandInterpreter &interpreter) { + const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); + const ArgumentTableEntry *entry = &(table[arg_type]); + + // The table is *supposed* to be kept in arg_type order, but someone *could* + // have messed it up... + + if (entry->arg_type != arg_type) + entry = CommandObject::FindArgumentDataByType(arg_type); + + if (!entry) + return; + + StreamString name_str; + name_str.Printf("<%s>", entry->arg_name); + + if (entry->help_function) { + const char *help_text = entry->help_function(); + if (!entry->help_function.self_formatting) { + interpreter.OutputFormattedHelpText(str, name_str.GetData(), "--", + help_text, name_str.GetSize()); + } else { + interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text, + name_str.GetSize()); } - else - interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize()); + } else + interpreter.OutputFormattedHelpText(str, name_str.GetData(), "--", + entry->help_text, name_str.GetSize()); } -const char * -CommandObject::GetArgumentName (CommandArgumentType arg_type) -{ - const ArgumentTableEntry *entry = &(CommandObject::GetArgumentTable()[arg_type]); +const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) { + const ArgumentTableEntry *entry = + &(CommandObject::GetArgumentTable()[arg_type]); - // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up... + // The table is *supposed* to be kept in arg_type order, but someone *could* + // have messed it up... - if (entry->arg_type != arg_type) - entry = CommandObject::FindArgumentDataByType (arg_type); + if (entry->arg_type != arg_type) + entry = CommandObject::FindArgumentDataByType(arg_type); - if (entry) - return entry->arg_name; + if (entry) + return entry->arg_name; - StreamString str; - str << "Arg name for type (" << arg_type << ") not in arg table!"; - return str.GetData(); + StreamString str; + str << "Arg name for type (" << arg_type << ") not in arg table!"; + return str.GetData(); } -bool -CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type) -{ - if ((arg_repeat_type == eArgRepeatPairPlain) - || (arg_repeat_type == eArgRepeatPairOptional) - || (arg_repeat_type == eArgRepeatPairPlus) - || (arg_repeat_type == eArgRepeatPairStar) - || (arg_repeat_type == eArgRepeatPairRange) - || (arg_repeat_type == eArgRepeatPairRangeOptional)) - return true; +bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) { + if ((arg_repeat_type == eArgRepeatPairPlain) || + (arg_repeat_type == eArgRepeatPairOptional) || + (arg_repeat_type == eArgRepeatPairPlus) || + (arg_repeat_type == eArgRepeatPairStar) || + (arg_repeat_type == eArgRepeatPairRange) || + (arg_repeat_type == eArgRepeatPairRangeOptional)) + return true; - return false; + return false; } static CommandObject::CommandArgumentEntry -OptSetFiltered(uint32_t opt_set_mask, CommandObject::CommandArgumentEntry &cmd_arg_entry) -{ - CommandObject::CommandArgumentEntry ret_val; - for (unsigned i = 0; i < cmd_arg_entry.size(); ++i) - if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association) - ret_val.push_back(cmd_arg_entry[i]); - return ret_val; +OptSetFiltered(uint32_t opt_set_mask, + CommandObject::CommandArgumentEntry &cmd_arg_entry) { + CommandObject::CommandArgumentEntry ret_val; + for (unsigned i = 0; i < cmd_arg_entry.size(); ++i) + if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association) + ret_val.push_back(cmd_arg_entry[i]); + return ret_val; } // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take // all the argument data into account. On rare cases where some argument sticks // with certain option sets, this function returns the option set filtered args. -void -CommandObject::GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask) -{ - int num_args = m_arguments.size(); - for (int i = 0; i < num_args; ++i) - { - if (i > 0) - str.Printf (" "); - CommandArgumentEntry arg_entry = - opt_set_mask == LLDB_OPT_SET_ALL ? m_arguments[i] - : OptSetFiltered(opt_set_mask, m_arguments[i]); - int num_alternatives = arg_entry.size(); - - if ((num_alternatives == 2) - && IsPairType (arg_entry[0].arg_repetition)) - { - const char *first_name = GetArgumentName (arg_entry[0].arg_type); - const char *second_name = GetArgumentName (arg_entry[1].arg_type); - switch (arg_entry[0].arg_repetition) - { - case eArgRepeatPairPlain: - str.Printf ("<%s> <%s>", first_name, second_name); - break; - case eArgRepeatPairOptional: - str.Printf ("[<%s> <%s>]", first_name, second_name); - break; - case eArgRepeatPairPlus: - str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name); - break; - case eArgRepeatPairStar: - str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name); - break; - case eArgRepeatPairRange: - str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name); - break; - case eArgRepeatPairRangeOptional: - str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name); - break; - // Explicitly test for all the rest of the cases, so if new types get added we will notice the - // missing case statement(s). - case eArgRepeatPlain: - case eArgRepeatOptional: - case eArgRepeatPlus: - case eArgRepeatStar: - case eArgRepeatRange: - // These should not be reached, as they should fail the IsPairType test above. - break; - } - } - else - { - StreamString names; - for (int j = 0; j < num_alternatives; ++j) - { - if (j > 0) - names.Printf (" | "); - names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type)); - } - switch (arg_entry[0].arg_repetition) - { - case eArgRepeatPlain: - str.Printf ("<%s>", names.GetData()); - break; - case eArgRepeatPlus: - str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData()); - break; - case eArgRepeatStar: - str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData()); - break; - case eArgRepeatOptional: - str.Printf ("[<%s>]", names.GetData()); - break; - case eArgRepeatRange: - str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData()); - break; - // Explicitly test for all the rest of the cases, so if new types get added we will notice the - // missing case statement(s). - case eArgRepeatPairPlain: - case eArgRepeatPairOptional: - case eArgRepeatPairPlus: - case eArgRepeatPairStar: - case eArgRepeatPairRange: - case eArgRepeatPairRangeOptional: - // These should not be hit, as they should pass the IsPairType test above, and control should - // have gone into the other branch of the if statement. - break; - } - } +void CommandObject::GetFormattedCommandArguments(Stream &str, + uint32_t opt_set_mask) { + int num_args = m_arguments.size(); + for (int i = 0; i < num_args; ++i) { + if (i > 0) + str.Printf(" "); + CommandArgumentEntry arg_entry = + opt_set_mask == LLDB_OPT_SET_ALL + ? m_arguments[i] + : OptSetFiltered(opt_set_mask, m_arguments[i]); + int num_alternatives = arg_entry.size(); + + if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) { + const char *first_name = GetArgumentName(arg_entry[0].arg_type); + const char *second_name = GetArgumentName(arg_entry[1].arg_type); + switch (arg_entry[0].arg_repetition) { + case eArgRepeatPairPlain: + str.Printf("<%s> <%s>", first_name, second_name); + break; + case eArgRepeatPairOptional: + str.Printf("[<%s> <%s>]", first_name, second_name); + break; + case eArgRepeatPairPlus: + str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, + first_name, second_name); + break; + case eArgRepeatPairStar: + str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, + first_name, second_name); + break; + case eArgRepeatPairRange: + str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, + first_name, second_name); + break; + case eArgRepeatPairRangeOptional: + str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, + first_name, second_name); + break; + // Explicitly test for all the rest of the cases, so if new types get + // added we will notice the + // missing case statement(s). + case eArgRepeatPlain: + case eArgRepeatOptional: + case eArgRepeatPlus: + case eArgRepeatStar: + case eArgRepeatRange: + // These should not be reached, as they should fail the IsPairType test + // above. + break; + } + } else { + StreamString names; + for (int j = 0; j < num_alternatives; ++j) { + if (j > 0) + names.Printf(" | "); + names.Printf("%s", GetArgumentName(arg_entry[j].arg_type)); + } + switch (arg_entry[0].arg_repetition) { + case eArgRepeatPlain: + str.Printf("<%s>", names.GetData()); + break; + case eArgRepeatPlus: + str.Printf("<%s> [<%s> [...]]", names.GetData(), names.GetData()); + break; + case eArgRepeatStar: + str.Printf("[<%s> [<%s> [...]]]", names.GetData(), names.GetData()); + break; + case eArgRepeatOptional: + str.Printf("[<%s>]", names.GetData()); + break; + case eArgRepeatRange: + str.Printf("<%s_1> .. <%s_n>", names.GetData(), names.GetData()); + break; + // Explicitly test for all the rest of the cases, so if new types get + // added we will notice the + // missing case statement(s). + case eArgRepeatPairPlain: + case eArgRepeatPairOptional: + case eArgRepeatPairPlus: + case eArgRepeatPairStar: + case eArgRepeatPairRange: + case eArgRepeatPairRangeOptional: + // These should not be hit, as they should pass the IsPairType test + // above, and control should + // have gone into the other branch of the if statement. + break; + } } + } } -CommandArgumentType -CommandObject::LookupArgumentName (const char *arg_name) -{ - CommandArgumentType return_type = eArgTypeLastArg; +CommandArgumentType CommandObject::LookupArgumentName(const char *arg_name) { + CommandArgumentType return_type = eArgTypeLastArg; - std::string arg_name_str (arg_name); - size_t len = arg_name_str.length(); - if (arg_name[0] == '<' - && arg_name[len-1] == '>') - arg_name_str = arg_name_str.substr (1, len-2); + std::string arg_name_str(arg_name); + size_t len = arg_name_str.length(); + if (arg_name[0] == '<' && arg_name[len - 1] == '>') + arg_name_str = arg_name_str.substr(1, len - 2); - const ArgumentTableEntry *table = GetArgumentTable(); - for (int i = 0; i < eArgTypeLastArg; ++i) - if (arg_name_str.compare (table[i].arg_name) == 0) - return_type = g_arguments_data[i].arg_type; + const ArgumentTableEntry *table = GetArgumentTable(); + for (int i = 0; i < eArgTypeLastArg; ++i) + if (arg_name_str.compare(table[i].arg_name) == 0) + return_type = g_arguments_data[i].arg_type; - return return_type; + return return_type; } -static const char * -RegisterNameHelpTextCallback () -{ - return "Register names can be specified using the architecture specific names. " - "They can also be specified using generic names. Not all generic entities have " - "registers backing them on all architectures. When they don't the generic name " - "will return an error.\n" - "The generic names defined in lldb are:\n" - "\n" - "pc - program counter register\n" - "ra - return address register\n" - "fp - frame pointer register\n" - "sp - stack pointer register\n" - "flags - the flags register\n" - "arg{1-6} - integer argument passing registers.\n"; +static const char *RegisterNameHelpTextCallback() { + return "Register names can be specified using the architecture specific " + "names. " + "They can also be specified using generic names. Not all generic " + "entities have " + "registers backing them on all architectures. When they don't the " + "generic name " + "will return an error.\n" + "The generic names defined in lldb are:\n" + "\n" + "pc - program counter register\n" + "ra - return address register\n" + "fp - frame pointer register\n" + "sp - stack pointer register\n" + "flags - the flags register\n" + "arg{1-6} - integer argument passing registers.\n"; } -static const char * -BreakpointIDHelpTextCallback () -{ - return "Breakpoints are identified using major and minor numbers; the major " - "number corresponds to the single entity that was created with a 'breakpoint " - "set' command; the minor numbers correspond to all the locations that were " - "actually found/set based on the major breakpoint. A full breakpoint ID might " - "look like 3.14, meaning the 14th location set for the 3rd breakpoint. You " - "can specify all the locations of a breakpoint by just indicating the major " - "breakpoint number. A valid breakpoint ID consists either of just the major " - "number, or the major number followed by a dot and the location number (e.g. " - "3 or 3.2 could both be valid breakpoint IDs.)"; +static const char *BreakpointIDHelpTextCallback() { + return "Breakpoints are identified using major and minor numbers; the major " + "number corresponds to the single entity that was created with a " + "'breakpoint " + "set' command; the minor numbers correspond to all the locations that " + "were " + "actually found/set based on the major breakpoint. A full breakpoint " + "ID might " + "look like 3.14, meaning the 14th location set for the 3rd " + "breakpoint. You " + "can specify all the locations of a breakpoint by just indicating the " + "major " + "breakpoint number. A valid breakpoint ID consists either of just the " + "major " + "number, or the major number followed by a dot and the location " + "number (e.g. " + "3 or 3.2 could both be valid breakpoint IDs.)"; } -static const char * -BreakpointIDRangeHelpTextCallback () -{ - return "A 'breakpoint ID list' is a manner of specifying multiple breakpoints. " - "This can be done through several mechanisms. The easiest way is to just " - "enter a space-separated list of breakpoint IDs. To specify all the " - "breakpoint locations under a major breakpoint, you can use the major " - "breakpoint number followed by '.*', eg. '5.*' means all the locations under " - "breakpoint 5. You can also indicate a range of breakpoints by using " - " - . The start-bp-id and end-bp-id for a range can " - "be any valid breakpoint IDs. It is not legal, however, to specify a range " - "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7" - " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; +static const char *BreakpointIDRangeHelpTextCallback() { + return "A 'breakpoint ID list' is a manner of specifying multiple " + "breakpoints. " + "This can be done through several mechanisms. The easiest way is to " + "just " + "enter a space-separated list of breakpoint IDs. To specify all the " + "breakpoint locations under a major breakpoint, you can use the major " + "breakpoint number followed by '.*', eg. '5.*' means all the " + "locations under " + "breakpoint 5. You can also indicate a range of breakpoints by using " + " - . The start-bp-id and end-bp-id for a " + "range can " + "be any valid breakpoint IDs. It is not legal, however, to specify a " + "range " + "using specific locations that cross major breakpoint numbers. I.e. " + "3.2 - 3.7" + " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; } -static const char * -BreakpointNameHelpTextCallback () -{ - return "A name that can be added to a breakpoint when it is created, or later " - "on with the \"breakpoint name add\" command. " - "Breakpoint names can be used to specify breakpoints in all the places breakpoint IDs " - "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, " - "and to operate on breakpoints you create without having to track the breakpoint number. " - "Note, the attributes you set when using a breakpoint name in a breakpoint command don't " - "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that " - "name. Future breakpoints " - "tagged with that name will not pick up the attributes previously given using that name. " - "In order to distinguish breakpoint names from breakpoint IDs and ranges, " - "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". " - "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations."; +static const char *BreakpointNameHelpTextCallback() { + return "A name that can be added to a breakpoint when it is created, or " + "later " + "on with the \"breakpoint name add\" command. " + "Breakpoint names can be used to specify breakpoints in all the " + "places breakpoint IDs " + "and breakpoint ID ranges can be used. As such they provide a " + "convenient way to group breakpoints, " + "and to operate on breakpoints you create without having to track the " + "breakpoint number. " + "Note, the attributes you set when using a breakpoint name in a " + "breakpoint command don't " + "adhere to the name, but instead are set individually on all the " + "breakpoints currently tagged with that " + "name. Future breakpoints " + "tagged with that name will not pick up the attributes previously " + "given using that name. " + "In order to distinguish breakpoint names from breakpoint IDs and " + "ranges, " + "names must start with a letter from a-z or A-Z and cannot contain " + "spaces, \".\" or \"-\". " + "Also, breakpoint names can only be applied to breakpoints, not to " + "breakpoint locations."; } -static const char * -GDBFormatHelpTextCallback () -{ - return "A GDB format consists of a repeat count, a format letter and a size letter. " - "The repeat count is optional and defaults to 1. The format letter is optional " - "and defaults to the previous format that was used. The size letter is optional " - "and defaults to the previous size that was used.\n" - "\n" - "Format letters include:\n" - "o - octal\n" - "x - hexadecimal\n" - "d - decimal\n" - "u - unsigned decimal\n" - "t - binary\n" - "f - float\n" - "a - address\n" - "i - instruction\n" - "c - char\n" - "s - string\n" - "T - OSType\n" - "A - float as hex\n" - "\n" - "Size letters include:\n" - "b - 1 byte (byte)\n" - "h - 2 bytes (halfword)\n" - "w - 4 bytes (word)\n" - "g - 8 bytes (giant)\n" - "\n" - "Example formats:\n" - "32xb - show 32 1 byte hexadecimal integer values\n" - "16xh - show 16 2 byte hexadecimal integer values\n" - "64 - show 64 2 byte hexadecimal integer values (format and size from the last format)\n" - "dw - show 1 4 byte decimal integer value\n" - ; -} - -static const char * -FormatHelpTextCallback () -{ - - static char* help_text_ptr = nullptr; - - if (help_text_ptr) - return help_text_ptr; - - StreamString sstr; - sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n"; - for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1)) - { - if (f != eFormatDefault) - sstr.PutChar('\n'); - - char format_char = FormatManager::GetFormatAsFormatChar(f); - if (format_char) - sstr.Printf("'%c' or ", format_char); - - sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f)); - } - - sstr.Flush(); - - std::string data = sstr.GetString(); - - help_text_ptr = new char[data.length()+1]; - - data.copy(help_text_ptr, data.length()); - - return help_text_ptr; +static const char *GDBFormatHelpTextCallback() { + return "A GDB format consists of a repeat count, a format letter and a size " + "letter. " + "The repeat count is optional and defaults to 1. The format letter is " + "optional " + "and defaults to the previous format that was used. The size letter " + "is optional " + "and defaults to the previous size that was used.\n" + "\n" + "Format letters include:\n" + "o - octal\n" + "x - hexadecimal\n" + "d - decimal\n" + "u - unsigned decimal\n" + "t - binary\n" + "f - float\n" + "a - address\n" + "i - instruction\n" + "c - char\n" + "s - string\n" + "T - OSType\n" + "A - float as hex\n" + "\n" + "Size letters include:\n" + "b - 1 byte (byte)\n" + "h - 2 bytes (halfword)\n" + "w - 4 bytes (word)\n" + "g - 8 bytes (giant)\n" + "\n" + "Example formats:\n" + "32xb - show 32 1 byte hexadecimal integer values\n" + "16xh - show 16 2 byte hexadecimal integer values\n" + "64 - show 64 2 byte hexadecimal integer values (format and size " + "from the last format)\n" + "dw - show 1 4 byte decimal integer value\n"; } -static const char * -LanguageTypeHelpTextCallback () -{ - static char* help_text_ptr = nullptr; - - if (help_text_ptr) - return help_text_ptr; - - StreamString sstr; - sstr << "One of the following languages:\n"; - - Language::PrintAllLanguages(sstr, " ", "\n"); - - sstr.Flush(); - - std::string data = sstr.GetString(); - - help_text_ptr = new char[data.length()+1]; - - data.copy(help_text_ptr, data.length()); - +static const char *FormatHelpTextCallback() { + + static char *help_text_ptr = nullptr; + + if (help_text_ptr) return help_text_ptr; -} -static const char * -SummaryStringHelpTextCallback() -{ - return - "A summary string is a way to extract information from variables in order to present them using a summary.\n" - "Summary strings contain static text, variables, scopes and control sequences:\n" - " - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n" - " - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n" - " - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n" - " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n" - "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n" - "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" - "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" - " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" - " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed." - " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n" - "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." - "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" - " path refers to:\n" - " - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number" - " and displayed as an individual variable\n" - " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" - " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" - "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n" - "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the" - " special symbols only allowed as part of a variable:\n" - " %V: show the value of the object by default\n" - " %S: show the summary of the object by default\n" - " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n" - " %L: show the location of the object (memory address or a register name)\n" - " %#: show the number of children of the object\n" - " %T: show the type of the object\n" - "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses" - " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would" - " count the number of actual elements stored in an std::list:\n" - "type summary add -s \"${svar%#}\" -x \"std::list<\""; + StreamString sstr; + sstr << "One of the format names (or one-character names) that can be used " + "to show a variable's value:\n"; + for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { + if (f != eFormatDefault) + sstr.PutChar('\n'); + + char format_char = FormatManager::GetFormatAsFormatChar(f); + if (format_char) + sstr.Printf("'%c' or ", format_char); + + sstr.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); + } + + sstr.Flush(); + + std::string data = sstr.GetString(); + + help_text_ptr = new char[data.length() + 1]; + + data.copy(help_text_ptr, data.length()); + + return help_text_ptr; } -static const char * -ExprPathHelpTextCallback() -{ - return - "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n" - "For instance, given a class:\n" - " class foo {\n" - " int a;\n" - " int b; .\n" - " foo* next;\n" - " };\n" - "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n" - "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n" - "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n" - "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n" - "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n" - "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract" - " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index" - " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the" - " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; +static const char *LanguageTypeHelpTextCallback() { + static char *help_text_ptr = nullptr; + + if (help_text_ptr) + return help_text_ptr; + + StreamString sstr; + sstr << "One of the following languages:\n"; + + Language::PrintAllLanguages(sstr, " ", "\n"); + + sstr.Flush(); + + std::string data = sstr.GetString(); + + help_text_ptr = new char[data.length() + 1]; + + data.copy(help_text_ptr, data.length()); + + return help_text_ptr; } -void -CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help) -{ - CommandInterpreter& interpreter = GetCommandInterpreter(); - std::stringstream lineStream (long_help); - std::string line; - while (std::getline (lineStream, line)) { - if (line.empty()) { - output_strm << "\n"; - continue; - } - size_t result = line.find_first_not_of (" \t"); - if (result == std::string::npos) { - result = 0; - } - std::string whitespace_prefix = line.substr (0, result); - std::string remainder = line.substr (result); - interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str()); - } +static const char *SummaryStringHelpTextCallback() { + return "A summary string is a way to extract information from variables in " + "order to present them using a summary.\n" + "Summary strings contain static text, variables, scopes and control " + "sequences:\n" + " - Static text can be any sequence of non-special characters, i.e. " + "anything but '{', '}', '$', or '\\'.\n" + " - Variables are sequences of characters beginning with ${, ending " + "with } and that contain symbols in the format described below.\n" + " - Scopes are any sequence of text between { and }. Anything " + "included in a scope will only appear in the output summary if there " + "were no errors.\n" + " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus " + "'\\$', '\\{' and '\\}'.\n" + "A summary string works by copying static text verbatim, turning " + "control sequences into their character counterpart, expanding " + "variables and trying to expand scopes.\n" + "A variable is expanded by giving it a value other than its textual " + "representation, and the way this is done depends on what comes after " + "the ${ marker.\n" + "The most common sequence if ${var followed by an expression path, " + "which is the text one would type to access a member of an aggregate " + "types, given a variable of that type" + " (e.g. if type T has a member named x, which has a member named y, " + "and if t is of type T, the expression path would be .x.y and the way " + "to fit that into a summary string would be" + " ${var.x.y}). You can also use ${*var followed by an expression path " + "and in that case the object referred by the path will be " + "dereferenced before being displayed." + " If the object is not a pointer, doing so will cause an error. For " + "additional details on expression paths, you can type 'help " + "expr-path'. \n" + "By default, summary strings attempt to display the summary for any " + "variable they reference, and if that fails the value. If neither can " + "be shown, nothing is displayed." + "In a summary string, you can also use an array index [n], or a " + "slice-like range [n-m]. This can have two different meanings " + "depending on what kind of object the expression" + " path refers to:\n" + " - if it is a scalar type (any basic type like int, float, ...) the " + "expression is a bitfield, i.e. the bits indicated by the indexing " + "operator are extracted out of the number" + " and displayed as an individual variable\n" + " - if it is an array or pointer the array items indicated by the " + "indexing operator are shown as the result of the variable. if the " + "expression is an array, real array items are" + " printed; if it is a pointer, the pointer-as-array syntax is used to " + "obtain the values (this means, the latter case can have no range " + "checking)\n" + "If you are trying to display an array for which the size is known, " + "you can also use [] instead of giving an exact range. This has the " + "effect of showing items 0 thru size - 1.\n" + "Additionally, a variable can contain an (optional) format code, as " + "in ${var.x.y%code}, where code can be any of the valid formats " + "described in 'help format', or one of the" + " special symbols only allowed as part of a variable:\n" + " %V: show the value of the object by default\n" + " %S: show the summary of the object by default\n" + " %@: show the runtime-provided object description (for " + "Objective-C, it calls NSPrintForDebugger; for C/C++ it does " + "nothing)\n" + " %L: show the location of the object (memory address or a " + "register name)\n" + " %#: show the number of children of the object\n" + " %T: show the type of the object\n" + "Another variable that you can use in summary strings is ${svar . " + "This sequence works exactly like ${var, including the fact that " + "${*svar is an allowed sequence, but uses" + " the object's synthetic children provider instead of the actual " + "objects. For instance, if you are using STL synthetic children " + "providers, the following summary string would" + " count the number of actual elements stored in an std::list:\n" + "type summary add -s \"${svar%#}\" -x \"std::list<\""; } -void -CommandObject::GenerateHelpText (CommandReturnObject &result) -{ - GenerateHelpText(result.GetOutputStream()); - - result.SetStatus (eReturnStatusSuccessFinishNoResult); +static const char *ExprPathHelpTextCallback() { + return "An expression path is the sequence of symbols that is used in C/C++ " + "to access a member variable of an aggregate object (class).\n" + "For instance, given a class:\n" + " class foo {\n" + " int a;\n" + " int b; .\n" + " foo* next;\n" + " };\n" + "the expression to read item b in the item pointed to by next for foo " + "aFoo would be aFoo.next->b.\n" + "Given that aFoo could just be any object of type foo, the string " + "'.next->b' is the expression path, because it can be attached to any " + "foo instance to achieve the effect.\n" + "Expression paths in LLDB include dot (.) and arrow (->) operators, " + "and most commands using expression paths have ways to also accept " + "the star (*) operator.\n" + "The meaning of these operators is the same as the usual one given to " + "them by the C/C++ standards.\n" + "LLDB also has support for indexing ([ ]) in expression paths, and " + "extends the traditional meaning of the square brackets operator to " + "allow bitfield extraction:\n" + "for objects of native types (int, float, char, ...) saying '[n-m]' " + "as an expression path (where n and m are any positive integers, e.g. " + "[3-5]) causes LLDB to extract" + " bits n thru m from the value of the variable. If n == m, [n] is " + "also allowed as a shortcut syntax. For arrays and pointers, " + "expression paths can only contain one index" + " and the meaning of the operation is the same as the one defined by " + "C/C++ (item extraction). Some commands extend bitfield-like syntax " + "for arrays and pointers with the" + " meaning of array slicing (taking elements n thru m inside the array " + "or pointed-to memory)."; } -void -CommandObject::GenerateHelpText (Stream &output_strm) -{ - CommandInterpreter& interpreter = GetCommandInterpreter(); - if (WantsRawCommandString()) - { - std::string help_text(GetHelp()); - help_text.append(" Expects 'raw' input (see 'help raw-input'.)"); - interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(), 1); - } - else - interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1); - output_strm.Printf("\nSyntax: %s\n", GetSyntax()); - Options *options = GetOptions(); - if (options != nullptr) - { - options->GenerateOptionUsage(output_strm, this, - GetCommandInterpreter() - .GetDebugger().GetTerminalWidth()); +void CommandObject::FormatLongHelpText(Stream &output_strm, + const char *long_help) { + CommandInterpreter &interpreter = GetCommandInterpreter(); + std::stringstream lineStream(long_help); + std::string line; + while (std::getline(lineStream, line)) { + if (line.empty()) { + output_strm << "\n"; + continue; } - const char *long_help = GetHelpLong(); - if ((long_help != nullptr) && (strlen(long_help) > 0)) - { - FormatLongHelpText(output_strm, long_help); - } - if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) - { - if (WantsRawCommandString() && !WantsCompletion()) - { - // Emit the message about using ' -- ' between the end of the command options and the raw input - // conditionally, i.e., only if the command object does not want completion. - interpreter.OutputFormattedHelpText( - output_strm, "", "", - "\nImportant Note: Because this command takes 'raw' input, if you use any command options" - " you must use ' -- ' between the end of the command options and the beginning of the raw input.", - 1); - } - else if (GetNumArgumentEntries() > 0) - { - // Also emit a warning about using "--" in case you are using a command that takes options and arguments. - interpreter.OutputFormattedHelpText( - output_strm, "", "", "\nThis command takes options and free-form arguments. If your arguments resemble" - " option specifiers (i.e., they start with a - or --), you must use ' -- ' between" - " the end of the command options and the beginning of the arguments.", - 1); - } + size_t result = line.find_first_not_of(" \t"); + if (result == std::string::npos) { + result = 0; } + std::string whitespace_prefix = line.substr(0, result); + std::string remainder = line.substr(result); + interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), + remainder.c_str()); + } } -void -CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange) -{ - CommandArgumentData id_arg; - CommandArgumentData id_range_arg; +void CommandObject::GenerateHelpText(CommandReturnObject &result) { + GenerateHelpText(result.GetOutputStream()); - // Create the first variant for the first (and only) argument for this command. - id_arg.arg_type = ID; - id_arg.arg_repetition = eArgRepeatOptional; + result.SetStatus(eReturnStatusSuccessFinishNoResult); +} - // Create the second variant for the first (and only) argument for this command. - id_range_arg.arg_type = IDRange; - id_range_arg.arg_repetition = eArgRepeatOptional; +void CommandObject::GenerateHelpText(Stream &output_strm) { + CommandInterpreter &interpreter = GetCommandInterpreter(); + if (WantsRawCommandString()) { + std::string help_text(GetHelp()); + help_text.append(" Expects 'raw' input (see 'help raw-input'.)"); + interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(), + 1); + } else + interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1); + output_strm.Printf("\nSyntax: %s\n", GetSyntax()); + Options *options = GetOptions(); + if (options != nullptr) { + options->GenerateOptionUsage( + output_strm, this, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + } + const char *long_help = GetHelpLong(); + if ((long_help != nullptr) && (strlen(long_help) > 0)) { + FormatLongHelpText(output_strm, long_help); + } + if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) { + if (WantsRawCommandString() && !WantsCompletion()) { + // Emit the message about using ' -- ' between the end of the command + // options and the raw input + // conditionally, i.e., only if the command object does not want + // completion. + interpreter.OutputFormattedHelpText( + output_strm, "", "", + "\nImportant Note: Because this command takes 'raw' input, if you " + "use any command options" + " you must use ' -- ' between the end of the command options and the " + "beginning of the raw input.", + 1); + } else if (GetNumArgumentEntries() > 0) { + // Also emit a warning about using "--" in case you are using a command + // that takes options and arguments. + interpreter.OutputFormattedHelpText( + output_strm, "", "", + "\nThis command takes options and free-form arguments. If your " + "arguments resemble" + " option specifiers (i.e., they start with a - or --), you must use " + "' -- ' between" + " the end of the command options and the beginning of the arguments.", + 1); + } + } +} - // The first (and only) argument for this command could be either an id or an id_range. - // Push both variants into the entry for the first argument for this command. - arg.push_back(id_arg); - arg.push_back(id_range_arg); +void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, + CommandArgumentType ID, + CommandArgumentType IDRange) { + CommandArgumentData id_arg; + CommandArgumentData id_range_arg; + + // Create the first variant for the first (and only) argument for this + // command. + id_arg.arg_type = ID; + id_arg.arg_repetition = eArgRepeatOptional; + + // Create the second variant for the first (and only) argument for this + // command. + id_range_arg.arg_type = IDRange; + id_range_arg.arg_repetition = eArgRepeatOptional; + + // The first (and only) argument for this command could be either an id or an + // id_range. + // Push both variants into the entry for the first argument for this command. + arg.push_back(id_arg); + arg.push_back(id_range_arg); } -const char * -CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type) -{ - assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentTypeAsCString"); - return g_arguments_data[arg_type].arg_name; +const char *CommandObject::GetArgumentTypeAsCString( + const lldb::CommandArgumentType arg_type) { + assert(arg_type < eArgTypeLastArg && + "Invalid argument type passed to GetArgumentTypeAsCString"); + return g_arguments_data[arg_type].arg_name; } -const char * -CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type) -{ - assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentDescriptionAsCString"); - return g_arguments_data[arg_type].help_text; +const char *CommandObject::GetArgumentDescriptionAsCString( + const lldb::CommandArgumentType arg_type) { + assert(arg_type < eArgTypeLastArg && + "Invalid argument type passed to GetArgumentDescriptionAsCString"); + return g_arguments_data[arg_type].help_text; } -Target * -CommandObject::GetDummyTarget() -{ - return m_interpreter.GetDebugger().GetDummyTarget(); +Target *CommandObject::GetDummyTarget() { + return m_interpreter.GetDebugger().GetDummyTarget(); } -Target * -CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) -{ - return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); +Target *CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) { + return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); } -Thread * -CommandObject::GetDefaultThread() -{ - Thread *thread_to_use = m_exe_ctx.GetThreadPtr(); - if (thread_to_use) - return thread_to_use; - - Process *process = m_exe_ctx.GetProcessPtr(); - if (!process) - { - Target *target = m_exe_ctx.GetTargetPtr(); - if (!target) - { - target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - } - if (target) - process = target->GetProcessSP().get(); +Thread *CommandObject::GetDefaultThread() { + Thread *thread_to_use = m_exe_ctx.GetThreadPtr(); + if (thread_to_use) + return thread_to_use; + + Process *process = m_exe_ctx.GetProcessPtr(); + if (!process) { + Target *target = m_exe_ctx.GetTargetPtr(); + if (!target) { + target = m_interpreter.GetDebugger().GetSelectedTarget().get(); } + if (target) + process = target->GetProcessSP().get(); + } - if (process) - return process->GetThreadList().GetSelectedThread().get(); - else - return nullptr; + if (process) + return process->GetThreadList().GetSelectedThread().get(); + else + return nullptr; } -bool -CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result) -{ - bool handled = false; - Args cmd_args (args_string); - if (HasOverrideCallback()) - { - Args full_args (GetCommandName ()); - full_args.AppendArguments(cmd_args); - handled = InvokeOverrideCallback (full_args.GetConstArgumentVector(), result); +bool CommandObjectParsed::Execute(const char *args_string, + CommandReturnObject &result) { + bool handled = false; + Args cmd_args(args_string); + if (HasOverrideCallback()) { + Args full_args(GetCommandName()); + full_args.AppendArguments(cmd_args); + handled = + InvokeOverrideCallback(full_args.GetConstArgumentVector(), result); + } + if (!handled) { + for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i) { + const char *tmp_str = cmd_args.GetArgumentAtIndex(i); + if (tmp_str[0] == '`') // back-quote + cmd_args.ReplaceArgumentAtIndex( + i, m_interpreter.ProcessEmbeddedScriptCommands(tmp_str)); } - if (!handled) - { - for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i) - { - const char *tmp_str = cmd_args.GetArgumentAtIndex (i); - if (tmp_str[0] == '`') // back-quote - cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str)); - } - - if (CheckRequirements(result)) - { - if (ParseOptions (cmd_args, result)) - { - // Call the command-specific version of 'Execute', passing it the already processed arguments. - handled = DoExecute (cmd_args, result); - } - } - Cleanup(); + if (CheckRequirements(result)) { + if (ParseOptions(cmd_args, result)) { + // Call the command-specific version of 'Execute', passing it the + // already processed arguments. + handled = DoExecute(cmd_args, result); + } } - return handled; + + Cleanup(); + } + return handled; } -bool -CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result) -{ - bool handled = false; - if (HasOverrideCallback()) - { - std::string full_command (GetCommandName ()); - full_command += ' '; - full_command += args_string; - const char *argv[2] = { nullptr, nullptr }; - argv[0] = full_command.c_str(); - handled = InvokeOverrideCallback (argv, result); - } - if (!handled) - { - if (CheckRequirements(result)) - handled = DoExecute (args_string, result); - - Cleanup(); - } - return handled; +bool CommandObjectRaw::Execute(const char *args_string, + CommandReturnObject &result) { + bool handled = false; + if (HasOverrideCallback()) { + std::string full_command(GetCommandName()); + full_command += ' '; + full_command += args_string; + const char *argv[2] = {nullptr, nullptr}; + argv[0] = full_command.c_str(); + handled = InvokeOverrideCallback(argv, result); + } + if (!handled) { + if (CheckRequirements(result)) + handled = DoExecute(args_string, result); + + Cleanup(); + } + return handled; } -static -const char *arch_helper() -{ - static StreamString g_archs_help; - if (g_archs_help.Empty()) - { - StringList archs; - ArchSpec::AutoComplete(nullptr, archs); - g_archs_help.Printf("These are the supported architecture names:\n"); - archs.Join("\n", g_archs_help); - } - return g_archs_help.GetData(); +static const char *arch_helper() { + static StreamString g_archs_help; + if (g_archs_help.Empty()) { + StringList archs; + ArchSpec::AutoComplete(nullptr, archs); + g_archs_help.Printf("These are the supported architecture names:\n"); + archs.Join("\n", g_archs_help); + } + return g_archs_help.GetData(); } CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { @@ -1204,12 +1137,10 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { // clang-format on }; -const CommandObject::ArgumentTableEntry* -CommandObject::GetArgumentTable () -{ - // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration - assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg); - return CommandObject::g_arguments_data; +const CommandObject::ArgumentTableEntry *CommandObject::GetArgumentTable() { + // If this assertion fires, then the table above is out of date with the + // CommandArgumentType enumeration + assert((sizeof(CommandObject::g_arguments_data) / + sizeof(CommandObject::ArgumentTableEntry)) == eArgTypeLastArg); + return CommandObject::g_arguments_data; } - - diff --git a/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/lldb/source/Interpreter/CommandObjectRegexCommand.cpp index 12de6d0dc73..53e14c416b5 100644 --- a/lldb/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/lldb/source/Interpreter/CommandObjectRegexCommand.cpp @@ -22,129 +22,99 @@ using namespace lldb_private; //---------------------------------------------------------------------- // CommandObjectRegexCommand constructor //---------------------------------------------------------------------- -CommandObjectRegexCommand::CommandObjectRegexCommand -( - CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t max_matches, - uint32_t completion_type_mask, - bool is_removable -) : - CommandObjectRaw (interpreter, name, help, syntax), - m_max_matches (max_matches), - m_completion_type_mask (completion_type_mask), - m_entries (), - m_is_removable (is_removable) -{ -} +CommandObjectRegexCommand::CommandObjectRegexCommand( + CommandInterpreter &interpreter, const char *name, const char *help, + const char *syntax, uint32_t max_matches, uint32_t completion_type_mask, + bool is_removable) + : CommandObjectRaw(interpreter, name, help, syntax), + m_max_matches(max_matches), m_completion_type_mask(completion_type_mask), + m_entries(), m_is_removable(is_removable) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CommandObjectRegexCommand::~CommandObjectRegexCommand() -{ -} - +CommandObjectRegexCommand::~CommandObjectRegexCommand() {} -bool -CommandObjectRegexCommand::DoExecute -( - const char *command, - CommandReturnObject &result -) -{ - if (command) - { - EntryCollection::const_iterator pos, end = m_entries.end(); - for (pos = m_entries.begin(); pos != end; ++pos) - { - RegularExpression::Match regex_match(m_max_matches); +bool CommandObjectRegexCommand::DoExecute(const char *command, + CommandReturnObject &result) { + if (command) { + EntryCollection::const_iterator pos, end = m_entries.end(); + for (pos = m_entries.begin(); pos != end; ++pos) { + RegularExpression::Match regex_match(m_max_matches); - if (pos->regex.Execute (command, ®ex_match)) - { - std::string new_command(pos->command); - std::string match_str; - char percent_var[8]; - size_t idx, percent_var_idx; - for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx) - { - if (regex_match.GetMatchAtIndex (command, match_idx, match_str)) - { - const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx); - for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; ) - { - new_command.erase(percent_var_idx, percent_var_len); - new_command.insert(percent_var_idx, match_str); - idx += percent_var_idx + match_str.size(); - } - } - } - // Interpret the new command and return this as the result! - if (m_interpreter.GetExpandRegexAliases()) - result.GetOutputStream().Printf("%s\n", new_command.c_str()); - // Pass in true for "no context switching". The command that called us should have set up the context - // appropriately, we shouldn't have to redo that. - return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true); + if (pos->regex.Execute(command, ®ex_match)) { + std::string new_command(pos->command); + std::string match_str; + char percent_var[8]; + size_t idx, percent_var_idx; + for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) { + if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) { + const int percent_var_len = + ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx); + for (idx = 0; (percent_var_idx = new_command.find( + percent_var, idx)) != std::string::npos;) { + new_command.erase(percent_var_idx, percent_var_len); + new_command.insert(percent_var_idx, match_str); + idx += percent_var_idx + match_str.size(); } + } } - result.SetStatus(eReturnStatusFailed); - if (GetSyntax() != nullptr) - result.AppendError (GetSyntax()); - else - result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n", - command, - m_cmd_name.c_str()); - return false; + // Interpret the new command and return this as the result! + if (m_interpreter.GetExpandRegexAliases()) + result.GetOutputStream().Printf("%s\n", new_command.c_str()); + // Pass in true for "no context switching". The command that called us + // should have set up the context + // appropriately, we shouldn't have to redo that. + return m_interpreter.HandleCommand(new_command.c_str(), + eLazyBoolCalculate, result, nullptr, + true, true); + } } - result.AppendError("empty command passed to regular expression command"); result.SetStatus(eReturnStatusFailed); + if (GetSyntax() != nullptr) + result.AppendError(GetSyntax()); + else + result.AppendErrorWithFormat("Command contents '%s' failed to match any " + "regular expression in the '%s' regex " + "command.\n", + command, m_cmd_name.c_str()); return false; + } + result.AppendError("empty command passed to regular expression command"); + result.SetStatus(eReturnStatusFailed); + return false; } - -bool -CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *command_cstr) -{ - m_entries.resize(m_entries.size() + 1); - // Only add the regular expression if it compiles - if (m_entries.back().regex.Compile (re_cstr)) - { - m_entries.back().command.assign (command_cstr); - return true; - } - // The regex didn't compile... - m_entries.pop_back(); - return false; +bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr, + const char *command_cstr) { + m_entries.resize(m_entries.size() + 1); + // Only add the regular expression if it compiles + if (m_entries.back().regex.Compile(re_cstr)) { + m_entries.back().command.assign(command_cstr); + return true; + } + // The regex didn't compile... + m_entries.pop_back(); + return false; } -int -CommandObjectRegexCommand::HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - if (m_completion_type_mask) - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - CommandCompletions::InvokeCommonCompletionCallbacks (GetCommandInterpreter(), - m_completion_type_mask, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } - else - { - matches.Clear(); - word_complete = false; - } - return 0; +int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) { + if (m_completion_type_mask) { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(), + match_start_point, max_return_elements, nullptr, word_complete, + matches); + return matches.GetSize(); + } else { + matches.Clear(); + word_complete = false; + } + return 0; } diff --git a/lldb/source/Interpreter/CommandObjectScript.cpp b/lldb/source/Interpreter/CommandObjectScript.cpp index e7de490878f..0891298c5ac 100644 --- a/lldb/source/Interpreter/CommandObjectScript.cpp +++ b/lldb/source/Interpreter/CommandObjectScript.cpp @@ -30,61 +30,57 @@ using namespace lldb_private; // CommandObjectScript //------------------------------------------------------------------------- -CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter, ScriptLanguage script_lang) - : CommandObjectRaw(interpreter, "script", "Invoke the script interpreter with provided code and display any " - "results. Start the interactive interpreter if no code is supplied.", - "script []") -{ -} +CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter, + ScriptLanguage script_lang) + : CommandObjectRaw( + interpreter, "script", + "Invoke the script interpreter with provided code and display any " + "results. Start the interactive interpreter if no code is supplied.", + "script []") {} -CommandObjectScript::~CommandObjectScript () -{ -} +CommandObjectScript::~CommandObjectScript() {} -bool -CommandObjectScript::DoExecute -( - const char *command, - CommandReturnObject &result -) -{ +bool CommandObjectScript::DoExecute(const char *command, + CommandReturnObject &result) { #ifdef LLDB_DISABLE_PYTHON - // if we ever support languages other than Python this simple #ifdef won't work - result.AppendError("your copy of LLDB does not support scripting."); - result.SetStatus (eReturnStatusFailed); - return false; + // if we ever support languages other than Python this simple #ifdef won't + // work + result.AppendError("your copy of LLDB does not support scripting."); + result.SetStatus(eReturnStatusFailed); + return false; #else - if (m_interpreter.GetDebugger().GetScriptLanguage() == lldb::eScriptLanguageNone) - { - result.AppendError("the script-lang setting is set to none - scripting not available"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter (); - - if (script_interpreter == nullptr) - { - result.AppendError("no script interpreter"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - DataVisualization::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it - - if (command == nullptr || command[0] == '\0') - { - script_interpreter->ExecuteInterpreterLoop (); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - // We can do better when reporting the status of one-liner script execution. - if (script_interpreter->ExecuteOneLine (command, &result)) - result.SetStatus(eReturnStatusSuccessFinishNoResult); - else - result.SetStatus(eReturnStatusFailed); + if (m_interpreter.GetDebugger().GetScriptLanguage() == + lldb::eScriptLanguageNone) { + result.AppendError( + "the script-lang setting is set to none - scripting not available"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter(); + if (script_interpreter == nullptr) { + result.AppendError("no script interpreter"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + DataVisualization::ForceUpdate(); // script might change Python code we use + // for formatting.. make sure we keep up to + // date with it + + if (command == nullptr || command[0] == '\0') { + script_interpreter->ExecuteInterpreterLoop(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); + } + + // We can do better when reporting the status of one-liner script execution. + if (script_interpreter->ExecuteOneLine(command, &result)) + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusFailed); + + return result.Succeeded(); #endif } diff --git a/lldb/source/Interpreter/CommandObjectScript.h b/lldb/source/Interpreter/CommandObjectScript.h index 5365aaac4cb..2c05ca9468d 100644 --- a/lldb/source/Interpreter/CommandObjectScript.h +++ b/lldb/source/Interpreter/CommandObjectScript.h @@ -22,17 +22,15 @@ namespace lldb_private { // CommandObjectScript //------------------------------------------------------------------------- -class CommandObjectScript : public CommandObjectRaw -{ +class CommandObjectScript : public CommandObjectRaw { public: - CommandObjectScript(CommandInterpreter &interpreter, - lldb::ScriptLanguage script_lang); + CommandObjectScript(CommandInterpreter &interpreter, + lldb::ScriptLanguage script_lang); - ~CommandObjectScript() override; + ~CommandObjectScript() override; protected: - bool - DoExecute(const char *command, CommandReturnObject &result) override; + bool DoExecute(const char *command, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/lldb/source/Interpreter/CommandOptionValidators.cpp b/lldb/source/Interpreter/CommandOptionValidators.cpp index 7d66de53c0b..1e614a958c7 100644 --- a/lldb/source/Interpreter/CommandOptionValidators.cpp +++ b/lldb/source/Interpreter/CommandOptionValidators.cpp @@ -15,25 +15,23 @@ using namespace lldb; using namespace lldb_private; -bool PosixPlatformCommandOptionValidator::IsValid(Platform &platform, const ExecutionContext &target) const -{ - llvm::Triple::OSType os = platform.GetSystemArchitecture().GetTriple().getOS(); - switch (os) - { - // Are there any other platforms that are not POSIX-compatible? - case llvm::Triple::Win32: - return false; - default: - return true; - } +bool PosixPlatformCommandOptionValidator::IsValid( + Platform &platform, const ExecutionContext &target) const { + llvm::Triple::OSType os = + platform.GetSystemArchitecture().GetTriple().getOS(); + switch (os) { + // Are there any other platforms that are not POSIX-compatible? + case llvm::Triple::Win32: + return false; + default: + return true; + } } -const char* PosixPlatformCommandOptionValidator::ShortConditionString() const -{ - return "POSIX"; +const char *PosixPlatformCommandOptionValidator::ShortConditionString() const { + return "POSIX"; } -const char* PosixPlatformCommandOptionValidator::LongConditionString() const -{ - return "Option only valid for POSIX-compliant hosts."; +const char *PosixPlatformCommandOptionValidator::LongConditionString() const { + return "Option only valid for POSIX-compliant hosts."; } diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp index b083c7f69f1..c289fd793a8 100644 --- a/lldb/source/Interpreter/CommandReturnObject.cpp +++ b/lldb/source/Interpreter/CommandReturnObject.cpp @@ -19,218 +19,154 @@ using namespace lldb; using namespace lldb_private; -static void -DumpStringToStreamWithNewline (Stream &strm, const std::string &s, bool add_newline_if_empty) -{ - bool add_newline = false; - if (s.empty()) - { - add_newline = add_newline_if_empty; - } - else - { - // We already checked for empty above, now make sure there is a newline - // in the error, and if there isn't one, add one. - strm.Write(s.c_str(), s.size()); - - const char last_char = *s.rbegin(); - add_newline = last_char != '\n' && last_char != '\r'; - - } - if (add_newline) - strm.EOL(); -} - - -CommandReturnObject::CommandReturnObject () : - m_out_stream (), - m_err_stream (), - m_status (eReturnStatusStarted), - m_did_change_process_state (false), - m_interactive (true), - m_abnormal_stop_was_expected(false) -{ -} - -CommandReturnObject::~CommandReturnObject () -{ -} - -void -CommandReturnObject::AppendErrorWithFormat (const char *format, ...) -{ - if (!format) - return; - va_list args; - va_start (args, format); - StreamString sstrm; - sstrm.PrintfVarArg(format, args); - va_end (args); - - - const std::string &s = sstrm.GetString(); - if (!s.empty()) - { - Stream &error_strm = GetErrorStream(); - error_strm.PutCString ("error: "); - DumpStringToStreamWithNewline (error_strm, s, false); - } -} - -void -CommandReturnObject::AppendMessageWithFormat (const char *format, ...) -{ - if (!format) - return; - va_list args; - va_start (args, format); - StreamString sstrm; - sstrm.PrintfVarArg(format, args); - va_end (args); - - GetOutputStream().Printf("%s", sstrm.GetData()); -} - -void -CommandReturnObject::AppendWarningWithFormat (const char *format, ...) -{ - if (!format) - return; - va_list args; - va_start (args, format); - StreamString sstrm; - sstrm.PrintfVarArg(format, args); - va_end (args); - - GetErrorStream().Printf("warning: %s", sstrm.GetData()); -} - -void -CommandReturnObject::AppendMessage (const char *in_string) -{ - if (!in_string) - return; - GetOutputStream().Printf("%s\n", in_string); -} - -void -CommandReturnObject::AppendWarning (const char *in_string) -{ - if (!in_string || *in_string == '\0') - return; - GetErrorStream().Printf("warning: %s\n", in_string); +static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s, + bool add_newline_if_empty) { + bool add_newline = false; + if (s.empty()) { + add_newline = add_newline_if_empty; + } else { + // We already checked for empty above, now make sure there is a newline + // in the error, and if there isn't one, add one. + strm.Write(s.c_str(), s.size()); + + const char last_char = *s.rbegin(); + add_newline = last_char != '\n' && last_char != '\r'; + } + if (add_newline) + strm.EOL(); +} + +CommandReturnObject::CommandReturnObject() + : m_out_stream(), m_err_stream(), m_status(eReturnStatusStarted), + m_did_change_process_state(false), m_interactive(true), + m_abnormal_stop_was_expected(false) {} + +CommandReturnObject::~CommandReturnObject() {} + +void CommandReturnObject::AppendErrorWithFormat(const char *format, ...) { + if (!format) + return; + va_list args; + va_start(args, format); + StreamString sstrm; + sstrm.PrintfVarArg(format, args); + va_end(args); + + const std::string &s = sstrm.GetString(); + if (!s.empty()) { + Stream &error_strm = GetErrorStream(); + error_strm.PutCString("error: "); + DumpStringToStreamWithNewline(error_strm, s, false); + } +} + +void CommandReturnObject::AppendMessageWithFormat(const char *format, ...) { + if (!format) + return; + va_list args; + va_start(args, format); + StreamString sstrm; + sstrm.PrintfVarArg(format, args); + va_end(args); + + GetOutputStream().Printf("%s", sstrm.GetData()); +} + +void CommandReturnObject::AppendWarningWithFormat(const char *format, ...) { + if (!format) + return; + va_list args; + va_start(args, format); + StreamString sstrm; + sstrm.PrintfVarArg(format, args); + va_end(args); + + GetErrorStream().Printf("warning: %s", sstrm.GetData()); +} + +void CommandReturnObject::AppendMessage(const char *in_string) { + if (!in_string) + return; + GetOutputStream().Printf("%s\n", in_string); +} + +void CommandReturnObject::AppendWarning(const char *in_string) { + if (!in_string || *in_string == '\0') + return; + GetErrorStream().Printf("warning: %s\n", in_string); } // Similar to AppendWarning, but do not prepend 'warning: ' to message, and // don't append "\n" to the end of it. -void -CommandReturnObject::AppendRawWarning (const char *in_string) -{ - if (in_string && in_string[0]) - GetErrorStream().PutCString(in_string); +void CommandReturnObject::AppendRawWarning(const char *in_string) { + if (in_string && in_string[0]) + GetErrorStream().PutCString(in_string); } -void -CommandReturnObject::AppendError (const char *in_string) -{ - if (!in_string || *in_string == '\0') - return; - GetErrorStream().Printf ("error: %s\n", in_string); +void CommandReturnObject::AppendError(const char *in_string) { + if (!in_string || *in_string == '\0') + return; + GetErrorStream().Printf("error: %s\n", in_string); } -void -CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr) -{ - const char *error_cstr = error.AsCString(); - if (error_cstr == nullptr) - error_cstr = fallback_error_cstr; - SetError(error_cstr); +void CommandReturnObject::SetError(const Error &error, + const char *fallback_error_cstr) { + const char *error_cstr = error.AsCString(); + if (error_cstr == nullptr) + error_cstr = fallback_error_cstr; + SetError(error_cstr); } -void -CommandReturnObject::SetError (const char *error_cstr) -{ - if (error_cstr) - { - AppendError (error_cstr); - SetStatus (eReturnStatusFailed); - } +void CommandReturnObject::SetError(const char *error_cstr) { + if (error_cstr) { + AppendError(error_cstr); + SetStatus(eReturnStatusFailed); + } } // Similar to AppendError, but do not prepend 'Error: ' to message, and // don't append "\n" to the end of it. -void -CommandReturnObject::AppendRawError (const char *in_string) -{ - if (in_string && in_string[0]) - GetErrorStream().PutCString(in_string); +void CommandReturnObject::AppendRawError(const char *in_string) { + if (in_string && in_string[0]) + GetErrorStream().PutCString(in_string); } -void -CommandReturnObject::SetStatus (ReturnStatus status) -{ - m_status = status; -} - -ReturnStatus -CommandReturnObject::GetStatus () -{ - return m_status; -} +void CommandReturnObject::SetStatus(ReturnStatus status) { m_status = status; } -bool -CommandReturnObject::Succeeded () -{ - return m_status <= eReturnStatusSuccessContinuingResult; -} +ReturnStatus CommandReturnObject::GetStatus() { return m_status; } -bool -CommandReturnObject::HasResult () -{ - return (m_status == eReturnStatusSuccessFinishResult || - m_status == eReturnStatusSuccessContinuingResult); +bool CommandReturnObject::Succeeded() { + return m_status <= eReturnStatusSuccessContinuingResult; } -void -CommandReturnObject::Clear() -{ - lldb::StreamSP stream_sp; - stream_sp = m_out_stream.GetStreamAtIndex (eStreamStringIndex); - if (stream_sp) - static_cast(stream_sp.get())->Clear(); - stream_sp = m_err_stream.GetStreamAtIndex (eStreamStringIndex); - if (stream_sp) - static_cast(stream_sp.get())->Clear(); - m_status = eReturnStatusStarted; - m_did_change_process_state = false; - m_interactive = true; +bool CommandReturnObject::HasResult() { + return (m_status == eReturnStatusSuccessFinishResult || + m_status == eReturnStatusSuccessContinuingResult); } -bool -CommandReturnObject::GetDidChangeProcessState () -{ - return m_did_change_process_state; +void CommandReturnObject::Clear() { + lldb::StreamSP stream_sp; + stream_sp = m_out_stream.GetStreamAtIndex(eStreamStringIndex); + if (stream_sp) + static_cast(stream_sp.get())->Clear(); + stream_sp = m_err_stream.GetStreamAtIndex(eStreamStringIndex); + if (stream_sp) + static_cast(stream_sp.get())->Clear(); + m_status = eReturnStatusStarted; + m_did_change_process_state = false; + m_interactive = true; } -void -CommandReturnObject::SetDidChangeProcessState (bool b) -{ - m_did_change_process_state = b; -} - - -bool -CommandReturnObject::GetInteractive () const -{ - return m_interactive; +bool CommandReturnObject::GetDidChangeProcessState() { + return m_did_change_process_state; } -void -CommandReturnObject::SetInteractive (bool b) -{ - m_interactive = b; +void CommandReturnObject::SetDidChangeProcessState(bool b) { + m_did_change_process_state = b; } +bool CommandReturnObject::GetInteractive() const { return m_interactive; } +void CommandReturnObject::SetInteractive(bool b) { m_interactive = b; } diff --git a/lldb/source/Interpreter/OptionGroupArchitecture.cpp b/lldb/source/Interpreter/OptionGroupArchitecture.cpp index 063466a99c4..2de0dd2493f 100644 --- a/lldb/source/Interpreter/OptionGroupArchitecture.cpp +++ b/lldb/source/Interpreter/OptionGroupArchitecture.cpp @@ -18,70 +18,53 @@ using namespace lldb; using namespace lldb_private; -OptionGroupArchitecture::OptionGroupArchitecture() : - m_arch_str () -{ -} +OptionGroupArchitecture::OptionGroupArchitecture() : m_arch_str() {} -OptionGroupArchitecture::~OptionGroupArchitecture () -{ -} +OptionGroupArchitecture::~OptionGroupArchitecture() {} -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1 , false, "arch" , 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture , "Specify the architecture for the target."}, +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "arch", 'a', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeArchitecture, + "Specify the architecture for the target."}, }; -uint32_t -OptionGroupArchitecture::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t OptionGroupArchitecture::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } -const OptionDefinition * -OptionGroupArchitecture::GetDefinitions () -{ - return g_option_table; +const OptionDefinition *OptionGroupArchitecture::GetDefinitions() { + return g_option_table; } -bool -OptionGroupArchitecture::GetArchitecture (Platform *platform, ArchSpec &arch) -{ - if (m_arch_str.empty()) - arch.Clear(); - else - arch.SetTriple(m_arch_str.c_str(), platform); - return arch.IsValid(); +bool OptionGroupArchitecture::GetArchitecture(Platform *platform, + ArchSpec &arch) { + if (m_arch_str.empty()) + arch.Clear(); + else + arch.SetTriple(m_arch_str.c_str(), platform); + return arch.IsValid(); } +Error OptionGroupArchitecture::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; -Error -OptionGroupArchitecture::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 'a': + m_arch_str.assign(option_arg); + break; - switch (short_option) - { - case 'a': - m_arch_str.assign (option_arg); - break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; + return error; } -void -OptionGroupArchitecture::OptionParsingStarting( - ExecutionContext *execution_context) -{ - m_arch_str.clear(); +void OptionGroupArchitecture::OptionParsingStarting( + ExecutionContext *execution_context) { + m_arch_str.clear(); } - diff --git a/lldb/source/Interpreter/OptionGroupBoolean.cpp b/lldb/source/Interpreter/OptionGroupBoolean.cpp index f21c3adacf1..4bc55ee2628 100644 --- a/lldb/source/Interpreter/OptionGroupBoolean.cpp +++ b/lldb/source/Interpreter/OptionGroupBoolean.cpp @@ -17,52 +17,44 @@ using namespace lldb; using namespace lldb_private; -OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask, - bool required, - const char *long_option, - int short_option, - const char *usage_text, - bool default_value, - bool no_argument_toggle_default) : - m_value (default_value, default_value) -{ - m_option_definition.usage_mask = usage_mask; - m_option_definition.required = required; - m_option_definition.long_option = long_option; - m_option_definition.short_option = short_option; - m_option_definition.validator = nullptr; - m_option_definition.option_has_arg = no_argument_toggle_default ? OptionParser::eNoArgument : OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; - m_option_definition.completion_type = 0; - m_option_definition.argument_type = eArgTypeBoolean; - m_option_definition.usage_text = usage_text; +OptionGroupBoolean::OptionGroupBoolean(uint32_t usage_mask, bool required, + const char *long_option, + int short_option, const char *usage_text, + bool default_value, + bool no_argument_toggle_default) + : m_value(default_value, default_value) { + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.validator = nullptr; + m_option_definition.option_has_arg = no_argument_toggle_default + ? OptionParser::eNoArgument + : OptionParser::eRequiredArgument; + m_option_definition.enum_values = nullptr; + m_option_definition.completion_type = 0; + m_option_definition.argument_type = eArgTypeBoolean; + m_option_definition.usage_text = usage_text; } -OptionGroupBoolean::~OptionGroupBoolean () -{ -} +OptionGroupBoolean::~OptionGroupBoolean() {} -Error -OptionGroupBoolean::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - if (m_option_definition.option_has_arg == OptionParser::eNoArgument) - { - // Not argument, toggle the default value and mark the option as having been set - m_value.SetCurrentValue (!m_value.GetDefaultValue()); - m_value.SetOptionWasSet (); - } - else - { - error = m_value.SetValueFromString (option_arg); - } - return error; +Error OptionGroupBoolean::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error; + if (m_option_definition.option_has_arg == OptionParser::eNoArgument) { + // Not argument, toggle the default value and mark the option as having been + // set + m_value.SetCurrentValue(!m_value.GetDefaultValue()); + m_value.SetOptionWasSet(); + } else { + error = m_value.SetValueFromString(option_arg); + } + return error; } -void -OptionGroupBoolean::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_value.Clear(); +void OptionGroupBoolean::OptionParsingStarting( + ExecutionContext *execution_context) { + m_value.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupFile.cpp b/lldb/source/Interpreter/OptionGroupFile.cpp index 1f82e579191..0dc485b75b7 100644 --- a/lldb/source/Interpreter/OptionGroupFile.cpp +++ b/lldb/source/Interpreter/OptionGroupFile.cpp @@ -17,83 +17,65 @@ using namespace lldb; using namespace lldb_private; -OptionGroupFile::OptionGroupFile (uint32_t usage_mask, - bool required, - const char *long_option, - int short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, - const char *usage_text) : - m_file () -{ - m_option_definition.usage_mask = usage_mask; - m_option_definition.required = required; - m_option_definition.long_option = long_option; - m_option_definition.short_option = short_option; - m_option_definition.validator = nullptr; - m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; - m_option_definition.completion_type = completion_type; - m_option_definition.argument_type = argument_type; - m_option_definition.usage_text = usage_text; +OptionGroupFile::OptionGroupFile(uint32_t usage_mask, bool required, + const char *long_option, int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text) + : m_file() { + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.validator = nullptr; + m_option_definition.option_has_arg = OptionParser::eRequiredArgument; + m_option_definition.enum_values = nullptr; + m_option_definition.completion_type = completion_type; + m_option_definition.argument_type = argument_type; + m_option_definition.usage_text = usage_text; } -OptionGroupFile::~OptionGroupFile () -{ -} +OptionGroupFile::~OptionGroupFile() {} -Error -OptionGroupFile::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error (m_file.SetValueFromString (option_arg)); - return error; +Error OptionGroupFile::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error(m_file.SetValueFromString(option_arg)); + return error; } -void -OptionGroupFile::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_file.Clear(); +void OptionGroupFile::OptionParsingStarting( + ExecutionContext *execution_context) { + m_file.Clear(); } - -OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask, - bool required, - const char *long_option, - int short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, - const char *usage_text) : - m_file_list () -{ - m_option_definition.usage_mask = usage_mask; - m_option_definition.required = required; - m_option_definition.long_option = long_option; - m_option_definition.short_option = short_option; - m_option_definition.validator = nullptr; - m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; - m_option_definition.completion_type = completion_type; - m_option_definition.argument_type = argument_type; - m_option_definition.usage_text = usage_text; +OptionGroupFileList::OptionGroupFileList( + uint32_t usage_mask, bool required, const char *long_option, + int short_option, uint32_t completion_type, + lldb::CommandArgumentType argument_type, const char *usage_text) + : m_file_list() { + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.validator = nullptr; + m_option_definition.option_has_arg = OptionParser::eRequiredArgument; + m_option_definition.enum_values = nullptr; + m_option_definition.completion_type = completion_type; + m_option_definition.argument_type = argument_type; + m_option_definition.usage_text = usage_text; } -OptionGroupFileList::~OptionGroupFileList () -{ -} +OptionGroupFileList::~OptionGroupFileList() {} -Error -OptionGroupFileList::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error (m_file_list.SetValueFromString (option_arg)); - return error; +Error OptionGroupFileList::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error(m_file_list.SetValueFromString(option_arg)); + return error; } -void -OptionGroupFileList::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_file_list.Clear(); +void OptionGroupFileList::OptionParsingStarting( + ExecutionContext *execution_context) { + m_file_list.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupFormat.cpp b/lldb/source/Interpreter/OptionGroupFormat.cpp index 1a1e060f7e6..aa0d3cc3369 100644 --- a/lldb/source/Interpreter/OptionGroupFormat.cpp +++ b/lldb/source/Interpreter/OptionGroupFormat.cpp @@ -22,251 +22,263 @@ using namespace lldb; using namespace lldb_private; -OptionGroupFormat::OptionGroupFormat (lldb::Format default_format, - uint64_t default_byte_size, - uint64_t default_count) : - m_format (default_format, default_format), - m_byte_size (default_byte_size, default_byte_size), - m_count (default_count, default_count), - m_prev_gdb_format('x'), - m_prev_gdb_size('w') -{ -} +OptionGroupFormat::OptionGroupFormat(lldb::Format default_format, + uint64_t default_byte_size, + uint64_t default_count) + : m_format(default_format, default_format), + m_byte_size(default_byte_size, default_byte_size), + m_count(default_count, default_count), m_prev_gdb_format('x'), + m_prev_gdb_size('w') {} -OptionGroupFormat::~OptionGroupFormat () -{ -} +OptionGroupFormat::~OptionGroupFormat() {} -static OptionDefinition -g_option_table[] = -{ -{ LLDB_OPT_SET_1, false, "format" ,'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFormat , "Specify a format to be used for display."}, -{ LLDB_OPT_SET_2, false, "gdb-format",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."}, -{ LLDB_OPT_SET_3, false, "size" ,'s', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."}, -{ LLDB_OPT_SET_4, false, "count" ,'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount , "The number of total items to display."}, +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeFormat, + "Specify a format to be used for display."}, + {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeGDBFormat, + "Specify a format using a GDB format specifier string."}, + {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeByteSize, + "The size in bytes to use when displaying with the selected format."}, + {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeCount, + "The number of total items to display."}, }; -uint32_t -OptionGroupFormat::GetNumDefinitions () -{ - if (m_byte_size.GetDefaultValue() < UINT64_MAX) - { - if (m_count.GetDefaultValue() < UINT64_MAX) - return 4; - else - return 3; - } - return 2; +uint32_t OptionGroupFormat::GetNumDefinitions() { + if (m_byte_size.GetDefaultValue() < UINT64_MAX) { + if (m_count.GetDefaultValue() < UINT64_MAX) + return 4; + else + return 3; + } + return 2; } -const OptionDefinition * -OptionGroupFormat::GetDefinitions () -{ - return g_option_table; +const OptionDefinition *OptionGroupFormat::GetDefinitions() { + return g_option_table; } -Error -OptionGroupFormat::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; +Error OptionGroupFormat::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'f': - error = m_format.SetValueFromString (option_arg); - break; + switch (short_option) { + case 'f': + error = m_format.SetValueFromString(option_arg); + break; + + case 'c': + if (m_count.GetDefaultValue() == 0) { + error.SetErrorString("--count option is disabled"); + } else { + error = m_count.SetValueFromString(option_arg); + if (m_count.GetCurrentValue() == 0) + error.SetErrorStringWithFormat("invalid --count option value '%s'", + option_arg); + } + break; + + case 's': + if (m_byte_size.GetDefaultValue() == 0) { + error.SetErrorString("--size option is disabled"); + } else { + error = m_byte_size.SetValueFromString(option_arg); + if (m_byte_size.GetCurrentValue() == 0) + error.SetErrorStringWithFormat("invalid --size option value '%s'", + option_arg); + } + break; + + case 'G': { + char *end = nullptr; + const char *gdb_format_cstr = option_arg; + uint64_t count = 0; + if (::isdigit(gdb_format_cstr[0])) { + count = strtoull(gdb_format_cstr, &end, 0); - case 'c': - if (m_count.GetDefaultValue() == 0) - { - error.SetErrorString ("--count option is disabled"); - } - else - { - error = m_count.SetValueFromString (option_arg); - if (m_count.GetCurrentValue() == 0) - error.SetErrorStringWithFormat("invalid --count option value '%s'", option_arg); - } - break; - - case 's': - if (m_byte_size.GetDefaultValue() == 0) - { - error.SetErrorString ("--size option is disabled"); - } - else - { - error = m_byte_size.SetValueFromString (option_arg); - if (m_byte_size.GetCurrentValue() == 0) - error.SetErrorStringWithFormat("invalid --size option value '%s'", option_arg); - } - break; + if (option_arg != end) + gdb_format_cstr = + end; // We have a valid count, advance the string position + else + count = 0; + } - case 'G': - { - char *end = nullptr; - const char *gdb_format_cstr = option_arg; - uint64_t count = 0; - if (::isdigit (gdb_format_cstr[0])) - { - count = strtoull (gdb_format_cstr, &end, 0); + Format format = eFormatDefault; + uint32_t byte_size = 0; - if (option_arg != end) - gdb_format_cstr = end; // We have a valid count, advance the string position - else - count = 0; - } + while (ParserGDBFormatLetter(execution_context, gdb_format_cstr[0], format, + byte_size)) { + ++gdb_format_cstr; + } - Format format = eFormatDefault; - uint32_t byte_size = 0; - - while (ParserGDBFormatLetter (execution_context, - gdb_format_cstr[0], format, - byte_size)) - { - ++gdb_format_cstr; - } - - // We the first character of the "gdb_format_cstr" is not the - // NULL terminator, we didn't consume the entire string and - // something is wrong. Also, if none of the format, size or count - // was specified correctly, then abort. - if (gdb_format_cstr[0] || (format == eFormatInvalid && byte_size == 0 && count == 0)) - { - // Nothing got set correctly - error.SetErrorStringWithFormat ("invalid gdb format string '%s'", option_arg); - return error; - } + // We the first character of the "gdb_format_cstr" is not the + // NULL terminator, we didn't consume the entire string and + // something is wrong. Also, if none of the format, size or count + // was specified correctly, then abort. + if (gdb_format_cstr[0] || + (format == eFormatInvalid && byte_size == 0 && count == 0)) { + // Nothing got set correctly + error.SetErrorStringWithFormat("invalid gdb format string '%s'", + option_arg); + return error; + } - // At least one of the format, size or count was set correctly. - // Anything that wasn't set correctly should be set to the - // previous default - if (format == eFormatInvalid) - ParserGDBFormatLetter (execution_context, m_prev_gdb_format, - format, byte_size); - - const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX; - const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX; - if (byte_size_enabled) - { - // Byte size is enabled - if (byte_size == 0) - ParserGDBFormatLetter (execution_context, m_prev_gdb_size, format, byte_size); - } - else - { - // Byte size is disabled, make sure it wasn't specified - // but if this is an address, it's actually necessary to - // specify one so don't error out - if (byte_size > 0 && format != lldb::eFormatAddressInfo) - { - error.SetErrorString ("this command doesn't support specifying a byte size"); - return error; - } - } + // At least one of the format, size or count was set correctly. + // Anything that wasn't set correctly should be set to the + // previous default + if (format == eFormatInvalid) + ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format, + byte_size); - if (count_enabled) - { - // Count is enabled and was not set, set it to the default for gdb format statements (which is 1). - if (count == 0) - count = 1; - } - else - { - // Count is disabled, make sure it wasn't specified - if (count > 0) - { - error.SetErrorString ("this command doesn't support specifying a count"); - return error; - } - } + const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX; + const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX; + if (byte_size_enabled) { + // Byte size is enabled + if (byte_size == 0) + ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format, + byte_size); + } else { + // Byte size is disabled, make sure it wasn't specified + // but if this is an address, it's actually necessary to + // specify one so don't error out + if (byte_size > 0 && format != lldb::eFormatAddressInfo) { + error.SetErrorString( + "this command doesn't support specifying a byte size"); + return error; + } + } - m_format.SetCurrentValue (format); - m_format.SetOptionWasSet (); - if (byte_size_enabled) - { - m_byte_size.SetCurrentValue (byte_size); - m_byte_size.SetOptionWasSet (); - } - if (count_enabled) - { - m_count.SetCurrentValue(count); - m_count.SetOptionWasSet (); - } - } - break; + if (count_enabled) { + // Count is enabled and was not set, set it to the default for gdb format + // statements (which is 1). + if (count == 0) + count = 1; + } else { + // Count is disabled, make sure it wasn't specified + if (count > 0) { + error.SetErrorString("this command doesn't support specifying a count"); + return error; + } + } - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; + m_format.SetCurrentValue(format); + m_format.SetOptionWasSet(); + if (byte_size_enabled) { + m_byte_size.SetCurrentValue(byte_size); + m_byte_size.SetOptionWasSet(); } + if (count_enabled) { + m_count.SetCurrentValue(count); + m_count.SetOptionWasSet(); + } + } break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } - return error; + return error; } -bool -OptionGroupFormat::ParserGDBFormatLetter(ExecutionContext *execution_context, - char format_letter, Format &format, - uint32_t &byte_size) -{ - m_has_gdb_format = true; - switch (format_letter) +bool OptionGroupFormat::ParserGDBFormatLetter( + ExecutionContext *execution_context, char format_letter, Format &format, + uint32_t &byte_size) { + m_has_gdb_format = true; + switch (format_letter) { + case 'o': + format = eFormatOctal; + m_prev_gdb_format = format_letter; + return true; + case 'x': + format = eFormatHex; + m_prev_gdb_format = format_letter; + return true; + case 'd': + format = eFormatDecimal; + m_prev_gdb_format = format_letter; + return true; + case 'u': + format = eFormatUnsigned; + m_prev_gdb_format = format_letter; + return true; + case 't': + format = eFormatBinary; + m_prev_gdb_format = format_letter; + return true; + case 'f': + format = eFormatFloat; + m_prev_gdb_format = format_letter; + return true; + case 'a': + format = eFormatAddressInfo; { - case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true; - case 'x': format = eFormatHex; m_prev_gdb_format = format_letter; return true; - case 'd': format = eFormatDecimal; m_prev_gdb_format = format_letter; return true; - case 'u': format = eFormatUnsigned; m_prev_gdb_format = format_letter; return true; - case 't': format = eFormatBinary; m_prev_gdb_format = format_letter; return true; - case 'f': format = eFormatFloat; m_prev_gdb_format = format_letter; return true; - case 'a': format = eFormatAddressInfo; - { - TargetSP target_sp = execution_context ? - execution_context->GetTargetSP() : TargetSP(); - if (target_sp) - byte_size = target_sp->GetArchitecture().GetAddressByteSize(); - m_prev_gdb_format = format_letter; - return true; - } - case 'i': format = eFormatInstruction; m_prev_gdb_format = format_letter; return true; - case 'c': format = eFormatChar; m_prev_gdb_format = format_letter; return true; - case 's': format = eFormatCString; m_prev_gdb_format = format_letter; return true; - case 'T': format = eFormatOSType; m_prev_gdb_format = format_letter; return true; - case 'A': format = eFormatHexFloat; m_prev_gdb_format = format_letter; return true; - - // Size isn't used for printing instructions, so if a size is specified, and the previous format was - // 'i', then we should reset it to the default ('x'). Otherwise we'll continue to print as instructions, - // which isn't expected. - case 'b': - byte_size = 1; - LLVM_FALLTHROUGH; - case 'h': - byte_size = 2; - LLVM_FALLTHROUGH; - case 'w': - byte_size = 4; - LLVM_FALLTHROUGH; - case 'g': - byte_size = 8; - - m_prev_gdb_size = format_letter; - if (m_prev_gdb_format == 'i') - m_prev_gdb_format = 'x'; - return true; - - break; - default: break; + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp) + byte_size = target_sp->GetArchitecture().GetAddressByteSize(); + m_prev_gdb_format = format_letter; + return true; } - return false; + case 'i': + format = eFormatInstruction; + m_prev_gdb_format = format_letter; + return true; + case 'c': + format = eFormatChar; + m_prev_gdb_format = format_letter; + return true; + case 's': + format = eFormatCString; + m_prev_gdb_format = format_letter; + return true; + case 'T': + format = eFormatOSType; + m_prev_gdb_format = format_letter; + return true; + case 'A': + format = eFormatHexFloat; + m_prev_gdb_format = format_letter; + return true; + + // Size isn't used for printing instructions, so if a size is specified, and + // the previous format was + // 'i', then we should reset it to the default ('x'). Otherwise we'll + // continue to print as instructions, + // which isn't expected. + case 'b': + byte_size = 1; + LLVM_FALLTHROUGH; + case 'h': + byte_size = 2; + LLVM_FALLTHROUGH; + case 'w': + byte_size = 4; + LLVM_FALLTHROUGH; + case 'g': + byte_size = 8; + + m_prev_gdb_size = format_letter; + if (m_prev_gdb_format == 'i') + m_prev_gdb_format = 'x'; + return true; + + break; + default: + break; + } + return false; } -void -OptionGroupFormat::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_format.Clear(); - m_byte_size.Clear(); - m_count.Clear(); - m_has_gdb_format = false; +void OptionGroupFormat::OptionParsingStarting( + ExecutionContext *execution_context) { + m_format.Clear(); + m_byte_size.Clear(); + m_count.Clear(); + m_has_gdb_format = false; } diff --git a/lldb/source/Interpreter/OptionGroupOutputFile.cpp b/lldb/source/Interpreter/OptionGroupOutputFile.cpp index 857d21e53f4..d9eccb9709b 100644 --- a/lldb/source/Interpreter/OptionGroupOutputFile.cpp +++ b/lldb/source/Interpreter/OptionGroupOutputFile.cpp @@ -18,69 +18,55 @@ using namespace lldb; using namespace lldb_private; -OptionGroupOutputFile::OptionGroupOutputFile() : - m_file (), - m_append (false, false) -{ -} +OptionGroupOutputFile::OptionGroupOutputFile() + : m_file(), m_append(false, false) {} -OptionGroupOutputFile::~OptionGroupOutputFile () -{ -} +OptionGroupOutputFile::~OptionGroupOutputFile() {} -static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd' +static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd' -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1 , false, "outfile", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename , "Specify a path for capturing command output."}, - { LLDB_OPT_SET_1 , false, "append-outfile" , SHORT_OPTION_APND, - OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone , - "Append to the file specified with '--outfile '."}, +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "outfile", 'o', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeFilename, + "Specify a path for capturing command output."}, + {LLDB_OPT_SET_1, false, "append-outfile", SHORT_OPTION_APND, + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Append to the file specified with '--outfile '."}, }; -uint32_t -OptionGroupOutputFile::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t OptionGroupOutputFile::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } -const OptionDefinition * -OptionGroupOutputFile::GetDefinitions () -{ - return g_option_table; +const OptionDefinition *OptionGroupOutputFile::GetDefinitions() { + return g_option_table; } -Error -OptionGroupOutputFile::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; +Error OptionGroupOutputFile::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'o': - error = m_file.SetValueFromString (option_arg); - break; + switch (short_option) { + case 'o': + error = m_file.SetValueFromString(option_arg); + break; - case SHORT_OPTION_APND: - m_append.SetCurrentValue(true); - break; + case SHORT_OPTION_APND: + m_append.SetCurrentValue(true); + break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } - return error; + return error; } -void -OptionGroupOutputFile::OptionParsingStarting( - ExecutionContext *execution_context) -{ - m_file.Clear(); - m_append.Clear(); +void OptionGroupOutputFile::OptionParsingStarting( + ExecutionContext *execution_context) { + m_file.Clear(); + m_append.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupPlatform.cpp b/lldb/source/Interpreter/OptionGroupPlatform.cpp index f5ea857fb7d..4b3eeeabf1a 100644 --- a/lldb/source/Interpreter/OptionGroupPlatform.cpp +++ b/lldb/source/Interpreter/OptionGroupPlatform.cpp @@ -20,163 +20,145 @@ using namespace lldb; using namespace lldb_private; -PlatformSP -OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter, - const ArchSpec &arch, - bool make_selected, - Error& error, - ArchSpec &platform_arch) const -{ - PlatformSP platform_sp; - - if (!m_platform_name.empty()) - { - platform_sp = Platform::Create (ConstString(m_platform_name.c_str()), error); - if (platform_sp) - { - if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) - { - error.SetErrorStringWithFormat ("platform '%s' doesn't support '%s'", - platform_sp->GetName().GetCString(), - arch.GetTriple().getTriple().c_str()); - platform_sp.reset(); - return platform_sp; - } - } +PlatformSP OptionGroupPlatform::CreatePlatformWithOptions( + CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected, + Error &error, ArchSpec &platform_arch) const { + PlatformSP platform_sp; + + if (!m_platform_name.empty()) { + platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error); + if (platform_sp) { + if (platform_arch.IsValid() && + !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) { + error.SetErrorStringWithFormat("platform '%s' doesn't support '%s'", + platform_sp->GetName().GetCString(), + arch.GetTriple().getTriple().c_str()); + platform_sp.reset(); + return platform_sp; + } } - else if (arch.IsValid()) - { - platform_sp = Platform::Create (arch, &platform_arch, error); - } - - if (platform_sp) - { - interpreter.GetDebugger().GetPlatformList().Append (platform_sp, make_selected); - if (m_os_version_major != UINT32_MAX) - { - platform_sp->SetOSVersion (m_os_version_major, - m_os_version_minor, - m_os_version_update); - } - - if (m_sdk_sysroot) - platform_sp->SetSDKRootDirectory (m_sdk_sysroot); - - if (m_sdk_build) - platform_sp->SetSDKBuild (m_sdk_build); + } else if (arch.IsValid()) { + platform_sp = Platform::Create(arch, &platform_arch, error); + } + + if (platform_sp) { + interpreter.GetDebugger().GetPlatformList().Append(platform_sp, + make_selected); + if (m_os_version_major != UINT32_MAX) { + platform_sp->SetOSVersion(m_os_version_major, m_os_version_minor, + m_os_version_update); } - return platform_sp; + if (m_sdk_sysroot) + platform_sp->SetSDKRootDirectory(m_sdk_sysroot); + + if (m_sdk_build) + platform_sp->SetSDKBuild(m_sdk_build); + } + + return platform_sp; } -void -OptionGroupPlatform::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_platform_name.clear(); - m_sdk_sysroot.Clear(); - m_sdk_build.Clear(); - m_os_version_major = UINT32_MAX; - m_os_version_minor = UINT32_MAX; - m_os_version_update = UINT32_MAX; +void OptionGroupPlatform::OptionParsingStarting( + ExecutionContext *execution_context) { + m_platform_name.clear(); + m_sdk_sysroot.Clear(); + m_sdk_build.Clear(); + m_os_version_major = UINT32_MAX; + m_os_version_minor = UINT32_MAX; + m_os_version_update = UINT32_MAX; } -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."}, - { LLDB_OPT_SET_ALL, false, "version" , 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." }, - { LLDB_OPT_SET_ALL, false, "build" , 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK build number." }, - { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." } -}; - -const OptionDefinition* -OptionGroupPlatform::GetDefinitions () -{ - if (m_include_platform_option) - return g_option_table; - return g_option_table + 1; +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to " + "use for this target, creating the " + "platform if necessary."}, + {LLDB_OPT_SET_ALL, false, "version", 'v', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeNone, + "Specify the initial SDK version to use prior to connecting."}, + {LLDB_OPT_SET_ALL, false, "build", 'b', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeNone, + "Specify the initial SDK build number."}, + {LLDB_OPT_SET_ALL, false, "sysroot", 'S', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory " + "that contains a root of all " + "remote system files."}}; + +const OptionDefinition *OptionGroupPlatform::GetDefinitions() { + if (m_include_platform_option) + return g_option_table; + return g_option_table + 1; } -uint32_t -OptionGroupPlatform::GetNumDefinitions () -{ - if (m_include_platform_option) - return llvm::array_lengthof(g_option_table); - return llvm::array_lengthof(g_option_table) - 1; +uint32_t OptionGroupPlatform::GetNumDefinitions() { + if (m_include_platform_option) + return llvm::array_lengthof(g_option_table); + return llvm::array_lengthof(g_option_table) - 1; } +Error OptionGroupPlatform::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error; + if (!m_include_platform_option) + ++option_idx; + + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'p': + m_platform_name.assign(option_arg); + break; + + case 'v': + if (Args::StringToVersion(option_arg, m_os_version_major, + m_os_version_minor, + m_os_version_update) == option_arg) + error.SetErrorStringWithFormat("invalid version string '%s'", option_arg); + break; + + case 'b': + m_sdk_build.SetCString(option_arg); + break; + + case 'S': + m_sdk_sysroot.SetCString(option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } + return error; +} -Error -OptionGroupPlatform::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - if (!m_include_platform_option) - ++option_idx; - - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'p': - m_platform_name.assign (option_arg); - break; - - case 'v': - if (Args::StringToVersion (option_arg, - m_os_version_major, - m_os_version_minor, - m_os_version_update) == option_arg) - error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg); - break; - - case 'b': - m_sdk_build.SetCString (option_arg); - break; - - case 'S': - m_sdk_sysroot.SetCString (option_arg); - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; +bool OptionGroupPlatform::PlatformMatches( + const lldb::PlatformSP &platform_sp) const { + if (platform_sp) { + if (!m_platform_name.empty()) { + if (platform_sp->GetName() != ConstString(m_platform_name.c_str())) + return false; } - return error; -} -bool -OptionGroupPlatform::PlatformMatches(const lldb::PlatformSP &platform_sp) const -{ - if (platform_sp) - { - if (!m_platform_name.empty()) - { - if (platform_sp->GetName() != ConstString(m_platform_name.c_str())) - return false; - } - - if (m_sdk_build && m_sdk_build != platform_sp->GetSDKBuild()) - return false; - - if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory()) - return false; - - if (m_os_version_major != UINT32_MAX) - { - uint32_t major, minor, update; - if (platform_sp->GetOSVersion (major, minor, update)) - { - if (m_os_version_major != major) - return false; - if (m_os_version_minor != minor) - return false; - if (m_os_version_update != update) - return false; - } - } - return true; + if (m_sdk_build && m_sdk_build != platform_sp->GetSDKBuild()) + return false; + + if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory()) + return false; + + if (m_os_version_major != UINT32_MAX) { + uint32_t major, minor, update; + if (platform_sp->GetOSVersion(major, minor, update)) { + if (m_os_version_major != major) + return false; + if (m_os_version_minor != minor) + return false; + if (m_os_version_update != update) + return false; + } } - return false; + return true; + } + return false; } diff --git a/lldb/source/Interpreter/OptionGroupString.cpp b/lldb/source/Interpreter/OptionGroupString.cpp index 1f45844e543..12d7f499fdb 100644 --- a/lldb/source/Interpreter/OptionGroupString.cpp +++ b/lldb/source/Interpreter/OptionGroupString.cpp @@ -17,43 +17,35 @@ using namespace lldb; using namespace lldb_private; -OptionGroupString::OptionGroupString (uint32_t usage_mask, - bool required, - const char *long_option, - int short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, - const char *usage_text, - const char *default_value) : - m_value (default_value, default_value) -{ - m_option_definition.usage_mask = usage_mask; - m_option_definition.required = required; - m_option_definition.long_option = long_option; - m_option_definition.short_option = short_option; - m_option_definition.validator = nullptr; - m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; - m_option_definition.completion_type = completion_type; - m_option_definition.argument_type = argument_type; - m_option_definition.usage_text = usage_text; +OptionGroupString::OptionGroupString(uint32_t usage_mask, bool required, + const char *long_option, int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text, + const char *default_value) + : m_value(default_value, default_value) { + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.validator = nullptr; + m_option_definition.option_has_arg = OptionParser::eRequiredArgument; + m_option_definition.enum_values = nullptr; + m_option_definition.completion_type = completion_type; + m_option_definition.argument_type = argument_type; + m_option_definition.usage_text = usage_text; } -OptionGroupString::~OptionGroupString () -{ -} +OptionGroupString::~OptionGroupString() {} -Error -OptionGroupString::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error (m_value.SetValueFromString (option_arg)); - return error; +Error OptionGroupString::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error(m_value.SetValueFromString(option_arg)); + return error; } -void -OptionGroupString::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_value.Clear(); +void OptionGroupString::OptionParsingStarting( + ExecutionContext *execution_context) { + m_value.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupUInt64.cpp b/lldb/source/Interpreter/OptionGroupUInt64.cpp index 5cc0d5deb20..4a3d660455e 100644 --- a/lldb/source/Interpreter/OptionGroupUInt64.cpp +++ b/lldb/source/Interpreter/OptionGroupUInt64.cpp @@ -17,43 +17,35 @@ using namespace lldb; using namespace lldb_private; -OptionGroupUInt64::OptionGroupUInt64 (uint32_t usage_mask, - bool required, - const char *long_option, - int short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, - const char *usage_text, - uint64_t default_value) : - m_value (default_value, default_value) -{ - m_option_definition.usage_mask = usage_mask; - m_option_definition.required = required; - m_option_definition.long_option = long_option; - m_option_definition.short_option = short_option; - m_option_definition.validator = nullptr; - m_option_definition.option_has_arg = OptionParser::eRequiredArgument; - m_option_definition.enum_values = nullptr; - m_option_definition.completion_type = completion_type; - m_option_definition.argument_type = argument_type; - m_option_definition.usage_text = usage_text; +OptionGroupUInt64::OptionGroupUInt64(uint32_t usage_mask, bool required, + const char *long_option, int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text, + uint64_t default_value) + : m_value(default_value, default_value) { + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.validator = nullptr; + m_option_definition.option_has_arg = OptionParser::eRequiredArgument; + m_option_definition.enum_values = nullptr; + m_option_definition.completion_type = completion_type; + m_option_definition.argument_type = argument_type; + m_option_definition.usage_text = usage_text; } -OptionGroupUInt64::~OptionGroupUInt64 () -{ -} +OptionGroupUInt64::~OptionGroupUInt64() {} -Error -OptionGroupUInt64::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error (m_value.SetValueFromString (option_arg)); - return error; +Error OptionGroupUInt64::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error(m_value.SetValueFromString(option_arg)); + return error; } -void -OptionGroupUInt64::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_value.Clear(); +void OptionGroupUInt64::OptionParsingStarting( + ExecutionContext *execution_context) { + m_value.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupUUID.cpp b/lldb/source/Interpreter/OptionGroupUUID.cpp index 0873dba1f58..2f786096a52 100644 --- a/lldb/source/Interpreter/OptionGroupUUID.cpp +++ b/lldb/source/Interpreter/OptionGroupUUID.cpp @@ -18,59 +18,45 @@ using namespace lldb; using namespace lldb_private; -OptionGroupUUID::OptionGroupUUID() : - m_uuid () -{ -} +OptionGroupUUID::OptionGroupUUID() : m_uuid() {} -OptionGroupUUID::~OptionGroupUUID () -{ -} +OptionGroupUUID::~OptionGroupUUID() {} -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1 , false, "uuid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."}, +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."}, }; -uint32_t -OptionGroupUUID::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t OptionGroupUUID::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } -const OptionDefinition * -OptionGroupUUID::GetDefinitions () -{ - return g_option_table; +const OptionDefinition *OptionGroupUUID::GetDefinitions() { + return g_option_table; } -Error -OptionGroupUUID::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'u': - error = m_uuid.SetValueFromString (option_arg); - if (error.Success()) - m_uuid.SetOptionWasSet(); - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; +Error OptionGroupUUID::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'u': + error = m_uuid.SetValueFromString(option_arg); + if (error.Success()) + m_uuid.SetOptionWasSet(); + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } + + return error; } -void -OptionGroupUUID::OptionParsingStarting(ExecutionContext *execution_context) -{ - m_uuid.Clear(); +void OptionGroupUUID::OptionParsingStarting( + ExecutionContext *execution_context) { + m_uuid.Clear(); } diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 718ddc77f82..5ce7fb8ed72 100644 --- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -15,191 +15,209 @@ // Project includes #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/Utils.h" using namespace lldb; using namespace lldb_private; -OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() -{ -} - -OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay () -{ +OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() {} + +OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {} + +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "dynamic-type", 'd', + OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0, + eArgTypeNone, "Show the object as its full dynamic type, not its static " + "type, if available."}, + {LLDB_OPT_SET_1, false, "synthetic-type", 'S', + OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, + "Show the object obeying its synthetic provider, if available."}, + {LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when " + "dumping aggregate types (default is " + "infinity)."}, + {LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr, + nullptr, 0, eArgTypeNone, "Display results in a flat format that uses " + "expression paths for each variable or member."}, + {LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr, + nullptr, 0, eArgTypeNone, "Show variable location information."}, + {LLDB_OPT_SET_1, false, "object-description", 'O', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Print as an Objective-C object."}, + {LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be " + "traversed when dumping values " + "(default is zero)."}, + {LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, + nullptr, nullptr, 0, eArgTypeNone, + "Show variable types when dumping values."}, + {LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', + OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, + "Set the depth at which omitting summary information stops (default is " + "1)."}, + {LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, + nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, + {LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, + nullptr, nullptr, 0, eArgTypeNone, + "Ignore the upper bound on the number of children to show."}, + {LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."}, + {LLDB_OPT_SET_1, false, "element-count", 'Z', + OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, + "Treat the result of the expression as if its type is an array of this " + "many values."}, + {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}}; + +uint32_t OptionGroupValueObjectDisplay::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1, false, "dynamic-type", 'd', OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."}, - { LLDB_OPT_SET_1, false, "synthetic-type", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."}, - { LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."}, - { LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."}, - { LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable location information."}, - { LLDB_OPT_SET_1, false, "object-description", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print as an Objective-C object."}, - { LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."}, - { LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable types when dumping values."}, - { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."}, - { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, - { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."}, - { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr,0, eArgTypeBoolean, "Show results of type validators."}, - { LLDB_OPT_SET_1, false, "element-count", 'Z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Treat the result of the expression as if its type is an array of this many values."}, - { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } -}; - -uint32_t -OptionGroupValueObjectDisplay::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +const OptionDefinition *OptionGroupValueObjectDisplay::GetDefinitions() { + return g_option_table; } -const OptionDefinition * -OptionGroupValueObjectDisplay::GetDefinitions () -{ - return g_option_table; -} - - -Error -OptionGroupValueObjectDisplay::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext - *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; - bool success = false; - - switch (short_option) - { - case 'd': - { - int32_t result; - result = Args::StringToOptionEnum (option_arg, g_dynamic_value_types, 2, error); - if (error.Success()) - use_dynamic = (lldb::DynamicValueType) result; - } - break; - case 'T': show_types = true; break; - case 'L': show_location= true; break; - case 'F': flat_output = true; break; - case 'O': use_objc = true; break; - case 'R': be_raw = true; break; - case 'A': ignore_cap = true; break; - - case 'D': - max_depth = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg); - break; - - case 'Z': - elem_count = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid element count '%s'", option_arg); - break; - - case 'P': - ptr_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg); - break; - - case 'Y': - if (option_arg) - { - no_summary_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg); - } - else - no_summary_depth = 1; - break; - - case 'S': - use_synth = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg); - break; - - case 'V': - run_validator = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid validate '%s'", option_arg); - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; +Error OptionGroupValueObjectDisplay::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; + bool success = false; + + switch (short_option) { + case 'd': { + int32_t result; + result = + Args::StringToOptionEnum(option_arg, g_dynamic_value_types, 2, error); + if (error.Success()) + use_dynamic = (lldb::DynamicValueType)result; + } break; + case 'T': + show_types = true; + break; + case 'L': + show_location = true; + break; + case 'F': + flat_output = true; + break; + case 'O': + use_objc = true; + break; + case 'R': + be_raw = true; + break; + case 'A': + ignore_cap = true; + break; + + case 'D': + max_depth = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg); + break; + + case 'Z': + elem_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid element count '%s'", option_arg); + break; + + case 'P': + ptr_depth = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg); + break; + + case 'Y': + if (option_arg) { + no_summary_depth = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid pointer depth '%s'", + option_arg); + } else + no_summary_depth = 1; + break; + + case 'S': + use_synth = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg); + break; + + case 'V': + run_validator = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid validate '%s'", option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } + + return error; } -void -OptionGroupValueObjectDisplay::OptionParsingStarting(ExecutionContext - *execution_context) -{ - // If these defaults change, be sure to modify AnyOptionWasSet(). - show_types = false; - no_summary_depth = 0; - show_location = false; - flat_output = false; - use_objc = false; - max_depth = UINT32_MAX; - ptr_depth = 0; - elem_count = 0; - use_synth = true; - be_raw = false; - ignore_cap = false; - run_validator = false; - - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : TargetSP(); - if (target_sp) - use_dynamic = target_sp->GetPreferDynamicValue(); - else - { - // If we don't have any targets, then dynamic values won't do us much good. - use_dynamic = lldb::eNoDynamicValues; - } +void OptionGroupValueObjectDisplay::OptionParsingStarting( + ExecutionContext *execution_context) { + // If these defaults change, be sure to modify AnyOptionWasSet(). + show_types = false; + no_summary_depth = 0; + show_location = false; + flat_output = false; + use_objc = false; + max_depth = UINT32_MAX; + ptr_depth = 0; + elem_count = 0; + use_synth = true; + be_raw = false; + ignore_cap = false; + run_validator = false; + + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp) + use_dynamic = target_sp->GetPreferDynamicValue(); + else { + // If we don't have any targets, then dynamic values won't do us much good. + use_dynamic = lldb::eNoDynamicValues; + } } -DumpValueObjectOptions -OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity, - lldb::Format format, - lldb::TypeSummaryImplSP summary_sp) -{ - DumpValueObjectOptions options; - options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Always,ptr_depth} ); - if (use_objc) - options.SetShowSummary(false); - else - options.SetOmitSummaryDepth(no_summary_depth); - options.SetMaximumDepth(max_depth) - .SetShowTypes(show_types) - .SetShowLocation(show_location) - .SetUseObjectiveC(use_objc) - .SetUseDynamicType(use_dynamic) - .SetUseSyntheticValue(use_synth) - .SetFlatOutput(flat_output) - .SetIgnoreCap(ignore_cap) - .SetFormat(format) - .SetSummary(summary_sp); - - if (lang_descr_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact) - options.SetHideRootType(use_objc) - .SetHideName(use_objc) - .SetHideValue(use_objc); - - if (be_raw) - options.SetRawDisplay(); - - options.SetRunValidator(run_validator); - - options.SetElementCount(elem_count); - - return options; +DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions( + LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity, + lldb::Format format, lldb::TypeSummaryImplSP summary_sp) { + DumpValueObjectOptions options; + options.SetMaximumPointerDepth( + {DumpValueObjectOptions::PointerDepth::Mode::Always, ptr_depth}); + if (use_objc) + options.SetShowSummary(false); + else + options.SetOmitSummaryDepth(no_summary_depth); + options.SetMaximumDepth(max_depth) + .SetShowTypes(show_types) + .SetShowLocation(show_location) + .SetUseObjectiveC(use_objc) + .SetUseDynamicType(use_dynamic) + .SetUseSyntheticValue(use_synth) + .SetFlatOutput(flat_output) + .SetIgnoreCap(ignore_cap) + .SetFormat(format) + .SetSummary(summary_sp); + + if (lang_descr_verbosity == + eLanguageRuntimeDescriptionDisplayVerbosityCompact) + options.SetHideRootType(use_objc).SetHideName(use_objc).SetHideValue( + use_objc); + + if (be_raw) + options.SetRawDisplay(); + + options.SetRunValidator(run_validator); + + options.SetElementCount(elem_count); + + return options; } diff --git a/lldb/source/Interpreter/OptionGroupVariable.cpp b/lldb/source/Interpreter/OptionGroupVariable.cpp index 6ee71aed800..253a2ede151 100644 --- a/lldb/source/Interpreter/OptionGroupVariable.cpp +++ b/lldb/source/Interpreter/OptionGroupVariable.cpp @@ -22,121 +22,129 @@ using namespace lldb; using namespace lldb_private; -// if you add any options here, remember to update the counters in OptionGroupVariable::GetNumDefinitions() -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit function arguments."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit local variables."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show the current frame source file global and static variables."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "The argument for name lookups are regular expressions."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."}, - { LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify the summary that the variable output should use."}, - { LLDB_OPT_SET_2, false, "summary-string", 'z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify a summary string to use to format the variable output."}, +// if you add any options here, remember to update the counters in +// OptionGroupVariable::GetNumDefinitions() +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Omit function arguments."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Omit local variables."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Show the current frame source file global and static variables."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration", 'c', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Show variable declaration information (source file and line where the " + "variable was declared)."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, + "The argument for name lookups are regular expressions."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', + OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, + "Show variable scope (argument, local, global, static)."}, + {LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, + nullptr, nullptr, 0, eArgTypeName, + "Specify the summary that the variable output should use."}, + {LLDB_OPT_SET_2, false, "summary-string", 'z', + OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, + "Specify a summary string to use to format the variable output."}, }; -static Error -ValidateNamedSummary (const char* str, void*) -{ - if (!str || !str[0]) - return Error("must specify a valid named summary"); - TypeSummaryImplSP summary_sp; - if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(str), summary_sp) == false) - return Error("must specify a valid named summary"); - return Error(); +static Error ValidateNamedSummary(const char *str, void *) { + if (!str || !str[0]) + return Error("must specify a valid named summary"); + TypeSummaryImplSP summary_sp; + if (DataVisualization::NamedSummaryFormats::GetSummaryFormat( + ConstString(str), summary_sp) == false) + return Error("must specify a valid named summary"); + return Error(); } -static Error -ValidateSummaryString (const char* str, void*) -{ - if (!str || !str[0]) - return Error("must specify a non-empty summary string"); - return Error(); +static Error ValidateSummaryString(const char *str, void *) { + if (!str || !str[0]) + return Error("must specify a non-empty summary string"); + return Error(); } -OptionGroupVariable::OptionGroupVariable (bool show_frame_options) : - OptionGroup(), - include_frame_options (show_frame_options), - summary(ValidateNamedSummary), - summary_string(ValidateSummaryString) -{ +OptionGroupVariable::OptionGroupVariable(bool show_frame_options) + : OptionGroup(), include_frame_options(show_frame_options), + summary(ValidateNamedSummary), summary_string(ValidateSummaryString) {} + +OptionGroupVariable::~OptionGroupVariable() {} + +Error OptionGroupVariable::SetOptionValue(uint32_t option_idx, + const char *option_arg, + ExecutionContext *execution_context) { + Error error; + if (!include_frame_options) + option_idx += 3; + const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 'r': + use_regex = true; + break; + case 'a': + show_args = false; + break; + case 'l': + show_locals = false; + break; + case 'g': + show_globals = true; + break; + case 'c': + show_decl = true; + break; + case 's': + show_scope = true; + break; + case 'y': + error = summary.SetCurrentValue(option_arg); + break; + case 'z': + error = summary_string.SetCurrentValue(option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + + return error; } -OptionGroupVariable::~OptionGroupVariable () -{ -} - -Error -OptionGroupVariable::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - if (!include_frame_options) - option_idx += 3; - const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'r': use_regex = true; break; - case 'a': show_args = false; break; - case 'l': show_locals = false; break; - case 'g': show_globals = true; break; - case 'c': show_decl = true; break; - case 's': - show_scope = true; - break; - case 'y': - error = summary.SetCurrentValue(option_arg); - break; - case 'z': - error = summary_string.SetCurrentValue(option_arg); - break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - - return error; -} - -void -OptionGroupVariable::OptionParsingStarting(ExecutionContext *execution_context) -{ - show_args = true; // Frame option only - show_locals = true; // Frame option only - show_globals = false; // Frame option only - show_decl = false; - use_regex = false; - show_scope = false; - summary.Clear(); - summary_string.Clear(); +void OptionGroupVariable::OptionParsingStarting( + ExecutionContext *execution_context) { + show_args = true; // Frame option only + show_locals = true; // Frame option only + show_globals = false; // Frame option only + show_decl = false; + use_regex = false; + show_scope = false; + summary.Clear(); + summary_string.Clear(); } #define NUM_FRAME_OPTS 3 -const OptionDefinition* -OptionGroupVariable::GetDefinitions () -{ - // Show the "--no-args", "--no-locals" and "--show-globals" - // options if we are showing frame specific options - if (include_frame_options) - return g_option_table; +const OptionDefinition *OptionGroupVariable::GetDefinitions() { + // Show the "--no-args", "--no-locals" and "--show-globals" + // options if we are showing frame specific options + if (include_frame_options) + return g_option_table; - // Skip the "--no-args", "--no-locals" and "--show-globals" - // options if we are not showing frame specific options (globals only) - return &g_option_table[NUM_FRAME_OPTS]; + // Skip the "--no-args", "--no-locals" and "--show-globals" + // options if we are not showing frame specific options (globals only) + return &g_option_table[NUM_FRAME_OPTS]; } -uint32_t -OptionGroupVariable::GetNumDefinitions () -{ - // Count the "--no-args", "--no-locals" and "--show-globals" - // options if we are showing frame specific options. - if (include_frame_options) - return llvm::array_lengthof(g_option_table); - else - return llvm::array_lengthof(g_option_table) - NUM_FRAME_OPTS; +uint32_t OptionGroupVariable::GetNumDefinitions() { + // Count the "--no-args", "--no-locals" and "--show-globals" + // options if we are showing frame specific options. + if (include_frame_options) + return llvm::array_lengthof(g_option_table); + else + return llvm::array_lengthof(g_option_table) - NUM_FRAME_OPTS; } - - diff --git a/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/lldb/source/Interpreter/OptionGroupWatchpoint.cpp index 82d0fa99742..8ed964085bf 100644 --- a/lldb/source/Interpreter/OptionGroupWatchpoint.cpp +++ b/lldb/source/Interpreter/OptionGroupWatchpoint.cpp @@ -13,110 +13,90 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-enumerations.h" #include "lldb/Interpreter/Args.h" #include "lldb/Utility/Utils.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; -static OptionEnumValueElement g_watch_type[] = -{ - { OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"}, - { OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"}, - { OptionGroupWatchpoint::eWatchReadWrite, "read_write", "Watch for read/write"}, - { 0, nullptr, nullptr } -}; - -static OptionEnumValueElement g_watch_size[] = -{ - { 1, "1", "Watch for byte size of 1"}, - { 2, "2", "Watch for byte size of 2"}, - { 4, "4", "Watch for byte size of 4"}, - { 8, "8", "Watch for byte size of 8"}, - { 0, nullptr, nullptr } -}; - -static OptionDefinition -g_option_table[] = -{ - { LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, nullptr, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."}, - { LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, nullptr, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."} -}; - - -bool -OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) -{ - for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i) - { - if (g_watch_size[i].value == 0) - break; - if (watch_size == g_watch_size[i].value) - return true; - } - return false; +static OptionEnumValueElement g_watch_type[] = { + {OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"}, + {OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"}, + {OptionGroupWatchpoint::eWatchReadWrite, "read_write", + "Watch for read/write"}, + {0, nullptr, nullptr}}; + +static OptionEnumValueElement g_watch_size[] = { + {1, "1", "Watch for byte size of 1"}, + {2, "2", "Watch for byte size of 2"}, + {4, "4", "Watch for byte size of 4"}, + {8, "8", "Watch for byte size of 8"}, + {0, nullptr, nullptr}}; + +static OptionDefinition g_option_table[] = { + {LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, + nullptr, g_watch_type, 0, eArgTypeWatchType, + "Specify the type of watching to perform."}, + {LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, + nullptr, g_watch_size, 0, eArgTypeByteSize, + "Number of bytes to use to watch a region."}}; + +bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) { + for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i) { + if (g_watch_size[i].value == 0) + break; + if (watch_size == g_watch_size[i].value) + return true; + } + return false; } -OptionGroupWatchpoint::OptionGroupWatchpoint () : - OptionGroup() -{ -} - -OptionGroupWatchpoint::~OptionGroupWatchpoint () -{ -} - -Error -OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'w': - { - WatchType tmp_watch_type; - tmp_watch_type = (WatchType) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); - if (error.Success()) - { - watch_type = tmp_watch_type; - watch_type_specified = true; - } - break; - } - case 's': - watch_size = (uint32_t) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; +OptionGroupWatchpoint::OptionGroupWatchpoint() : OptionGroup() {} + +OptionGroupWatchpoint::~OptionGroupWatchpoint() {} + +Error OptionGroupWatchpoint::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 'w': { + WatchType tmp_watch_type; + tmp_watch_type = (WatchType)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, 0, error); + if (error.Success()) { + watch_type = tmp_watch_type; + watch_type_specified = true; } - - return error; + break; + } + case 's': + watch_size = (uint32_t)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, 0, error); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + + return error; } -void -OptionGroupWatchpoint::OptionParsingStarting(ExecutionContext - *execution_context) -{ - watch_type_specified = false; - watch_type = eWatchInvalid; - watch_size = 0; +void OptionGroupWatchpoint::OptionParsingStarting( + ExecutionContext *execution_context) { + watch_type_specified = false; + watch_type = eWatchInvalid; + watch_size = 0; } - -const OptionDefinition* -OptionGroupWatchpoint::GetDefinitions () -{ - return g_option_table; +const OptionDefinition *OptionGroupWatchpoint::GetDefinitions() { + return g_option_table; } -uint32_t -OptionGroupWatchpoint::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t OptionGroupWatchpoint::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp index 8f136a5b1c5..0c1f21f230b 100644 --- a/lldb/source/Interpreter/OptionValue.cpp +++ b/lldb/source/Interpreter/OptionValue.cpp @@ -19,720 +19,606 @@ using namespace lldb; using namespace lldb_private; - //------------------------------------------------------------------------- // Get this value as a uint64_t value if it is encoded as a boolean, -// uint64_t or int64_t. Other types will cause "fail_value" to be +// uint64_t or int64_t. Other types will cause "fail_value" to be // returned //------------------------------------------------------------------------- -uint64_t -OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr) -{ - if (success_ptr) - *success_ptr = true; - switch (GetType()) - { - case OptionValue::eTypeBoolean: return static_cast(this)->GetCurrentValue(); - case OptionValue::eTypeSInt64: return static_cast(this)->GetCurrentValue(); - case OptionValue::eTypeUInt64: return static_cast(this)->GetCurrentValue(); - default: - break; - } - if (success_ptr) - *success_ptr = false; - return fail_value; -} - -Error -OptionValue::SetSubValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *name, - const char *value) -{ - Error error; - error.SetErrorStringWithFormat("SetSubValue is not supported"); - return error; -} - - -OptionValueBoolean * -OptionValue::GetAsBoolean () -{ - if (GetType () == OptionValue::eTypeBoolean) - return static_cast(this); - return nullptr; -} - -const OptionValueBoolean * -OptionValue::GetAsBoolean () const -{ - if (GetType () == OptionValue::eTypeBoolean) - return static_cast(this); - return nullptr; -} - -const OptionValueChar * -OptionValue::GetAsChar () const -{ - if (GetType () == OptionValue::eTypeChar) - return static_cast(this); - return nullptr; -} - -OptionValueChar * -OptionValue::GetAsChar () -{ - if (GetType () == OptionValue::eTypeChar) - return static_cast(this); - return nullptr; -} - -OptionValueFileSpec * -OptionValue::GetAsFileSpec () -{ - if (GetType () == OptionValue::eTypeFileSpec) - return static_cast(this); - return nullptr; - -} - -const OptionValueFileSpec * -OptionValue::GetAsFileSpec () const -{ - if (GetType () == OptionValue::eTypeFileSpec) - return static_cast(this); - return nullptr; - -} - -OptionValueFileSpecList * -OptionValue::GetAsFileSpecList () -{ - if (GetType () == OptionValue::eTypeFileSpecList) - return static_cast(this); - return nullptr; - -} - -const OptionValueFileSpecList * -OptionValue::GetAsFileSpecList () const -{ - if (GetType () == OptionValue::eTypeFileSpecList) - return static_cast(this); - return nullptr; - -} - -OptionValueArch * -OptionValue::GetAsArch () -{ - if (GetType () == OptionValue::eTypeArch) - return static_cast(this); - return nullptr; +uint64_t OptionValue::GetUInt64Value(uint64_t fail_value, bool *success_ptr) { + if (success_ptr) + *success_ptr = true; + switch (GetType()) { + case OptionValue::eTypeBoolean: + return static_cast(this)->GetCurrentValue(); + case OptionValue::eTypeSInt64: + return static_cast(this)->GetCurrentValue(); + case OptionValue::eTypeUInt64: + return static_cast(this)->GetCurrentValue(); + default: + break; + } + if (success_ptr) + *success_ptr = false; + return fail_value; +} + +Error OptionValue::SetSubValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, const char *name, + const char *value) { + Error error; + error.SetErrorStringWithFormat("SetSubValue is not supported"); + return error; +} + +OptionValueBoolean *OptionValue::GetAsBoolean() { + if (GetType() == OptionValue::eTypeBoolean) + return static_cast(this); + return nullptr; +} + +const OptionValueBoolean *OptionValue::GetAsBoolean() const { + if (GetType() == OptionValue::eTypeBoolean) + return static_cast(this); + return nullptr; +} + +const OptionValueChar *OptionValue::GetAsChar() const { + if (GetType() == OptionValue::eTypeChar) + return static_cast(this); + return nullptr; +} + +OptionValueChar *OptionValue::GetAsChar() { + if (GetType() == OptionValue::eTypeChar) + return static_cast(this); + return nullptr; +} + +OptionValueFileSpec *OptionValue::GetAsFileSpec() { + if (GetType() == OptionValue::eTypeFileSpec) + return static_cast(this); + return nullptr; } +const OptionValueFileSpec *OptionValue::GetAsFileSpec() const { + if (GetType() == OptionValue::eTypeFileSpec) + return static_cast(this); + return nullptr; +} -const OptionValueArch * -OptionValue::GetAsArch () const -{ - if (GetType () == OptionValue::eTypeArch) - return static_cast(this); - return nullptr; +OptionValueFileSpecList *OptionValue::GetAsFileSpecList() { + if (GetType() == OptionValue::eTypeFileSpecList) + return static_cast(this); + return nullptr; } -OptionValueArray * -OptionValue::GetAsArray () -{ - if (GetType () == OptionValue::eTypeArray) - return static_cast(this); - return nullptr; +const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const { + if (GetType() == OptionValue::eTypeFileSpecList) + return static_cast(this); + return nullptr; } +OptionValueArch *OptionValue::GetAsArch() { + if (GetType() == OptionValue::eTypeArch) + return static_cast(this); + return nullptr; +} -const OptionValueArray * -OptionValue::GetAsArray () const -{ - if (GetType () == OptionValue::eTypeArray) - return static_cast(this); - return nullptr; +const OptionValueArch *OptionValue::GetAsArch() const { + if (GetType() == OptionValue::eTypeArch) + return static_cast(this); + return nullptr; } -OptionValueArgs * -OptionValue::GetAsArgs () -{ - if (GetType () == OptionValue::eTypeArgs) - return static_cast(this); - return nullptr; +OptionValueArray *OptionValue::GetAsArray() { + if (GetType() == OptionValue::eTypeArray) + return static_cast(this); + return nullptr; } +const OptionValueArray *OptionValue::GetAsArray() const { + if (GetType() == OptionValue::eTypeArray) + return static_cast(this); + return nullptr; +} -const OptionValueArgs * -OptionValue::GetAsArgs () const -{ - if (GetType () == OptionValue::eTypeArgs) - return static_cast(this); - return nullptr; +OptionValueArgs *OptionValue::GetAsArgs() { + if (GetType() == OptionValue::eTypeArgs) + return static_cast(this); + return nullptr; } -OptionValueDictionary * -OptionValue::GetAsDictionary () -{ - if (GetType () == OptionValue::eTypeDictionary) - return static_cast(this); - return nullptr; +const OptionValueArgs *OptionValue::GetAsArgs() const { + if (GetType() == OptionValue::eTypeArgs) + return static_cast(this); + return nullptr; } -const OptionValueDictionary * -OptionValue::GetAsDictionary () const -{ - if (GetType () == OptionValue::eTypeDictionary) - return static_cast(this); - return nullptr; +OptionValueDictionary *OptionValue::GetAsDictionary() { + if (GetType() == OptionValue::eTypeDictionary) + return static_cast(this); + return nullptr; } -OptionValueEnumeration * -OptionValue::GetAsEnumeration () -{ - if (GetType () == OptionValue::eTypeEnum) - return static_cast(this); - return nullptr; +const OptionValueDictionary *OptionValue::GetAsDictionary() const { + if (GetType() == OptionValue::eTypeDictionary) + return static_cast(this); + return nullptr; } -const OptionValueEnumeration * -OptionValue::GetAsEnumeration () const -{ - if (GetType () == OptionValue::eTypeEnum) - return static_cast(this); - return nullptr; +OptionValueEnumeration *OptionValue::GetAsEnumeration() { + if (GetType() == OptionValue::eTypeEnum) + return static_cast(this); + return nullptr; } -OptionValueFormat * -OptionValue::GetAsFormat () -{ - if (GetType () == OptionValue::eTypeFormat) - return static_cast(this); - return nullptr; +const OptionValueEnumeration *OptionValue::GetAsEnumeration() const { + if (GetType() == OptionValue::eTypeEnum) + return static_cast(this); + return nullptr; } -const OptionValueFormat * -OptionValue::GetAsFormat () const -{ - if (GetType () == OptionValue::eTypeFormat) - return static_cast(this); - return nullptr; +OptionValueFormat *OptionValue::GetAsFormat() { + if (GetType() == OptionValue::eTypeFormat) + return static_cast(this); + return nullptr; } -OptionValueLanguage * -OptionValue::GetAsLanguage () -{ - if (GetType () == OptionValue::eTypeLanguage) - return static_cast(this); - return NULL; +const OptionValueFormat *OptionValue::GetAsFormat() const { + if (GetType() == OptionValue::eTypeFormat) + return static_cast(this); + return nullptr; } -const OptionValueLanguage * -OptionValue::GetAsLanguage () const -{ - if (GetType () == OptionValue::eTypeLanguage) - return static_cast(this); - return NULL; +OptionValueLanguage *OptionValue::GetAsLanguage() { + if (GetType() == OptionValue::eTypeLanguage) + return static_cast(this); + return NULL; } -OptionValueFormatEntity * -OptionValue::GetAsFormatEntity () -{ - if (GetType () == OptionValue::eTypeFormatEntity) - return static_cast(this); - return nullptr; +const OptionValueLanguage *OptionValue::GetAsLanguage() const { + if (GetType() == OptionValue::eTypeLanguage) + return static_cast(this); + return NULL; } -const OptionValueFormatEntity * -OptionValue::GetAsFormatEntity () const -{ - if (GetType () == OptionValue::eTypeFormatEntity) - return static_cast(this); - return nullptr; +OptionValueFormatEntity *OptionValue::GetAsFormatEntity() { + if (GetType() == OptionValue::eTypeFormatEntity) + return static_cast(this); + return nullptr; } -OptionValuePathMappings * -OptionValue::GetAsPathMappings () -{ - if (GetType () == OptionValue::eTypePathMap) - return static_cast(this); - return nullptr; +const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const { + if (GetType() == OptionValue::eTypeFormatEntity) + return static_cast(this); + return nullptr; } -const OptionValuePathMappings * -OptionValue::GetAsPathMappings () const -{ - if (GetType () == OptionValue::eTypePathMap) - return static_cast(this); - return nullptr; +OptionValuePathMappings *OptionValue::GetAsPathMappings() { + if (GetType() == OptionValue::eTypePathMap) + return static_cast(this); + return nullptr; } -OptionValueProperties * -OptionValue::GetAsProperties () -{ - if (GetType () == OptionValue::eTypeProperties) - return static_cast(this); - return nullptr; +const OptionValuePathMappings *OptionValue::GetAsPathMappings() const { + if (GetType() == OptionValue::eTypePathMap) + return static_cast(this); + return nullptr; } -const OptionValueProperties * -OptionValue::GetAsProperties () const -{ - if (GetType () == OptionValue::eTypeProperties) - return static_cast(this); - return nullptr; -} - -OptionValueRegex * -OptionValue::GetAsRegex () -{ - if (GetType () == OptionValue::eTypeRegex) - return static_cast(this); - return nullptr; -} - -const OptionValueRegex * -OptionValue::GetAsRegex () const -{ - if (GetType () == OptionValue::eTypeRegex) - return static_cast(this); - return nullptr; -} - -OptionValueSInt64 * -OptionValue::GetAsSInt64 () -{ - if (GetType () == OptionValue::eTypeSInt64) - return static_cast(this); - return nullptr; -} - -const OptionValueSInt64 * -OptionValue::GetAsSInt64 () const -{ - if (GetType () == OptionValue::eTypeSInt64) - return static_cast(this); - return nullptr; -} - -OptionValueString * -OptionValue::GetAsString () -{ - if (GetType () == OptionValue::eTypeString) - return static_cast(this); - return nullptr; -} - -const OptionValueString * -OptionValue::GetAsString () const -{ - if (GetType () == OptionValue::eTypeString) - return static_cast(this); - return nullptr; -} - -OptionValueUInt64 * -OptionValue::GetAsUInt64 () -{ - if (GetType () == OptionValue::eTypeUInt64) - return static_cast(this); - return nullptr; -} - -const OptionValueUInt64 * -OptionValue::GetAsUInt64 () const -{ - if (GetType () == OptionValue::eTypeUInt64) - return static_cast(this); - return nullptr; -} - -OptionValueUUID * -OptionValue::GetAsUUID () -{ - if (GetType () == OptionValue::eTypeUUID) - return static_cast(this); - return nullptr; - -} - -const OptionValueUUID * -OptionValue::GetAsUUID () const -{ - if (GetType () == OptionValue::eTypeUUID) - return static_cast(this); - return nullptr; - -} - -bool -OptionValue::GetBooleanValue (bool fail_value) const -{ - const OptionValueBoolean *option_value = GetAsBoolean (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetBooleanValue (bool new_value) -{ - OptionValueBoolean *option_value = GetAsBoolean (); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; -} - -char -OptionValue::GetCharValue(char fail_value) const -{ - const OptionValueChar *option_value = GetAsChar(); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -char -OptionValue::SetCharValue(char new_value) -{ - OptionValueChar *option_value = GetAsChar(); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; -} - -int64_t -OptionValue::GetEnumerationValue (int64_t fail_value) const -{ - const OptionValueEnumeration *option_value = GetAsEnumeration(); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetEnumerationValue (int64_t value) -{ - OptionValueEnumeration *option_value = GetAsEnumeration(); - if (option_value) - { - option_value->SetCurrentValue(value); - return true; - } - return false; -} - -FileSpec -OptionValue::GetFileSpecValue () const -{ - const OptionValueFileSpec *option_value = GetAsFileSpec (); - if (option_value) - return option_value->GetCurrentValue(); - return FileSpec(); -} - - -bool -OptionValue::SetFileSpecValue (const FileSpec &file_spec) -{ - OptionValueFileSpec *option_value = GetAsFileSpec (); - if (option_value) - { - option_value->SetCurrentValue(file_spec, false); - return true; - } - return false; -} - -FileSpecList -OptionValue::GetFileSpecListValue () const -{ - const OptionValueFileSpecList *option_value = GetAsFileSpecList (); - if (option_value) - return option_value->GetCurrentValue(); - return FileSpecList(); -} - - -lldb::Format -OptionValue::GetFormatValue (lldb::Format fail_value) const -{ - const OptionValueFormat *option_value = GetAsFormat (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetFormatValue (lldb::Format new_value) -{ - OptionValueFormat *option_value = GetAsFormat (); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; +OptionValueProperties *OptionValue::GetAsProperties() { + if (GetType() == OptionValue::eTypeProperties) + return static_cast(this); + return nullptr; +} + +const OptionValueProperties *OptionValue::GetAsProperties() const { + if (GetType() == OptionValue::eTypeProperties) + return static_cast(this); + return nullptr; +} + +OptionValueRegex *OptionValue::GetAsRegex() { + if (GetType() == OptionValue::eTypeRegex) + return static_cast(this); + return nullptr; +} + +const OptionValueRegex *OptionValue::GetAsRegex() const { + if (GetType() == OptionValue::eTypeRegex) + return static_cast(this); + return nullptr; +} + +OptionValueSInt64 *OptionValue::GetAsSInt64() { + if (GetType() == OptionValue::eTypeSInt64) + return static_cast(this); + return nullptr; +} + +const OptionValueSInt64 *OptionValue::GetAsSInt64() const { + if (GetType() == OptionValue::eTypeSInt64) + return static_cast(this); + return nullptr; +} + +OptionValueString *OptionValue::GetAsString() { + if (GetType() == OptionValue::eTypeString) + return static_cast(this); + return nullptr; +} + +const OptionValueString *OptionValue::GetAsString() const { + if (GetType() == OptionValue::eTypeString) + return static_cast(this); + return nullptr; +} + +OptionValueUInt64 *OptionValue::GetAsUInt64() { + if (GetType() == OptionValue::eTypeUInt64) + return static_cast(this); + return nullptr; +} + +const OptionValueUInt64 *OptionValue::GetAsUInt64() const { + if (GetType() == OptionValue::eTypeUInt64) + return static_cast(this); + return nullptr; +} + +OptionValueUUID *OptionValue::GetAsUUID() { + if (GetType() == OptionValue::eTypeUUID) + return static_cast(this); + return nullptr; +} + +const OptionValueUUID *OptionValue::GetAsUUID() const { + if (GetType() == OptionValue::eTypeUUID) + return static_cast(this); + return nullptr; +} + +bool OptionValue::GetBooleanValue(bool fail_value) const { + const OptionValueBoolean *option_value = GetAsBoolean(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetBooleanValue(bool new_value) { + OptionValueBoolean *option_value = GetAsBoolean(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + +char OptionValue::GetCharValue(char fail_value) const { + const OptionValueChar *option_value = GetAsChar(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +char OptionValue::SetCharValue(char new_value) { + OptionValueChar *option_value = GetAsChar(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + +int64_t OptionValue::GetEnumerationValue(int64_t fail_value) const { + const OptionValueEnumeration *option_value = GetAsEnumeration(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetEnumerationValue(int64_t value) { + OptionValueEnumeration *option_value = GetAsEnumeration(); + if (option_value) { + option_value->SetCurrentValue(value); + return true; + } + return false; +} + +FileSpec OptionValue::GetFileSpecValue() const { + const OptionValueFileSpec *option_value = GetAsFileSpec(); + if (option_value) + return option_value->GetCurrentValue(); + return FileSpec(); +} + +bool OptionValue::SetFileSpecValue(const FileSpec &file_spec) { + OptionValueFileSpec *option_value = GetAsFileSpec(); + if (option_value) { + option_value->SetCurrentValue(file_spec, false); + return true; + } + return false; +} + +FileSpecList OptionValue::GetFileSpecListValue() const { + const OptionValueFileSpecList *option_value = GetAsFileSpecList(); + if (option_value) + return option_value->GetCurrentValue(); + return FileSpecList(); +} + +lldb::Format OptionValue::GetFormatValue(lldb::Format fail_value) const { + const OptionValueFormat *option_value = GetAsFormat(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetFormatValue(lldb::Format new_value) { + OptionValueFormat *option_value = GetAsFormat(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; } lldb::LanguageType -OptionValue::GetLanguageValue (lldb::LanguageType fail_value) const -{ - const OptionValueLanguage *option_value = GetAsLanguage (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetLanguageValue (lldb::LanguageType new_language) -{ - OptionValueLanguage *option_value = GetAsLanguage (); - if (option_value) - { - option_value->SetCurrentValue(new_language); - return true; - } - return false; -} - -const FormatEntity::Entry * -OptionValue::GetFormatEntity () const -{ - const OptionValueFormatEntity *option_value = GetAsFormatEntity(); - if (option_value) - return &option_value->GetCurrentValue(); - return nullptr; -} - -const RegularExpression * -OptionValue::GetRegexValue () const -{ - const OptionValueRegex *option_value = GetAsRegex (); - if (option_value) - return option_value->GetCurrentValue(); - return nullptr; -} - - -int64_t -OptionValue::GetSInt64Value (int64_t fail_value) const -{ - const OptionValueSInt64 *option_value = GetAsSInt64 (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetSInt64Value (int64_t new_value) -{ - OptionValueSInt64 *option_value = GetAsSInt64 (); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; -} - -const char * -OptionValue::GetStringValue (const char *fail_value) const -{ - const OptionValueString *option_value = GetAsString (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetStringValue (const char *new_value) -{ - OptionValueString *option_value = GetAsString (); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; -} - -uint64_t -OptionValue::GetUInt64Value (uint64_t fail_value) const -{ - const OptionValueUInt64 *option_value = GetAsUInt64 (); - if (option_value) - return option_value->GetCurrentValue(); - return fail_value; -} - -bool -OptionValue::SetUInt64Value (uint64_t new_value) -{ - OptionValueUInt64 *option_value = GetAsUInt64 (); - if (option_value) - { - option_value->SetCurrentValue(new_value); - return true; - } - return false; -} - -UUID -OptionValue::GetUUIDValue () const -{ - const OptionValueUUID *option_value = GetAsUUID(); - if (option_value) - return option_value->GetCurrentValue(); - return UUID(); -} - -bool -OptionValue::SetUUIDValue (const UUID &uuid) -{ - OptionValueUUID *option_value = GetAsUUID(); - if (option_value) - { - option_value->SetCurrentValue(uuid); - return true; - } - return false; -} - -const char * -OptionValue::GetBuiltinTypeAsCString (Type t) -{ - switch (t) - { - case eTypeInvalid: return "invalid"; - case eTypeArch: return "arch"; - case eTypeArgs: return "arguments"; - case eTypeArray: return "array"; - case eTypeBoolean: return "boolean"; - case eTypeChar: - return "char"; - case eTypeDictionary: return "dictionary"; - case eTypeEnum: return "enum"; - case eTypeFileSpec: return "file"; - case eTypeFileSpecList: return "file-list"; - case eTypeFormat: return "format"; - case eTypeFormatEntity: return "format-string"; - case eTypeLanguage: return "language"; - case eTypePathMap: return "path-map"; - case eTypeProperties: return "properties"; - case eTypeRegex: return "regex"; - case eTypeSInt64: return "int"; - case eTypeString: return "string"; - case eTypeUInt64: return "unsigned"; - case eTypeUUID: return "uuid"; - } - return nullptr; -} - - -lldb::OptionValueSP -OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t type_mask, Error &error) -{ - // If only 1 bit is set in the type mask for a dictionary or array - // then we know how to decode a value from a cstring - lldb::OptionValueSP value_sp; - switch (type_mask) - { - case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break; - case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break; - case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break; - case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break; - case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; - case 1u << eTypeFormatEntity: value_sp.reset(new OptionValueFormatEntity(NULL)); break; - case 1u << eTypeLanguage: value_sp.reset(new OptionValueLanguage(eLanguageTypeUnknown)); break; - case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break; - case 1u << eTypeString: value_sp.reset(new OptionValueString()); break; - case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break; - case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break; - } - - if (value_sp) - error = value_sp->SetValueFromString (value_cstr, eVarSetOperationAssign); +OptionValue::GetLanguageValue(lldb::LanguageType fail_value) const { + const OptionValueLanguage *option_value = GetAsLanguage(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { + OptionValueLanguage *option_value = GetAsLanguage(); + if (option_value) { + option_value->SetCurrentValue(new_language); + return true; + } + return false; +} + +const FormatEntity::Entry *OptionValue::GetFormatEntity() const { + const OptionValueFormatEntity *option_value = GetAsFormatEntity(); + if (option_value) + return &option_value->GetCurrentValue(); + return nullptr; +} + +const RegularExpression *OptionValue::GetRegexValue() const { + const OptionValueRegex *option_value = GetAsRegex(); + if (option_value) + return option_value->GetCurrentValue(); + return nullptr; +} + +int64_t OptionValue::GetSInt64Value(int64_t fail_value) const { + const OptionValueSInt64 *option_value = GetAsSInt64(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetSInt64Value(int64_t new_value) { + OptionValueSInt64 *option_value = GetAsSInt64(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + +const char *OptionValue::GetStringValue(const char *fail_value) const { + const OptionValueString *option_value = GetAsString(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetStringValue(const char *new_value) { + OptionValueString *option_value = GetAsString(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + +uint64_t OptionValue::GetUInt64Value(uint64_t fail_value) const { + const OptionValueUInt64 *option_value = GetAsUInt64(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +bool OptionValue::SetUInt64Value(uint64_t new_value) { + OptionValueUInt64 *option_value = GetAsUInt64(); + if (option_value) { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + +UUID OptionValue::GetUUIDValue() const { + const OptionValueUUID *option_value = GetAsUUID(); + if (option_value) + return option_value->GetCurrentValue(); + return UUID(); +} + +bool OptionValue::SetUUIDValue(const UUID &uuid) { + OptionValueUUID *option_value = GetAsUUID(); + if (option_value) { + option_value->SetCurrentValue(uuid); + return true; + } + return false; +} + +const char *OptionValue::GetBuiltinTypeAsCString(Type t) { + switch (t) { + case eTypeInvalid: + return "invalid"; + case eTypeArch: + return "arch"; + case eTypeArgs: + return "arguments"; + case eTypeArray: + return "array"; + case eTypeBoolean: + return "boolean"; + case eTypeChar: + return "char"; + case eTypeDictionary: + return "dictionary"; + case eTypeEnum: + return "enum"; + case eTypeFileSpec: + return "file"; + case eTypeFileSpecList: + return "file-list"; + case eTypeFormat: + return "format"; + case eTypeFormatEntity: + return "format-string"; + case eTypeLanguage: + return "language"; + case eTypePathMap: + return "path-map"; + case eTypeProperties: + return "properties"; + case eTypeRegex: + return "regex"; + case eTypeSInt64: + return "int"; + case eTypeString: + return "string"; + case eTypeUInt64: + return "unsigned"; + case eTypeUUID: + return "uuid"; + } + return nullptr; +} + +lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask( + const char *value_cstr, uint32_t type_mask, Error &error) { + // If only 1 bit is set in the type mask for a dictionary or array + // then we know how to decode a value from a cstring + lldb::OptionValueSP value_sp; + switch (type_mask) { + case 1u << eTypeArch: + value_sp.reset(new OptionValueArch()); + break; + case 1u << eTypeBoolean: + value_sp.reset(new OptionValueBoolean(false)); + break; + case 1u << eTypeChar: + value_sp.reset(new OptionValueChar('\0')); + break; + case 1u << eTypeFileSpec: + value_sp.reset(new OptionValueFileSpec()); + break; + case 1u << eTypeFormat: + value_sp.reset(new OptionValueFormat(eFormatInvalid)); + break; + case 1u << eTypeFormatEntity: + value_sp.reset(new OptionValueFormatEntity(NULL)); + break; + case 1u << eTypeLanguage: + value_sp.reset(new OptionValueLanguage(eLanguageTypeUnknown)); + break; + case 1u << eTypeSInt64: + value_sp.reset(new OptionValueSInt64()); + break; + case 1u << eTypeString: + value_sp.reset(new OptionValueString()); + break; + case 1u << eTypeUInt64: + value_sp.reset(new OptionValueUInt64()); + break; + case 1u << eTypeUUID: + value_sp.reset(new OptionValueUUID()); + break; + } + + if (value_sp) + error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign); + else + error.SetErrorString("unsupported type mask"); + return value_sp; +} + +bool OptionValue::DumpQualifiedName(Stream &strm) const { + bool dumped_something = false; + lldb::OptionValueSP m_parent_sp(m_parent_wp.lock()); + if (m_parent_sp) { + if (m_parent_sp->DumpQualifiedName(strm)) + dumped_something = true; + } + ConstString name(GetName()); + if (name) { + if (dumped_something) + strm.PutChar('.'); else - error.SetErrorString("unsupported type mask"); - return value_sp; -} - -bool -OptionValue::DumpQualifiedName (Stream &strm) const -{ - bool dumped_something = false; - lldb::OptionValueSP m_parent_sp(m_parent_wp.lock()); - if (m_parent_sp) - { - if (m_parent_sp->DumpQualifiedName(strm)) - dumped_something = true; - } - ConstString name (GetName()); - if (name) - { - if (dumped_something) - strm.PutChar('.'); - else - dumped_something = true; - strm << name; - } - return dumped_something; -} - -size_t -OptionValue::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - return matches.GetSize(); -} - -Error -OptionValue::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationReplace: - error.SetErrorStringWithFormat ("%s objects do not support the 'replace' operation", GetTypeAsCString()); - break; - case eVarSetOperationInsertBefore: - error.SetErrorStringWithFormat ("%s objects do not support the 'insert-before' operation", GetTypeAsCString()); - break; - case eVarSetOperationInsertAfter: - error.SetErrorStringWithFormat ("%s objects do not support the 'insert-after' operation", GetTypeAsCString()); - break; - case eVarSetOperationRemove: - error.SetErrorStringWithFormat ("%s objects do not support the 'remove' operation", GetTypeAsCString()); - break; - case eVarSetOperationAppend: - error.SetErrorStringWithFormat ("%s objects do not support the 'append' operation", GetTypeAsCString()); - break; - case eVarSetOperationClear: - error.SetErrorStringWithFormat ("%s objects do not support the 'clear' operation", GetTypeAsCString()); - break; - case eVarSetOperationAssign: - error.SetErrorStringWithFormat ("%s objects do not support the 'assign' operation", GetTypeAsCString()); - break; - case eVarSetOperationInvalid: - error.SetErrorStringWithFormat ("invalid operation performed on a %s object", GetTypeAsCString()); - break; - } - return error; + dumped_something = true; + strm << name; + } + return dumped_something; +} + +size_t OptionValue::AutoComplete(CommandInterpreter &interpreter, const char *s, + int match_start_point, int max_return_elements, + bool &word_complete, StringList &matches) { + word_complete = false; + matches.Clear(); + return matches.GetSize(); +} + +Error OptionValue::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationReplace: + error.SetErrorStringWithFormat( + "%s objects do not support the 'replace' operation", + GetTypeAsCString()); + break; + case eVarSetOperationInsertBefore: + error.SetErrorStringWithFormat( + "%s objects do not support the 'insert-before' operation", + GetTypeAsCString()); + break; + case eVarSetOperationInsertAfter: + error.SetErrorStringWithFormat( + "%s objects do not support the 'insert-after' operation", + GetTypeAsCString()); + break; + case eVarSetOperationRemove: + error.SetErrorStringWithFormat( + "%s objects do not support the 'remove' operation", GetTypeAsCString()); + break; + case eVarSetOperationAppend: + error.SetErrorStringWithFormat( + "%s objects do not support the 'append' operation", GetTypeAsCString()); + break; + case eVarSetOperationClear: + error.SetErrorStringWithFormat( + "%s objects do not support the 'clear' operation", GetTypeAsCString()); + break; + case eVarSetOperationAssign: + error.SetErrorStringWithFormat( + "%s objects do not support the 'assign' operation", GetTypeAsCString()); + break; + case eVarSetOperationInvalid: + error.SetErrorStringWithFormat("invalid operation performed on a %s object", + GetTypeAsCString()); + break; + } + return error; } - diff --git a/lldb/source/Interpreter/OptionValueArch.cpp b/lldb/source/Interpreter/OptionValueArch.cpp index 06973f8b644..81d458ffe01 100644 --- a/lldb/source/Interpreter/OptionValueArch.cpp +++ b/lldb/source/Interpreter/OptionValueArch.cpp @@ -22,88 +22,65 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueArch::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueArch::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); + strm.PutCString(" = "); - if (m_current_value.IsValid()) - { - const char *arch_name = m_current_value.GetArchitectureName(); - if (arch_name) - strm.PutCString (arch_name); - } + if (m_current_value.IsValid()) { + const char *arch_name = m_current_value.GetArchitectureName(); + if (arch_name) + strm.PutCString(arch_name); } + } } -Error -OptionValueArch::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - std::string value_str = value.trim().str(); - if (m_current_value.SetTriple (value_str.c_str())) - { - m_value_was_set = true; - NotifyValueChanged(); - } - else - error.SetErrorStringWithFormat("unsupported architecture '%s'", value_str.c_str()); - break; - } - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); - break; - } - return error; -} +Error OptionValueArch::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; -lldb::OptionValueSP -OptionValueArch::DeepCopy () const -{ - return OptionValueSP(new OptionValueArch(*this)); + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + std::string value_str = value.trim().str(); + if (m_current_value.SetTriple(value_str.c_str())) { + m_value_was_set = true; + NotifyValueChanged(); + } else + error.SetErrorStringWithFormat("unsupported architecture '%s'", + value_str.c_str()); + break; + } + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } - -size_t -OptionValueArch::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, - CommandCompletions::eArchitectureCompletion, - s, - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); +lldb::OptionValueSP OptionValueArch::DeepCopy() const { + return OptionValueSP(new OptionValueArch(*this)); } - - - +size_t OptionValueArch::AutoComplete(CommandInterpreter &interpreter, + const char *s, int match_start_point, + int max_return_elements, + bool &word_complete, StringList &matches) { + word_complete = false; + matches.Clear(); + CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, CommandCompletions::eArchitectureCompletion, s, + match_start_point, max_return_elements, nullptr, word_complete, matches); + return matches.GetSize(); +} diff --git a/lldb/source/Interpreter/OptionValueArgs.cpp b/lldb/source/Interpreter/OptionValueArgs.cpp index e28d884581f..2cc93ab3502 100644 --- a/lldb/source/Interpreter/OptionValueArgs.cpp +++ b/lldb/source/Interpreter/OptionValueArgs.cpp @@ -18,21 +18,18 @@ using namespace lldb; using namespace lldb_private; -size_t -OptionValueArgs::GetArgs (Args &args) -{ - const uint32_t size = m_values.size(); - std::vector argv; - for (uint32_t i = 0; iGetStringValue (); - if (string_value) - argv.push_back(string_value); - } +size_t OptionValueArgs::GetArgs(Args &args) { + const uint32_t size = m_values.size(); + std::vector argv; + for (uint32_t i = 0; i < size; ++i) { + const char *string_value = m_values[i]->GetStringValue(); + if (string_value) + argv.push_back(string_value); + } - if (argv.empty()) - args.Clear(); - else - args.SetArguments(argv.size(), &argv[0]); - return args.GetArgumentCount(); + if (argv.empty()) + args.Clear(); + else + args.SetArguments(argv.size(), &argv[0]); + return args.GetArgumentCount(); } diff --git a/lldb/source/Interpreter/OptionValueArray.cpp b/lldb/source/Interpreter/OptionValueArray.cpp index 348414f432c..9d3c1989bc7 100644 --- a/lldb/source/Interpreter/OptionValueArray.cpp +++ b/lldb/source/Interpreter/OptionValueArray.cpp @@ -20,340 +20,294 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ - const Type array_element_type = ConvertTypeMaskToType (m_type_mask); +void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + const Type array_element_type = ConvertTypeMaskToType(m_type_mask); + if (dump_mask & eDumpOptionType) { + if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid)) + strm.Printf("(%s of %ss)", GetTypeAsCString(), + GetBuiltinTypeAsCString(array_element_type)); + else + strm.Printf("(%s)", GetTypeAsCString()); + } + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - { - if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid)) - strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type)); - else - strm.Printf ("(%s)", GetTypeAsCString()); - } - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : ""); - strm.IndentMore(); - const uint32_t size = m_values.size(); - for (uint32_t i = 0; iDumpValue(exe_ctx, strm, dump_mask | extra_dump_options); - break; - - case eTypeBoolean: - case eTypeChar: - case eTypeEnum: - case eTypeFileSpec: - case eTypeFormat: - case eTypeSInt64: - case eTypeString: - case eTypeUInt64: - case eTypeUUID: - // No need to show the type for dictionaries of simple items - m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); - break; - } - if (i < (size - 1)) - strm.EOL(); - } - strm.IndentLess(); + strm.Printf(" =%s", (m_values.size() > 0) ? "\n" : ""); + strm.IndentMore(); + const uint32_t size = m_values.size(); + for (uint32_t i = 0; i < size; ++i) { + strm.Indent(); + strm.Printf("[%u]: ", i); + const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; + switch (array_element_type) { + default: + case eTypeArray: + case eTypeDictionary: + case eTypeProperties: + case eTypeFileSpecList: + case eTypePathMap: + m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); + break; + + case eTypeBoolean: + case eTypeChar: + case eTypeEnum: + case eTypeFileSpec: + case eTypeFormat: + case eTypeSInt64: + case eTypeString: + case eTypeUInt64: + case eTypeUUID: + // No need to show the type for dictionaries of simple items + m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | + extra_dump_options); + break; + } + if (i < (size - 1)) + strm.EOL(); } + strm.IndentLess(); + } } -Error -OptionValueArray::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Args args(value.str().c_str()); - Error error = SetArgs (args, op); - if (error.Success()) - NotifyValueChanged(); - return error; +Error OptionValueArray::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Args args(value.str().c_str()); + Error error = SetArgs(args, op); + if (error.Success()) + NotifyValueChanged(); + return error; } - lldb::OptionValueSP -OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx, - const char *name, - bool will_modify, - Error &error) const -{ - if (name && name[0] == '[') - { - const char *end_bracket = strchr (name+1, ']'); - if (end_bracket) - { - const char *sub_value = nullptr; - if (end_bracket[1]) - sub_value = end_bracket + 1; - std::string index_str (name+1, end_bracket); - const size_t array_count = m_values.size(); - int32_t idx = StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr); - if (idx != INT32_MAX) - { - ; - uint32_t new_idx = UINT32_MAX; - if (idx < 0) - { - // Access from the end of the array if the index is negative - new_idx = array_count - idx; - } - else - { - // Just a standard index - new_idx = idx; - } +OptionValueArray::GetSubValue(const ExecutionContext *exe_ctx, const char *name, + bool will_modify, Error &error) const { + if (name && name[0] == '[') { + const char *end_bracket = strchr(name + 1, ']'); + if (end_bracket) { + const char *sub_value = nullptr; + if (end_bracket[1]) + sub_value = end_bracket + 1; + std::string index_str(name + 1, end_bracket); + const size_t array_count = m_values.size(); + int32_t idx = + StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr); + if (idx != INT32_MAX) { + ; + uint32_t new_idx = UINT32_MAX; + if (idx < 0) { + // Access from the end of the array if the index is negative + new_idx = array_count - idx; + } else { + // Just a standard index + new_idx = idx; + } - if (new_idx < array_count) - { - if (m_values[new_idx]) - { - if (sub_value) - return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error); - else - return m_values[new_idx]; - } - } - else - { - if (array_count == 0) - error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx); - else if (idx > 0) - error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %" PRIu64, idx, (uint64_t)(array_count - 1)); - else - error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%" PRIu64, idx, (uint64_t)array_count); - } - } + if (new_idx < array_count) { + if (m_values[new_idx]) { + if (sub_value) + return m_values[new_idx]->GetSubValue(exe_ctx, sub_value, + will_modify, error); + else + return m_values[new_idx]; + } + } else { + if (array_count == 0) + error.SetErrorStringWithFormat( + "index %i is not valid for an empty array", idx); + else if (idx > 0) + error.SetErrorStringWithFormat( + "index %i out of range, valid values are 0 through %" PRIu64, + idx, (uint64_t)(array_count - 1)); + else + error.SetErrorStringWithFormat("negative index %i out of range, " + "valid values are -1 through " + "-%" PRIu64, + idx, (uint64_t)array_count); } + } } - else - { - error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[]' subvalues where is a positive or negative array index", name, GetTypeAsCString()); - } - return OptionValueSP(); + } else { + error.SetErrorStringWithFormat( + "invalid value path '%s', %s values only support '[]' subvalues " + "where is a positive or negative array index", + name, GetTypeAsCString()); + } + return OptionValueSP(); } +size_t OptionValueArray::GetArgs(Args &args) const { + const uint32_t size = m_values.size(); + std::vector argv; + for (uint32_t i = 0; i < size; ++i) { + const char *string_value = m_values[i]->GetStringValue(); + if (string_value) + argv.push_back(string_value); + } -size_t -OptionValueArray::GetArgs (Args &args) const -{ - const uint32_t size = m_values.size(); - std::vector argv; - for (uint32_t i = 0; iGetStringValue (); - if (string_value) - argv.push_back(string_value); - } - - if (argv.empty()) - args.Clear(); - else - args.SetArguments(argv.size(), &argv[0]); - return args.GetArgumentCount(); + if (argv.empty()) + args.Clear(); + else + args.SetArguments(argv.size(), &argv[0]); + return args.GetArgumentCount(); } -Error -OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) -{ - Error error; - const size_t argc = args.GetArgumentCount(); - switch (op) - { - case eVarSetOperationInvalid: - error.SetErrorString("unsupported operation"); - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - if (argc > 1) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count); - } - else - { - if (op == eVarSetOperationInsertAfter) - ++idx; - for (size_t i=1; i= m_values.size()) - m_values.push_back(value_sp); - else - m_values.insert(m_values.begin() + idx, value_sp); - } - else - { - error.SetErrorString("array of complex types must subclass OptionValueArray"); - return error; - } - } - } - } - else - { - error.SetErrorString("insert operation takes an array index followed by one or more values"); - } - break; - - case eVarSetOperationRemove: - if (argc > 0) - { - const uint32_t size = m_values.size(); - std::vector remove_indexes; - bool all_indexes_valid = true; - size_t i; - for (i=0; i= size) - { - all_indexes_valid = false; - break; - } - else - remove_indexes.push_back(idx); - } - - if (all_indexes_valid) - { - size_t num_remove_indexes = remove_indexes.size(); - if (num_remove_indexes) - { - // Sort and then erase in reverse so indexes are always valid - if (num_remove_indexes > 1) - { - std::sort(remove_indexes.begin(), remove_indexes.end()); - for (std::vector::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos) - { - m_values.erase(m_values.begin() + *pos); - } - } - else - { - // Only one index - m_values.erase(m_values.begin() + remove_indexes.front()); - } - } - } +Error OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) { + Error error; + const size_t argc = args.GetArgumentCount(); + switch (op) { + case eVarSetOperationInvalid: + error.SetErrorString("unsupported operation"); + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + if (argc > 1) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid insert array index %u, index must be 0 through %u", idx, + count); + } else { + if (op == eVarSetOperationInsertAfter) + ++idx; + for (size_t i = 1; i < argc; ++i, ++idx) { + lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( + args.GetArgumentAtIndex(i), m_type_mask, error)); + if (value_sp) { + if (error.Fail()) + return error; + if (idx >= m_values.size()) + m_values.push_back(value_sp); else - { - error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i)); - } - } - else - { - error.SetErrorString("remove operation takes one or more array indices"); + m_values.insert(m_values.begin() + idx, value_sp); + } else { + error.SetErrorString( + "array of complex types must subclass OptionValueArray"); + return error; + } } - break; - - case eVarSetOperationClear: - Clear (); - break; - - case eVarSetOperationReplace: - if (argc > 1) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count); - } - else - { - for (size_t i=1; i 0) { + const uint32_t size = m_values.size(); + std::vector remove_indexes; + bool all_indexes_valid = true; + size_t i; + for (i = 0; i < argc; ++i) { + const size_t idx = + StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); + if (idx >= size) { + all_indexes_valid = false; + break; + } else + remove_indexes.push_back(idx); + } + + if (all_indexes_valid) { + size_t num_remove_indexes = remove_indexes.size(); + if (num_remove_indexes) { + // Sort and then erase in reverse so indexes are always valid + if (num_remove_indexes > 1) { + std::sort(remove_indexes.begin(), remove_indexes.end()); + for (std::vector::const_reverse_iterator + pos = remove_indexes.rbegin(), + end = remove_indexes.rend(); + pos != end; ++pos) { + m_values.erase(m_values.begin() + *pos); } + } else { + // Only one index + m_values.erase(m_values.begin() + remove_indexes.front()); + } } - else - { - error.SetErrorString("replace operation takes an array index followed by one or more values"); - } - break; - - case eVarSetOperationAssign: - m_values.clear(); - // Fall through to append case - LLVM_FALLTHROUGH; - case eVarSetOperationAppend: - for (size_t i=0; i 1) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid replace array index %u, index must be 0 through %u", idx, + count); + } else { + for (size_t i = 1; i < argc; ++i, ++idx) { + lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( + args.GetArgumentAtIndex(i), m_type_mask, error)); + if (value_sp) { + if (error.Fail()) + return error; + if (idx < count) + m_values[idx] = value_sp; else - { - error.SetErrorString("array of complex types must subclass OptionValueArray"); - } + m_values.push_back(value_sp); + } else { + error.SetErrorString( + "array of complex types must subclass OptionValueArray"); + return error; + } } - break; + } + } else { + error.SetErrorString("replace operation takes an array index followed by " + "one or more values"); } - return error; -} + break; -lldb::OptionValueSP -OptionValueArray::DeepCopy () const -{ - OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump); - lldb::OptionValueSP copied_value_sp(copied_array); - *static_cast(copied_array) = *this; - copied_array->m_callback = m_callback; - const uint32_t size = m_values.size(); - for (uint32_t i = 0; iAppendValue (m_values[i]->DeepCopy()); + case eVarSetOperationAssign: + m_values.clear(); + // Fall through to append case + LLVM_FALLTHROUGH; + case eVarSetOperationAppend: + for (size_t i = 0; i < argc; ++i) { + lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( + args.GetArgumentAtIndex(i), m_type_mask, error)); + if (value_sp) { + if (error.Fail()) + return error; + m_value_was_set = true; + AppendValue(value_sp); + } else { + error.SetErrorString( + "array of complex types must subclass OptionValueArray"); + } } - return copied_value_sp; + break; + } + return error; } - - +lldb::OptionValueSP OptionValueArray::DeepCopy() const { + OptionValueArray *copied_array = + new OptionValueArray(m_type_mask, m_raw_value_dump); + lldb::OptionValueSP copied_value_sp(copied_array); + *static_cast(copied_array) = *this; + copied_array->m_callback = m_callback; + const uint32_t size = m_values.size(); + for (uint32_t i = 0; i < size; ++i) { + copied_array->AppendValue(m_values[i]->DeepCopy()); + } + return copied_value_sp; +} diff --git a/lldb/source/Interpreter/OptionValueBoolean.cpp b/lldb/source/Interpreter/OptionValueBoolean.cpp index 4ba03d250ac..dbbd46ea093 100644 --- a/lldb/source/Interpreter/OptionValueBoolean.cpp +++ b/lldb/source/Interpreter/OptionValueBoolean.cpp @@ -1,4 +1,5 @@ -//===-- OptionValueBoolean.cpp ------------------------------------*- C++ -*-===// +//===-- OptionValueBoolean.cpp ------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -22,117 +23,90 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueBoolean::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueBoolean::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + // if (dump_mask & eDumpOptionName) + // DumpQualifiedName (strm); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); -// if (dump_mask & eDumpOptionName) -// DumpQualifiedName (strm); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - strm.PutCString (m_current_value ? "true" : "false"); - } + strm.PutCString(" = "); + strm.PutCString(m_current_value ? "true" : "false"); + } } -Error -OptionValueBoolean::SetValueFromString (llvm::StringRef value_str, - VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - bool success = false; - bool value = Args::StringToBoolean(value_str.str().c_str(), false, &success); - if (success) - { - m_value_was_set = true; - m_current_value = value; - NotifyValueChanged(); - } - else - { - if (value_str.size() == 0) - error.SetErrorString ("invalid boolean string value "); - else - error.SetErrorStringWithFormat ("invalid boolean string value: '%s'", - value_str.str().c_str()); - } - } - break; +Error OptionValueBoolean::SetValueFromString(llvm::StringRef value_str, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value_str, op); - break; + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + bool success = false; + bool value = + Args::StringToBoolean(value_str.str().c_str(), false, &success); + if (success) { + m_value_was_set = true; + m_current_value = value; + NotifyValueChanged(); + } else { + if (value_str.size() == 0) + error.SetErrorString("invalid boolean string value "); + else + error.SetErrorStringWithFormat("invalid boolean string value: '%s'", + value_str.str().c_str()); } - return error; -} + } break; -lldb::OptionValueSP -OptionValueBoolean::DeepCopy () const -{ - return OptionValueSP(new OptionValueBoolean(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value_str, op); + break; + } + return error; } -size_t -OptionValueBoolean::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - struct StringEntry { - const char *string; - const size_t length; - }; - static const StringEntry g_autocomplete_entries[] = - { - { "true" , 4 }, - { "false", 5 }, - { "on" , 2 }, - { "off" , 3 }, - { "yes" , 3 }, - { "no" , 2 }, - { "1" , 1 }, - { "0" , 1 }, - }; - const size_t k_num_autocomplete_entries = llvm::array_lengthof(g_autocomplete_entries); - - if (s && s[0]) - { - const size_t s_len = strlen(s); - for (size_t i=0; isecond.get(); - strm.EOL(); - strm.Indent(pos->first.GetCString()); - - const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; - switch (dict_type) - { - default: - case eTypeArray: - case eTypeDictionary: - case eTypeProperties: - case eTypeFileSpecList: - case eTypePathMap: - strm.PutChar (' '); - option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); - break; + strm.IndentMore(); - case eTypeBoolean: - case eTypeChar: - case eTypeEnum: - case eTypeFileSpec: - case eTypeFormat: - case eTypeSInt64: - case eTypeString: - case eTypeUInt64: - case eTypeUUID: - // No need to show the type for dictionaries of simple items - strm.PutCString("="); - option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); - break; - } - } - strm.IndentLess(); - } + for (pos = m_values.begin(); pos != end; ++pos) { + OptionValue *option_value = pos->second.get(); + strm.EOL(); + strm.Indent(pos->first.GetCString()); -} + const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; + switch (dict_type) { + default: + case eTypeArray: + case eTypeDictionary: + case eTypeProperties: + case eTypeFileSpecList: + case eTypePathMap: + strm.PutChar(' '); + option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); + break; -size_t -OptionValueDictionary::GetArgs (Args &args) const -{ - args.Clear(); - collection::const_iterator pos, end = m_values.end(); - for (pos = m_values.begin(); pos != end; ++pos) - { - StreamString strm; - strm.Printf("%s=", pos->first.GetCString()); - pos->second->DumpValue(nullptr, strm, eDumpOptionValue|eDumpOptionRaw); - args.AppendArgument(strm.GetString().c_str()); + case eTypeBoolean: + case eTypeChar: + case eTypeEnum: + case eTypeFileSpec: + case eTypeFormat: + case eTypeSInt64: + case eTypeString: + case eTypeUInt64: + case eTypeUUID: + // No need to show the type for dictionaries of simple items + strm.PutCString("="); + option_value->DumpValue(exe_ctx, strm, + (dump_mask & (~eDumpOptionType)) | + extra_dump_options); + break; + } } - return args.GetArgumentCount(); + strm.IndentLess(); + } } -Error -OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op) -{ - Error error; - const size_t argc = args.GetArgumentCount(); - switch (op) - { - case eVarSetOperationClear: - Clear(); - break; - - case eVarSetOperationAppend: - case eVarSetOperationReplace: - case eVarSetOperationAssign: - if (argc > 0) - { - for (size_t i=0; i'] - // [""] - if ((key.size() > 2) && (key.back() == ']')) - { - // Strip leading '[' and trailing ']' - key = key.substr(1, key.size()-2); - const char quote_char = key.front(); - if ((quote_char == '\'') || (quote_char == '"')) - { - if ((key.size() > 2) && (key.back() == quote_char)) - { - // Strip the quotes - key = key.substr(1, key.size()-2); - key_valid = true; - } - } - else - { - // square brackets, no quotes - key_valid = true; - } - } - } - else - { - // No square brackets or quotes - key_valid = true; - } - } - if (!key_valid) - { - error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [] or [''] or [\"\"]", kvp.first.str().c_str()); - return error; - } +Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) { + Error error; + const size_t argc = args.GetArgumentCount(); + switch (op) { + case eVarSetOperationClear: + Clear(); + break; - lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(), - m_type_mask, - error)); - if (value_sp) - { - if (error.Fail()) - return error; - m_value_was_set = true; - SetValueForKey (ConstString(key), value_sp, true); - } - else - { - error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray"); - } - } - else - { - error.SetErrorString("empty argument"); - } - } - } - else - { - error.SetErrorString("assign operation takes one or more key=value arguments"); - } - break; - - case eVarSetOperationRemove: - if (argc > 0) - { - for (size_t i=0; i 0) { + for (size_t i = 0; i < argc; ++i) { + llvm::StringRef key_and_value(args.GetArgumentAtIndex(i)); + if (!key_and_value.empty()) { + if (key_and_value.find('=') == llvm::StringRef::npos) { + error.SetErrorString( + "assign operation takes one or more key=value arguments"); + return error; + } + + std::pair kvp( + key_and_value.split('=')); + llvm::StringRef key = kvp.first; + bool key_valid = false; + if (!key.empty()) { + if (key.front() == '[') { + // Key name starts with '[', so the key value must be in single or + // double quotes like: + // [''] + // [""] + if ((key.size() > 2) && (key.back() == ']')) { + // Strip leading '[' and trailing ']' + key = key.substr(1, key.size() - 2); + const char quote_char = key.front(); + if ((quote_char == '\'') || (quote_char == '"')) { + if ((key.size() > 2) && (key.back() == quote_char)) { + // Strip the quotes + key = key.substr(1, key.size() - 2); + key_valid = true; + } + } else { + // square brackets, no quotes + key_valid = true; } + } + } else { + // No square brackets or quotes + key_valid = true; } + } + if (!key_valid) { + error.SetErrorStringWithFormat( + "invalid key \"%s\", the key must be a bare string or " + "surrounded by brackets with optional quotes: [] or " + "[''] or [\"\"]", + kvp.first.str().c_str()); + return error; + } + + lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( + kvp.second.data(), m_type_mask, error)); + if (value_sp) { + if (error.Fail()) + return error; + m_value_was_set = true; + SetValueForKey(ConstString(key), value_sp, true); + } else { + error.SetErrorString("dictionaries that can contain multiple types " + "must subclass OptionValueArray"); + } + } else { + error.SetErrorString("empty argument"); } - else - { - error.SetErrorString("remove operation takes one or more key arguments"); + } + } else { + error.SetErrorString( + "assign operation takes one or more key=value arguments"); + } + break; + + case eVarSetOperationRemove: + if (argc > 0) { + for (size_t i = 0; i < argc; ++i) { + ConstString key(args.GetArgumentAtIndex(i)); + if (!DeleteValueForKey(key)) { + error.SetErrorStringWithFormat( + "no value found named '%s', aborting remove operation", + key.GetCString()); + break; } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (llvm::StringRef(), op); - break; + } + } else { + error.SetErrorString("remove operation takes one or more key arguments"); } - return error; + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(llvm::StringRef(), op); + break; + } + return error; } -Error -OptionValueDictionary::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Args args(value.str().c_str()); - Error error = SetArgs (args, op); - if (error.Success()) - NotifyValueChanged(); - return error; +Error OptionValueDictionary::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Args args(value.str().c_str()); + Error error = SetArgs(args, op); + if (error.Success()) + NotifyValueChanged(); + return error; } lldb::OptionValueSP -OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char *name, bool will_modify, Error &error) const -{ - lldb::OptionValueSP value_sp; +OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx, + const char *name, bool will_modify, + Error &error) const { + lldb::OptionValueSP value_sp; - if (name && name[0]) - { - const char *sub_name = nullptr; - ConstString key; - const char *open_bracket = ::strchr (name, '['); + if (name && name[0]) { + const char *sub_name = nullptr; + ConstString key; + const char *open_bracket = ::strchr(name, '['); - if (open_bracket) - { - const char *key_start = open_bracket + 1; - const char *key_end = nullptr; - switch (open_bracket[1]) - { - case '\'': - ++key_start; - key_end = strchr(key_start, '\''); - if (key_end) - { - if (key_end[1] == ']') - { - if (key_end[2]) - sub_name = key_end + 2; - } - else - { - error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as [''] where is a string that doesn't contain quotes", name); - return value_sp; - } - } - else - { - error.SetErrorString ("missing '] key name terminator, key name started with ['"); - return value_sp; - } - break; - case '"': - ++key_start; - key_end = strchr(key_start, '"'); - if (key_end) - { - if (key_end[1] == ']') - { - if (key_end[2]) - sub_name = key_end + 2; - break; - } - error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"\"] where is a string that doesn't contain quotes", name); - return value_sp; - } - else - { - error.SetErrorString ("missing \"] key name terminator, key name started with [\""); - return value_sp; - } - break; + if (open_bracket) { + const char *key_start = open_bracket + 1; + const char *key_end = nullptr; + switch (open_bracket[1]) { + case '\'': + ++key_start; + key_end = strchr(key_start, '\''); + if (key_end) { + if (key_end[1] == ']') { + if (key_end[2]) + sub_name = key_end + 2; + } else { + error.SetErrorStringWithFormat("invalid value path '%s', single " + "quoted key names must be formatted " + "as [''] where is a " + "string that doesn't contain quotes", + name); + return value_sp; + } + } else { + error.SetErrorString( + "missing '] key name terminator, key name started with ['"); + return value_sp; + } + break; + case '"': + ++key_start; + key_end = strchr(key_start, '"'); + if (key_end) { + if (key_end[1] == ']') { + if (key_end[2]) + sub_name = key_end + 2; + break; + } + error.SetErrorStringWithFormat("invalid value path '%s', double " + "quoted key names must be formatted " + "as [\"\"] where is a " + "string that doesn't contain quotes", + name); + return value_sp; + } else { + error.SetErrorString( + "missing \"] key name terminator, key name started with [\""); + return value_sp; + } + break; - default: - key_end = strchr(key_start, ']'); - if (key_end) - { - if (key_end[1]) - sub_name = key_end + 1; - } - else - { - error.SetErrorString ("missing ] key name terminator, key name started with ["); - return value_sp; - } - break; - } - - if (key_start && key_end) - { - key.SetCStringWithLength (key_start, key_end - key_start); - - value_sp = GetValueForKey (key); - if (value_sp) - { - if (sub_name) - return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error); - } - else - { - error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString()); - } - } + default: + key_end = strchr(key_start, ']'); + if (key_end) { + if (key_end[1]) + sub_name = key_end + 1; + } else { + error.SetErrorString( + "missing ] key name terminator, key name started with ["); + return value_sp; } - if (!value_sp && error.AsCString() == nullptr) - { - error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[]' subvalues where a string value optionally delimited by single or double quotes", - name, - GetTypeAsCString()); + break; + } + + if (key_start && key_end) { + key.SetCStringWithLength(key_start, key_end - key_start); + + value_sp = GetValueForKey(key); + if (value_sp) { + if (sub_name) + return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error); + } else { + error.SetErrorStringWithFormat( + "dictionary does not contain a value for the key name '%s'", + key.GetCString()); } + } } - return value_sp; -} - -Error -OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value) -{ - Error error; - const bool will_modify = true; - lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); - if (value_sp) - error = value_sp->SetValueFromString(value, op); - else - { - if (error.AsCString() == nullptr) - error.SetErrorStringWithFormat("invalid value path '%s'", name); + if (!value_sp && error.AsCString() == nullptr) { + error.SetErrorStringWithFormat("invalid value path '%s', %s values only " + "support '[]' subvalues where " + "a string value optionally delimited by " + "single or double quotes", + name, GetTypeAsCString()); } - return error; + } + return value_sp; } +Error OptionValueDictionary::SetSubValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *name, const char *value) { + Error error; + const bool will_modify = true; + lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error)); + if (value_sp) + error = value_sp->SetValueFromString(value, op); + else { + if (error.AsCString() == nullptr) + error.SetErrorStringWithFormat("invalid value path '%s'", name); + } + return error; +} lldb::OptionValueSP -OptionValueDictionary::GetValueForKey (const ConstString &key) const -{ - lldb::OptionValueSP value_sp; - collection::const_iterator pos = m_values.find (key); - if (pos != m_values.end()) - value_sp = pos->second; - return value_sp; +OptionValueDictionary::GetValueForKey(const ConstString &key) const { + lldb::OptionValueSP value_sp; + collection::const_iterator pos = m_values.find(key); + if (pos != m_values.end()) + value_sp = pos->second; + return value_sp; } const char * -OptionValueDictionary::GetStringValueForKey (const ConstString &key) -{ - collection::const_iterator pos = m_values.find (key); - if (pos != m_values.end()) - { - OptionValueString *string_value = pos->second->GetAsString(); - if (string_value) - return string_value->GetCurrentValue(); - } - return nullptr; +OptionValueDictionary::GetStringValueForKey(const ConstString &key) { + collection::const_iterator pos = m_values.find(key); + if (pos != m_values.end()) { + OptionValueString *string_value = pos->second->GetAsString(); + if (string_value) + return string_value->GetCurrentValue(); + } + return nullptr; } - -bool -OptionValueDictionary::SetStringValueForKey (const ConstString &key, - const char *value, - bool can_replace) -{ - collection::const_iterator pos = m_values.find (key); - if (pos != m_values.end()) - { - if (!can_replace) - return false; - if (pos->second->GetType() == OptionValue::eTypeString) - { - pos->second->SetValueFromString(value); - return true; - } +bool OptionValueDictionary::SetStringValueForKey(const ConstString &key, + const char *value, + bool can_replace) { + collection::const_iterator pos = m_values.find(key); + if (pos != m_values.end()) { + if (!can_replace) + return false; + if (pos->second->GetType() == OptionValue::eTypeString) { + pos->second->SetValueFromString(value); + return true; } - m_values[key] = OptionValueSP (new OptionValueString (value)); - return true; - + } + m_values[key] = OptionValueSP(new OptionValueString(value)); + return true; } -bool -OptionValueDictionary::SetValueForKey (const ConstString &key, - const lldb::OptionValueSP &value_sp, - bool can_replace) -{ - // Make sure the value_sp object is allowed to contain - // values of the type passed in... - if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) - { - if (!can_replace) - { - collection::const_iterator pos = m_values.find (key); - if (pos != m_values.end()) - return false; - } - m_values[key] = value_sp; - return true; +bool OptionValueDictionary::SetValueForKey(const ConstString &key, + const lldb::OptionValueSP &value_sp, + bool can_replace) { + // Make sure the value_sp object is allowed to contain + // values of the type passed in... + if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) { + if (!can_replace) { + collection::const_iterator pos = m_values.find(key); + if (pos != m_values.end()) + return false; } - return false; + m_values[key] = value_sp; + return true; + } + return false; } -bool -OptionValueDictionary::DeleteValueForKey (const ConstString &key) -{ - collection::iterator pos = m_values.find (key); - if (pos != m_values.end()) - { - m_values.erase(pos); - return true; - } - return false; +bool OptionValueDictionary::DeleteValueForKey(const ConstString &key) { + collection::iterator pos = m_values.find(key); + if (pos != m_values.end()) { + m_values.erase(pos); + return true; + } + return false; } -lldb::OptionValueSP -OptionValueDictionary::DeepCopy () const -{ - OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump); - lldb::OptionValueSP copied_value_sp(copied_dict); - collection::const_iterator pos, end = m_values.end(); - for (pos = m_values.begin(); pos != end; ++pos) - { - StreamString strm; - strm.Printf("%s=", pos->first.GetCString()); - copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true); - } - return copied_value_sp; +lldb::OptionValueSP OptionValueDictionary::DeepCopy() const { + OptionValueDictionary *copied_dict = + new OptionValueDictionary(m_type_mask, m_raw_value_dump); + lldb::OptionValueSP copied_value_sp(copied_dict); + collection::const_iterator pos, end = m_values.end(); + for (pos = m_values.begin(); pos != end; ++pos) { + StreamString strm; + strm.Printf("%s=", pos->first.GetCString()); + copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true); + } + return copied_value_sp; } - diff --git a/lldb/source/Interpreter/OptionValueEnumeration.cpp b/lldb/source/Interpreter/OptionValueEnumeration.cpp index 0f163d1c4f7..88b7f16d64b 100644 --- a/lldb/source/Interpreter/OptionValueEnumeration.cpp +++ b/lldb/source/Interpreter/OptionValueEnumeration.cpp @@ -18,146 +18,115 @@ using namespace lldb; using namespace lldb_private; -OptionValueEnumeration::OptionValueEnumeration (const OptionEnumValueElement *enumerators, - enum_type value) : - OptionValue(), - m_current_value (value), - m_default_value (value), - m_enumerations () -{ - SetEnumerations(enumerators); +OptionValueEnumeration::OptionValueEnumeration( + const OptionEnumValueElement *enumerators, enum_type value) + : OptionValue(), m_current_value(value), m_default_value(value), + m_enumerations() { + SetEnumerations(enumerators); } -OptionValueEnumeration::~OptionValueEnumeration() -{ -} +OptionValueEnumeration::~OptionValueEnumeration() {} -void -OptionValueEnumeration::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - const size_t count = m_enumerations.GetSize (); - for (size_t i=0; ivalue.value; - NotifyValueChanged(); - } - else - { - StreamString error_strm; - error_strm.Printf("invalid enumeration value '%s'", value.str().c_str()); - const size_t count = m_enumerations.GetSize (); - if (count) - { - error_strm.Printf(", valid values are: %s", m_enumerations.GetCStringAtIndex(0)); - for (size_t i=1; ivalue.value; + NotifyValueChanged(); + } else { + StreamString error_strm; + error_strm.Printf("invalid enumeration value '%s'", value.str().c_str()); + const size_t count = m_enumerations.GetSize(); + if (count) { + error_strm.Printf(", valid values are: %s", + m_enumerations.GetCStringAtIndex(0)); + for (size_t i = 1; i < count; ++i) { + error_strm.Printf(", %s", m_enumerations.GetCStringAtIndex(i)); } - m_enumerations.Sort(); + } + error.SetErrorString(error_strm.GetData()); } -} - + break; + } -lldb::OptionValueSP -OptionValueEnumeration::DeepCopy () const -{ - return OptionValueSP(new OptionValueEnumeration(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } -size_t -OptionValueEnumeration::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - - const uint32_t num_enumerators = m_enumerations.GetSize(); - if (s && s[0]) - { - const size_t s_len = strlen(s); - for (size_t i=0; i 0) - { - // The setting value may have whitespace, double-quotes, or single-quotes around the file - // path to indicate that internal spaces are not word breaks. Strip off any ws & quotes - // from the start and end of the file path - we aren't doing any word // breaking here so - // the quoting is unnecessary. NB this will cause a problem if someone tries to specify - // a file path that legitimately begins or ends with a " or ' character, or whitespace. - value = value.trim("\"' \t"); - m_value_was_set = true; - m_current_value.SetFile(value.str().c_str(), m_resolve); - m_data_sp.reset(); - m_data_mod_time.Clear(); - NotifyValueChanged(); - } - else - { - error.SetErrorString("invalid value string"); - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); - break; +Error OptionValueFileSpec::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + if (value.size() > 0) { + // The setting value may have whitespace, double-quotes, or single-quotes + // around the file + // path to indicate that internal spaces are not word breaks. Strip off + // any ws & quotes + // from the start and end of the file path - we aren't doing any word // + // breaking here so + // the quoting is unnecessary. NB this will cause a problem if someone + // tries to specify + // a file path that legitimately begins or ends with a " or ' character, + // or whitespace. + value = value.trim("\"' \t"); + m_value_was_set = true; + m_current_value.SetFile(value.str().c_str(), m_resolve); + m_data_sp.reset(); + m_data_mod_time.Clear(); + NotifyValueChanged(); + } else { + error.SetErrorString("invalid value string"); } - return error; + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } -lldb::OptionValueSP -OptionValueFileSpec::DeepCopy () const -{ - return OptionValueSP(new OptionValueFileSpec(*this)); +lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const { + return OptionValueSP(new OptionValueFileSpec(*this)); } - -size_t -OptionValueFileSpec::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, - m_completion_mask, - s, - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); +size_t OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter, + const char *s, int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) { + word_complete = false; + matches.Clear(); + CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, m_completion_mask, s, match_start_point, max_return_elements, + nullptr, word_complete, matches); + return matches.GetSize(); } - - const lldb::DataBufferSP & -OptionValueFileSpec::GetFileContents(bool null_terminate) -{ - if (m_current_value) - { - const TimeValue file_mod_time = m_current_value.GetModificationTime(); - if (m_data_sp && m_data_mod_time == file_mod_time) - return m_data_sp; - if (null_terminate) - m_data_sp = m_current_value.ReadFileContentsAsCString(); - else - m_data_sp = m_current_value.ReadFileContents(); - m_data_mod_time = file_mod_time; - } - return m_data_sp; +OptionValueFileSpec::GetFileContents(bool null_terminate) { + if (m_current_value) { + const TimeValue file_mod_time = m_current_value.GetModificationTime(); + if (m_data_sp && m_data_mod_time == file_mod_time) + return m_data_sp; + if (null_terminate) + m_data_sp = m_current_value.ReadFileContentsAsCString(); + else + m_data_sp = m_current_value.ReadFileContents(); + m_data_mod_time = file_mod_time; + } + return m_data_sp; } - - diff --git a/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp b/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp index 6a0ba11b676..a15dd5c11b7 100644 --- a/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp @@ -20,171 +20,145 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueFileSpecList::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.Printf (" =%s", m_current_value.GetSize() > 0 ? "\n" : ""); - strm.IndentMore(); - const uint32_t size = m_current_value.GetSize(); - for (uint32_t i = 0; i 0 ? "\n" : ""); + strm.IndentMore(); + const uint32_t size = m_current_value.GetSize(); + for (uint32_t i = 0; i < size; ++i) { + strm.Indent(); + strm.Printf("[%u]: ", i); + m_current_value.GetFileSpecAtIndex(i).Dump(&strm); } + strm.IndentLess(); + } } -Error -OptionValueFileSpecList::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - Args args(value.str().c_str()); - const size_t argc = args.GetArgumentCount(); +Error OptionValueFileSpecList::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + Args args(value.str().c_str()); + const size_t argc = args.GetArgumentCount(); - switch (op) - { - case eVarSetOperationClear: - Clear (); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - if (argc > 1) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = m_current_value.GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count); - } - else - { - for (size_t i=1; i 0) - { - m_value_was_set = true; - for (size_t i=0; i 1) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = m_current_value.GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid insert file list index %u, index must be 0 through %u", idx, count); - } - else - { - if (op == eVarSetOperationInsertAfter) - ++idx; - for (size_t i=1; i 0) - { - std::vector remove_indexes; - bool all_indexes_valid = true; - size_t i; - for (i=0; all_indexes_valid && i 1) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = m_current_value.GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid file list index %u, index must be 0 through %u", idx, + count); + } else { + for (size_t i = 1; i < argc; ++i, ++idx) { + FileSpec file(args.GetArgumentAtIndex(i), false); + if (idx < count) + m_current_value.Replace(idx, file); + else + m_current_value.Append(file); + } + NotifyValueChanged(); + } + } else { + error.SetErrorString("replace operation takes an array index followed by " + "one or more values"); } - return error; -} + break; -lldb::OptionValueSP -OptionValueFileSpecList::DeepCopy () const -{ - return OptionValueSP(new OptionValueFileSpecList(*this)); -} + case eVarSetOperationAssign: + m_current_value.Clear(); + // Fall through to append case + LLVM_FALLTHROUGH; + case eVarSetOperationAppend: + if (argc > 0) { + m_value_was_set = true; + for (size_t i = 0; i < argc; ++i) { + FileSpec file(args.GetArgumentAtIndex(i), false); + m_current_value.Append(file); + } + NotifyValueChanged(); + } else { + error.SetErrorString( + "assign operation takes at least one file path argument"); + } + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + if (argc > 1) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = m_current_value.GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid insert file list index %u, index must be 0 through %u", + idx, count); + } else { + if (op == eVarSetOperationInsertAfter) + ++idx; + for (size_t i = 1; i < argc; ++i, ++idx) { + FileSpec file(args.GetArgumentAtIndex(i), false); + m_current_value.Insert(idx, file); + } + NotifyValueChanged(); + } + } else { + error.SetErrorString("insert operation takes an array index followed by " + "one or more values"); + } + break; + + case eVarSetOperationRemove: + if (argc > 0) { + std::vector remove_indexes; + bool all_indexes_valid = true; + size_t i; + for (i = 0; all_indexes_valid && i < argc; ++i) { + const int idx = + StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); + if (idx == INT32_MAX) + all_indexes_valid = false; + else + remove_indexes.push_back(idx); + } + if (all_indexes_valid) { + size_t num_remove_indexes = remove_indexes.size(); + if (num_remove_indexes) { + // Sort and then erase in reverse so indexes are always valid + std::sort(remove_indexes.begin(), remove_indexes.end()); + for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { + m_current_value.Remove(j); + } + } + NotifyValueChanged(); + } else { + error.SetErrorStringWithFormat( + "invalid array index '%s', aborting remove operation", + args.GetArgumentAtIndex(i)); + } + } else { + error.SetErrorString("remove operation takes one or more array index"); + } + break; + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; +} + +lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const { + return OptionValueSP(new OptionValueFileSpecList(*this)); +} diff --git a/lldb/source/Interpreter/OptionValueFormat.cpp b/lldb/source/Interpreter/OptionValueFormat.cpp index 1d73d58ce8e..041d8a500a8 100644 --- a/lldb/source/Interpreter/OptionValueFormat.cpp +++ b/lldb/source/Interpreter/OptionValueFormat.cpp @@ -20,59 +20,48 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueFormat::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueFormat::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - strm.PutCString (FormatManager::GetFormatAsCString (m_current_value)); - } + strm.PutCString(" = "); + strm.PutCString(FormatManager::GetFormatAsCString(m_current_value)); + } } -Error -OptionValueFormat::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - Format new_format; - error = Args::StringToFormat (value.str().c_str(), new_format, nullptr); - if (error.Success()) - { - m_value_was_set = true; - m_current_value = new_format; - NotifyValueChanged(); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); - break; - } - return error; -} +Error OptionValueFormat::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + Format new_format; + error = Args::StringToFormat(value.str().c_str(), new_format, nullptr); + if (error.Success()) { + m_value_was_set = true; + m_current_value = new_format; + NotifyValueChanged(); + } + } break; -lldb::OptionValueSP -OptionValueFormat::DeepCopy () const -{ - return OptionValueSP(new OptionValueFormat(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } +lldb::OptionValueSP OptionValueFormat::DeepCopy() const { + return OptionValueSP(new OptionValueFormat(*this)); +} diff --git a/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/lldb/source/Interpreter/OptionValueFormatEntity.cpp index 66d8d8419ed..29c3b404806 100644 --- a/lldb/source/Interpreter/OptionValueFormatEntity.cpp +++ b/lldb/source/Interpreter/OptionValueFormatEntity.cpp @@ -20,121 +20,96 @@ using namespace lldb; using namespace lldb_private; - -OptionValueFormatEntity::OptionValueFormatEntity (const char *default_format) : - OptionValue(), - m_current_format (), - m_default_format (), - m_current_entry (), - m_default_entry () -{ - if (default_format && default_format[0]) - { - llvm::StringRef default_format_str(default_format); - Error error = FormatEntity::Parse(default_format_str, m_default_entry); - if (error.Success()) - { - m_default_format = default_format; - m_current_format = default_format; - m_current_entry = m_default_entry; - } +OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) + : OptionValue(), m_current_format(), m_default_format(), m_current_entry(), + m_default_entry() { + if (default_format && default_format[0]) { + llvm::StringRef default_format_str(default_format); + Error error = FormatEntity::Parse(default_format_str, m_default_entry); + if (error.Success()) { + m_default_format = default_format; + m_current_format = default_format; + m_current_entry = m_default_entry; } + } } -bool -OptionValueFormatEntity::Clear () -{ - m_current_entry = m_default_entry; - m_current_format = m_default_format; - m_value_was_set = false; - return true; +bool OptionValueFormatEntity::Clear() { + m_current_entry = m_default_entry; + m_current_format = m_default_format; + m_value_was_set = false; + return true; } - -void -OptionValueFormatEntity::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = \""); - strm << m_current_format.c_str() << '"'; - } + strm.PutCString(" = \""); + strm << m_current_format.c_str() << '"'; + } } -Error -OptionValueFormatEntity::SetValueFromString (llvm::StringRef value_str, - VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - // Check if the string starts with a quote character after removing leading and trailing spaces. - // If it does start with a quote character, make sure it ends with the same quote character - // and remove the quotes before we parse the format string. If the string doesn't start with - // a quote, leave the string alone and parse as is. - llvm::StringRef trimmed_value_str = value_str.trim(); - if (!trimmed_value_str.empty()) - { - const char first_char = trimmed_value_str[0]; - if (first_char == '"' || first_char == '\'') - { - const size_t trimmed_len = trimmed_value_str.size(); - if (trimmed_len == 1 || value_str[trimmed_len-1] != first_char) - { - error.SetErrorStringWithFormat("mismatched quotes"); - return error; - } - value_str = trimmed_value_str.substr(1,trimmed_len-2); - } - } - FormatEntity::Entry entry; - error = FormatEntity::Parse(value_str, entry); - if (error.Success()) - { - m_current_entry = std::move(entry); - m_current_format = value_str; - m_value_was_set = true; - NotifyValueChanged(); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value_str, op); - break; +Error OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + // Check if the string starts with a quote character after removing leading + // and trailing spaces. + // If it does start with a quote character, make sure it ends with the same + // quote character + // and remove the quotes before we parse the format string. If the string + // doesn't start with + // a quote, leave the string alone and parse as is. + llvm::StringRef trimmed_value_str = value_str.trim(); + if (!trimmed_value_str.empty()) { + const char first_char = trimmed_value_str[0]; + if (first_char == '"' || first_char == '\'') { + const size_t trimmed_len = trimmed_value_str.size(); + if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) { + error.SetErrorStringWithFormat("mismatched quotes"); + return error; + } + value_str = trimmed_value_str.substr(1, trimmed_len - 2); + } } - return error; -} + FormatEntity::Entry entry; + error = FormatEntity::Parse(value_str, entry); + if (error.Success()) { + m_current_entry = std::move(entry); + m_current_format = value_str; + m_value_was_set = true; + NotifyValueChanged(); + } + } break; -lldb::OptionValueSP -OptionValueFormatEntity::DeepCopy () const -{ - return OptionValueSP(new OptionValueFormatEntity(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value_str, op); + break; + } + return error; } -size_t -OptionValueFormatEntity::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - return FormatEntity::AutoComplete (s, match_start_point, max_return_elements, word_complete, matches); +lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const { + return OptionValueSP(new OptionValueFormatEntity(*this)); } +size_t OptionValueFormatEntity::AutoComplete( + CommandInterpreter &interpreter, const char *s, int match_start_point, + int max_return_elements, bool &word_complete, StringList &matches) { + return FormatEntity::AutoComplete(s, match_start_point, max_return_elements, + word_complete, matches); +} diff --git a/lldb/source/Interpreter/OptionValueLanguage.cpp b/lldb/source/Interpreter/OptionValueLanguage.cpp index dd7173c3dc7..f5505f70320 100644 --- a/lldb/source/Interpreter/OptionValueLanguage.cpp +++ b/lldb/source/Interpreter/OptionValueLanguage.cpp @@ -21,72 +21,61 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueLanguage::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueLanguage::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - strm.PutCString (Language::GetNameForLanguageType(m_current_value)); - } + strm.PutCString(" = "); + strm.PutCString(Language::GetNameForLanguageType(m_current_value)); + } } -Error -OptionValueLanguage::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - ConstString lang_name(value.trim()); - std::set languages_for_types; - std::set languages_for_expressions; - Language::GetLanguagesSupportingTypeSystems(languages_for_types, languages_for_expressions); +Error OptionValueLanguage::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + break; - LanguageType new_type = Language::GetLanguageTypeFromString(lang_name.GetCString()); - if (new_type && languages_for_types.count(new_type)) - { - m_value_was_set = true; - m_current_value = new_type; - } - else - { - StreamString error_strm; - error_strm.Printf("invalid language type '%s', ", value.str().c_str()); - error_strm.Printf("valid values are:\n"); - for (lldb::LanguageType language : languages_for_types) - { - error_strm.Printf("%s%s%s", " ", Language::GetNameForLanguageType(language), "\n"); - } - error.SetErrorString(error_strm.GetData()); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString(value, op); - break; - } - return error; -} + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + ConstString lang_name(value.trim()); + std::set languages_for_types; + std::set languages_for_expressions; + Language::GetLanguagesSupportingTypeSystems(languages_for_types, + languages_for_expressions); + LanguageType new_type = + Language::GetLanguageTypeFromString(lang_name.GetCString()); + if (new_type && languages_for_types.count(new_type)) { + m_value_was_set = true; + m_current_value = new_type; + } else { + StreamString error_strm; + error_strm.Printf("invalid language type '%s', ", value.str().c_str()); + error_strm.Printf("valid values are:\n"); + for (lldb::LanguageType language : languages_for_types) { + error_strm.Printf("%s%s%s", " ", + Language::GetNameForLanguageType(language), "\n"); + } + error.SetErrorString(error_strm.GetData()); + } + } break; -lldb::OptionValueSP -OptionValueLanguage::DeepCopy () const -{ - return OptionValueSP(new OptionValueLanguage(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } +lldb::OptionValueSP OptionValueLanguage::DeepCopy() const { + return OptionValueSP(new OptionValueLanguage(*this)); +} diff --git a/lldb/source/Interpreter/OptionValuePathMappings.cpp b/lldb/source/Interpreter/OptionValuePathMappings.cpp index f3f146f1f8c..15e50fdc4cd 100644 --- a/lldb/source/Interpreter/OptionValuePathMappings.cpp +++ b/lldb/source/Interpreter/OptionValuePathMappings.cpp @@ -20,222 +20,189 @@ using namespace lldb; using namespace lldb_private; -namespace -{ - static bool - VerifyPathExists(const char *path) - { - if (path && path[0]) - return FileSpec(path, false).Exists(); - else - return false; - } +namespace { +static bool VerifyPathExists(const char *path) { + if (path && path[0]) + return FileSpec(path, false).Exists(); + else + return false; +} } - -void -OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : ""); - m_path_mappings.Dump(&strm); - } + strm.Printf(" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : ""); + m_path_mappings.Dump(&strm); + } } -Error -OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - Args args(value.str().c_str()); - const size_t argc = args.GetArgumentCount(); +Error OptionValuePathMappings::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + Args args(value.str().c_str()); + const size_t argc = args.GetArgumentCount(); - switch (op) - { - case eVarSetOperationClear: - Clear (); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - // Must be at least one index + 1 pair of paths, and the pair count must be even - if (argc >= 3 && (((argc - 1) & 1) == 0)) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = m_path_mappings.GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count); - } - else - { - bool changed = false; - for (size_t i=1; i= 3 && (((argc - 1) & 1) == 0)) - { - uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); - const uint32_t count = m_path_mappings.GetSize(); - if (idx > count) - { - error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count); - } - else - { - bool changed = false; - if (op == eVarSetOperationInsertAfter) - ++idx; - for (size_t i=1; i 0) - { - std::vector remove_indexes; - bool all_indexes_valid = true; - size_t i; - for (i=0; all_indexes_valid && i= 3 && (((argc - 1) & 1) == 0)) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = m_path_mappings.GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid file list index %u, index must be 0 through %u", idx, + count); + } else { + bool changed = false; + for (size_t i = 1; i < argc; i += 2, ++idx) { + const char *orginal_path = args.GetArgumentAtIndex(i); + const char *replace_path = args.GetArgumentAtIndex(i + 1); + if (VerifyPathExists(replace_path)) { + ConstString a(orginal_path); + ConstString b(replace_path); + if (!m_path_mappings.Replace(a, b, idx, m_notify_changes)) + m_path_mappings.Append(a, b, m_notify_changes); + changed = true; + } else { + error.SetErrorStringWithFormat( + "the replacement path doesn't exist: \"%s\"", replace_path); break; + } + } + if (changed) + NotifyValueChanged(); + } + } else { + error.SetErrorString("replace operation takes an array index followed by " + "one or more path pairs"); + } + break; - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); + case eVarSetOperationAssign: + if (argc < 2 || (argc & 1)) { + error.SetErrorString("assign operation takes one or more path pairs"); + break; + } + m_path_mappings.Clear(m_notify_changes); + // Fall through to append case + LLVM_FALLTHROUGH; + case eVarSetOperationAppend: + if (argc < 2 || (argc & 1)) { + error.SetErrorString("append operation takes one or more path pairs"); + break; + } else { + bool changed = false; + for (size_t i = 0; i < argc; i += 2) { + const char *orginal_path = args.GetArgumentAtIndex(i); + const char *replace_path = args.GetArgumentAtIndex(i + 1); + if (VerifyPathExists(replace_path)) { + ConstString a(orginal_path); + ConstString b(replace_path); + m_path_mappings.Append(a, b, m_notify_changes); + m_value_was_set = true; + changed = true; + } else { + error.SetErrorStringWithFormat( + "the replacement path doesn't exist: \"%s\"", replace_path); + break; + } + } + if (changed) + NotifyValueChanged(); + } + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + // Must be at least one index + 1 pair of paths, and the pair count must be + // even + if (argc >= 3 && (((argc - 1) & 1) == 0)) { + uint32_t idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + const uint32_t count = m_path_mappings.GetSize(); + if (idx > count) { + error.SetErrorStringWithFormat( + "invalid file list index %u, index must be 0 through %u", idx, + count); + } else { + bool changed = false; + if (op == eVarSetOperationInsertAfter) + ++idx; + for (size_t i = 1; i < argc; i += 2, ++idx) { + const char *orginal_path = args.GetArgumentAtIndex(i); + const char *replace_path = args.GetArgumentAtIndex(i + 1); + if (VerifyPathExists(replace_path)) { + ConstString a(orginal_path); + ConstString b(replace_path); + m_path_mappings.Insert(a, b, idx, m_notify_changes); + changed = true; + } else { + error.SetErrorStringWithFormat( + "the replacement path doesn't exist: \"%s\"", replace_path); break; + } + } + if (changed) + NotifyValueChanged(); + } + } else { + error.SetErrorString("insert operation takes an array index followed by " + "one or more path pairs"); } - return error; + break; + + case eVarSetOperationRemove: + if (argc > 0) { + std::vector remove_indexes; + bool all_indexes_valid = true; + size_t i; + for (i = 0; all_indexes_valid && i < argc; ++i) { + const int idx = + StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); + if (idx == INT32_MAX) + all_indexes_valid = false; + else + remove_indexes.push_back(idx); + } + + if (all_indexes_valid) { + size_t num_remove_indexes = remove_indexes.size(); + if (num_remove_indexes) { + // Sort and then erase in reverse so indexes are always valid + std::sort(remove_indexes.begin(), remove_indexes.end()); + for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { + m_path_mappings.Remove(j, m_notify_changes); + } + } + NotifyValueChanged(); + } else { + error.SetErrorStringWithFormat( + "invalid array index '%s', aborting remove operation", + args.GetArgumentAtIndex(i)); + } + } else { + error.SetErrorString("remove operation takes one or more array index"); + } + break; + + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } -lldb::OptionValueSP -OptionValuePathMappings::DeepCopy () const -{ - return OptionValueSP(new OptionValuePathMappings(*this)); +lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const { + return OptionValueSP(new OptionValuePathMappings(*this)); } diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp index 7024c3601d9..d5f7e3f18a0 100644 --- a/lldb/source/Interpreter/OptionValueProperties.cpp +++ b/lldb/source/Interpreter/OptionValueProperties.cpp @@ -1,4 +1,5 @@ -//===-- OptionValueProperties.cpp ---------------------------------*- C++ -*-===// +//===-- OptionValueProperties.cpp ---------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -24,89 +25,68 @@ using namespace lldb; using namespace lldb_private; - -OptionValueProperties::OptionValueProperties (const ConstString &name) : - OptionValue (), - m_name (name), - m_properties (), - m_name_to_index () -{ -} - -OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) : - OptionValue (global_properties), - std::enable_shared_from_this (), - m_name (global_properties.m_name), - m_properties (global_properties.m_properties), - m_name_to_index (global_properties.m_name_to_index) -{ - // We now have an exact copy of "global_properties". We need to now - // find all non-global settings and copy the property values so that - // all non-global settings get new OptionValue instances created for - // them. - const size_t num_properties = m_properties.size(); - for (size_t i=0; iDeepCopy()); - m_properties[i].SetOptionValue(new_value_sp); - } +OptionValueProperties::OptionValueProperties(const ConstString &name) + : OptionValue(), m_name(name), m_properties(), m_name_to_index() {} + +OptionValueProperties::OptionValueProperties( + const OptionValueProperties &global_properties) + : OptionValue(global_properties), + std::enable_shared_from_this(), + m_name(global_properties.m_name), + m_properties(global_properties.m_properties), + m_name_to_index(global_properties.m_name_to_index) { + // We now have an exact copy of "global_properties". We need to now + // find all non-global settings and copy the property values so that + // all non-global settings get new OptionValue instances created for + // them. + const size_t num_properties = m_properties.size(); + for (size_t i = 0; i < num_properties; ++i) { + // Duplicate any values that are not global when constructing properties + // from + // a global copy + if (m_properties[i].IsGlobal() == false) { + lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy()); + m_properties[i].SetOptionValue(new_value_sp); } + } } - - -size_t -OptionValueProperties::GetNumProperties() const -{ - return m_properties.size(); +size_t OptionValueProperties::GetNumProperties() const { + return m_properties.size(); } - -void -OptionValueProperties::Initialize (const PropertyDefinition *defs) -{ - for (size_t i=0; defs[i].name; ++i) - { - Property property(defs[i]); - assert(property.IsValid()); - m_name_to_index.Append(property.GetName().GetCString(),m_properties.size()); - property.GetValue()->SetParent(shared_from_this()); - m_properties.push_back(property); - } - m_name_to_index.Sort(); +void OptionValueProperties::Initialize(const PropertyDefinition *defs) { + for (size_t i = 0; defs[i].name; ++i) { + Property property(defs[i]); + assert(property.IsValid()); + m_name_to_index.Append(property.GetName().GetCString(), + m_properties.size()); + property.GetValue()->SetParent(shared_from_this()); + m_properties.push_back(property); + } + m_name_to_index.Sort(); } -void -OptionValueProperties::SetValueChangedCallback (uint32_t property_idx, - OptionValueChangedCallback callback, - void *baton) -{ - Property *property = ProtectedGetPropertyAtIndex (property_idx); - if (property) - property->SetValueChangedCallback (callback, baton); +void OptionValueProperties::SetValueChangedCallback( + uint32_t property_idx, OptionValueChangedCallback callback, void *baton) { + Property *property = ProtectedGetPropertyAtIndex(property_idx); + if (property) + property->SetValueChangedCallback(callback, baton); } -void -OptionValueProperties::AppendProperty(const ConstString &name, - const ConstString &desc, - bool is_global, - const OptionValueSP &value_sp) -{ - Property property(name, desc, is_global, value_sp); - m_name_to_index.Append(name.GetCString(),m_properties.size()); - m_properties.push_back(property); - value_sp->SetParent (shared_from_this()); - m_name_to_index.Sort(); +void OptionValueProperties::AppendProperty(const ConstString &name, + const ConstString &desc, + bool is_global, + const OptionValueSP &value_sp) { + Property property(name, desc, is_global, value_sp); + m_name_to_index.Append(name.GetCString(), m_properties.size()); + m_properties.push_back(property); + value_sp->SetParent(shared_from_this()); + m_name_to_index.Sort(); } - - -//bool -//OptionValueProperties::GetQualifiedName (Stream &strm) +// bool +// OptionValueProperties::GetQualifiedName (Stream &strm) //{ // bool dumped_something = false; //// lldb::OptionValuePropertiesSP parent_sp(GetParent ()); @@ -125,686 +105,589 @@ OptionValueProperties::AppendProperty(const ConstString &name, //} // lldb::OptionValueSP -OptionValueProperties::GetValueForKey (const ExecutionContext *exe_ctx, - const ConstString &key, - bool will_modify) const -{ - lldb::OptionValueSP value_sp; - size_t idx = m_name_to_index.Find (key.GetCString(), SIZE_MAX); - if (idx < m_properties.size()) - value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue(); - return value_sp; +OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx, + const ConstString &key, + bool will_modify) const { + lldb::OptionValueSP value_sp; + size_t idx = m_name_to_index.Find(key.GetCString(), SIZE_MAX); + if (idx < m_properties.size()) + value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue(); + return value_sp; } lldb::OptionValueSP -OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx, - const char *name, - bool will_modify, - Error &error) const -{ - lldb::OptionValueSP value_sp; - - if (name && name[0]) - { - const char *sub_name = nullptr; - ConstString key; - size_t key_len = ::strcspn (name, ".[{"); - - if (name[key_len]) - { - key.SetCStringWithLength (name, key_len); - sub_name = name + key_len; +OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx, + const char *name, bool will_modify, + Error &error) const { + lldb::OptionValueSP value_sp; + + if (name && name[0]) { + const char *sub_name = nullptr; + ConstString key; + size_t key_len = ::strcspn(name, ".[{"); + + if (name[key_len]) { + key.SetCStringWithLength(name, key_len); + sub_name = name + key_len; + } else + key.SetCString(name); + + value_sp = GetValueForKey(exe_ctx, key, will_modify); + if (sub_name && value_sp) { + switch (sub_name[0]) { + case '.': { + lldb::OptionValueSP return_val_sp; + return_val_sp = + value_sp->GetSubValue(exe_ctx, sub_name + 1, will_modify, error); + if (!return_val_sp) { + if (Properties::IsSettingExperimental(sub_name + 1)) { + size_t experimental_len = + strlen(Properties::GetExperimentalSettingsName()); + if (*(sub_name + experimental_len + 1) == '.') + return_val_sp = value_sp->GetSubValue( + exe_ctx, sub_name + experimental_len + 2, will_modify, error); + // It isn't an error if an experimental setting is not present. + if (!return_val_sp) + error.Clear(); + } } - else - key.SetCString (name); - - value_sp = GetValueForKey (exe_ctx, key, will_modify); - if (sub_name && value_sp) - { - switch (sub_name[0]) - { - case '.': - { - lldb::OptionValueSP return_val_sp; - return_val_sp = value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error); - if (!return_val_sp) - { - if (Properties::IsSettingExperimental(sub_name + 1)) - { - size_t experimental_len = strlen(Properties::GetExperimentalSettingsName()); - if (*(sub_name + experimental_len + 1) == '.') - return_val_sp = value_sp->GetSubValue(exe_ctx, sub_name + experimental_len + 2, will_modify, error); - // It isn't an error if an experimental setting is not present. - if (!return_val_sp) - error.Clear(); - } - } - return return_val_sp; - } - case '{': - // Predicate matching for predicates like - // "{}" - // strings are parsed by the current OptionValueProperties subclass - // to mean whatever they want to. For instance a subclass of - // OptionValueProperties for a lldb_private::Target might implement: - // "target.run-args{arch==i386}" -- only set run args if the arch is i386 - // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches - // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if executable basename is "test" and arch is "x86_64" - if (sub_name[1]) - { - const char *predicate_start = sub_name + 1; - const char *predicate_end = strchr(predicate_start, '}'); - if (predicate_end) - { - std::string predicate(predicate_start, predicate_end); - if (PredicateMatches(exe_ctx, predicate.c_str())) - { - if (predicate_end[1]) - { - // Still more subvalue string to evaluate - return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error); - } - else - { - // We have a match! - break; - } - } - } - } - // Predicate didn't match or wasn't correctly formed - value_sp.reset(); - break; - - case '[': - // Array or dictionary access for subvalues like: - // "[12]" -- access 12th array element - // "['hello']" -- dictionary access of key named hello - return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error); - - default: - value_sp.reset(); + return return_val_sp; + } + case '{': + // Predicate matching for predicates like + // "{}" + // strings are parsed by the current OptionValueProperties subclass + // to mean whatever they want to. For instance a subclass of + // OptionValueProperties for a lldb_private::Target might implement: + // "target.run-args{arch==i386}" -- only set run args if the arch is + // i386 + // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the + // path matches + // "target.run-args{basename==test&&arch==x86_64}" -- only set run args + // if executable basename is "test" and arch is "x86_64" + if (sub_name[1]) { + const char *predicate_start = sub_name + 1; + const char *predicate_end = strchr(predicate_start, '}'); + if (predicate_end) { + std::string predicate(predicate_start, predicate_end); + if (PredicateMatches(exe_ctx, predicate.c_str())) { + if (predicate_end[1]) { + // Still more subvalue string to evaluate + return value_sp->GetSubValue(exe_ctx, predicate_end + 1, + will_modify, error); + } else { + // We have a match! break; + } } + } } + // Predicate didn't match or wasn't correctly formed + value_sp.reset(); + break; + + case '[': + // Array or dictionary access for subvalues like: + // "[12]" -- access 12th array element + // "['hello']" -- dictionary access of key named hello + return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error); + + default: + value_sp.reset(); + break; + } } - return value_sp; -} - -Error -OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *name, - const char *value) -{ - Error error; - const bool will_modify = true; - lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); - if (value_sp) - error = value_sp->SetValueFromString(value ? llvm::StringRef(value) : llvm::StringRef(), op); - else - { - if (error.AsCString() == nullptr) - error.SetErrorStringWithFormat("invalid value path '%s'", name); - } - return error; + } + return value_sp; } +Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *name, const char *value) { + Error error; + const bool will_modify = true; + lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error)); + if (value_sp) + error = value_sp->SetValueFromString( + value ? llvm::StringRef(value) : llvm::StringRef(), op); + else { + if (error.AsCString() == nullptr) + error.SetErrorStringWithFormat("invalid value path '%s'", name); + } + return error; +} -ConstString -OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex(nullptr, false, idx); - if (property) - return property->GetName(); - return ConstString(); - +ConstString OptionValueProperties::GetPropertyNameAtIndex(uint32_t idx) const { + const Property *property = GetPropertyAtIndex(nullptr, false, idx); + if (property) + return property->GetName(); + return ConstString(); } const char * -OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex(nullptr, false, idx); - if (property) - return property->GetDescription(); - return nullptr; +OptionValueProperties::GetPropertyDescriptionAtIndex(uint32_t idx) const { + const Property *property = GetPropertyAtIndex(nullptr, false, idx); + if (property) + return property->GetDescription(); + return nullptr; } uint32_t -OptionValueProperties::GetPropertyIndex (const ConstString &name) const -{ - return m_name_to_index.Find (name.GetCString(), SIZE_MAX); +OptionValueProperties::GetPropertyIndex(const ConstString &name) const { + return m_name_to_index.Find(name.GetCString(), SIZE_MAX); } const Property * -OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const -{ - return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), SIZE_MAX)); +OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx, + bool will_modify, + const ConstString &name) const { + return GetPropertyAtIndex(exe_ctx, will_modify, + m_name_to_index.Find(name.GetCString(), SIZE_MAX)); } -const Property * -OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const -{ - return ProtectedGetPropertyAtIndex (idx); +const Property *OptionValueProperties::GetPropertyAtIndex( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + return ProtectedGetPropertyAtIndex(idx); } -lldb::OptionValueSP -OptionValueProperties::GetPropertyValueAtIndex (const ExecutionContext *exe_ctx, - bool will_modify, - uint32_t idx) const -{ - const Property *setting = GetPropertyAtIndex (exe_ctx, will_modify, idx); - if (setting) - return setting->GetValue(); - return OptionValueSP(); +lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx); + if (setting) + return setting->GetValue(); + return OptionValueSP(); } OptionValuePathMappings * -OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const -{ - OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); - if (value_sp) - return value_sp->GetAsPathMappings(); - return nullptr; +OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); + if (value_sp) + return value_sp->GetAsPathMappings(); + return nullptr; } OptionValueFileSpecList * -OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const -{ - OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); - if (value_sp) - return value_sp->GetAsFileSpecList(); - return nullptr; -} - -OptionValueArch * -OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - return property->GetValue()->GetAsArch(); - return nullptr; -} - -OptionValueLanguage * -OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - return property->GetValue()->GetAsLanguage(); - return nullptr; +OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); + if (value_sp) + return value_sp->GetAsFileSpecList(); + return nullptr; } -bool -OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - { - const OptionValueArray *array = value->GetAsArray(); - if (array) - return array->GetArgs(args); - else - { - const OptionValueDictionary *dict = value->GetAsDictionary(); - if (dict) - return dict->GetArgs(args); - } - } - } - return false; +OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) + return property->GetValue()->GetAsArch(); + return nullptr; } -bool -OptionValueProperties::SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - { - OptionValueArray *array = value->GetAsArray(); - if (array) - return array->SetArgs(args, eVarSetOperationAssign).Success(); - else - { - OptionValueDictionary *dict = value->GetAsDictionary(); - if (dict) - return dict->SetArgs(args, eVarSetOperationAssign).Success(); - } - } +OptionValueLanguage * +OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) + return property->GetValue()->GetAsLanguage(); + return nullptr; +} + +bool OptionValueProperties::GetPropertyAtIndexAsArgs( + const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) { + const OptionValueArray *array = value->GetAsArray(); + if (array) + return array->GetArgs(args); + else { + const OptionValueDictionary *dict = value->GetAsDictionary(); + if (dict) + return dict->GetArgs(args); + } } - return false; -} - -bool -OptionValueProperties::GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetBooleanValue(fail_value); + } + return false; +} + +bool OptionValueProperties::SetPropertyAtIndexFromArgs( + const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) { + OptionValueArray *array = value->GetAsArray(); + if (array) + return array->SetArgs(args, eVarSetOperationAssign).Success(); + else { + OptionValueDictionary *dict = value->GetAsDictionary(); + if (dict) + return dict->SetArgs(args, eVarSetOperationAssign).Success(); + } } - return fail_value; -} - -bool -OptionValueProperties::SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - { - value->SetBooleanValue(new_value); - return true; - } + } + return false; +} + +bool OptionValueProperties::GetPropertyAtIndexAsBoolean( + const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetBooleanValue(fail_value); + } + return fail_value; +} + +bool OptionValueProperties::SetPropertyAtIndexAsBoolean( + const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) { + value->SetBooleanValue(new_value); + return true; } - return false; + } + return false; } OptionValueDictionary * -OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - return property->GetValue()->GetAsDictionary(); - return nullptr; -} - -int64_t -OptionValueProperties::GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetEnumerationValue(fail_value); - } - return fail_value; -} - -bool -OptionValueProperties::SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->SetEnumerationValue(new_value); - } - return false; +OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) + return property->GetValue()->GetAsDictionary(); + return nullptr; +} + +int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration( + const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetEnumerationValue(fail_value); + } + return fail_value; +} + +bool OptionValueProperties::SetPropertyAtIndexAsEnumeration( + const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->SetEnumerationValue(new_value); + } + return false; } const FormatEntity::Entry * -OptionValueProperties::GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetFormatEntity(); - } - return nullptr; +OptionValueProperties::GetPropertyAtIndexAsFormatEntity( + const ExecutionContext *exe_ctx, uint32_t idx) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetFormatEntity(); + } + return nullptr; } OptionValueFileSpec * -OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetAsFileSpec(); - } - return nullptr; -} - - -FileSpec -OptionValueProperties::GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetFileSpecValue(); - } - return FileSpec(); -} - - -bool -OptionValueProperties::SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &new_file_spec) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->SetFileSpecValue(new_file_spec); - } - return false; +OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetAsFileSpec(); + } + return nullptr; +} + +FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetFileSpecValue(); + } + return FileSpec(); +} + +bool OptionValueProperties::SetPropertyAtIndexAsFileSpec( + const ExecutionContext *exe_ctx, uint32_t idx, + const FileSpec &new_file_spec) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->SetFileSpecValue(new_file_spec); + } + return false; } const RegularExpression * -OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetRegexValue(); +OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetRegexValue(); + } + return nullptr; +} + +OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64( + const ExecutionContext *exe_ctx, uint32_t idx) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetAsSInt64(); + } + return nullptr; +} + +int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64( + const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetSInt64Value(fail_value); + } + return fail_value; +} + +bool OptionValueProperties::SetPropertyAtIndexAsSInt64( + const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->SetSInt64Value(new_value); + } + return false; +} + +const char *OptionValueProperties::GetPropertyAtIndexAsString( + const ExecutionContext *exe_ctx, uint32_t idx, + const char *fail_value) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetStringValue(fail_value); + } + return fail_value; +} + +bool OptionValueProperties::SetPropertyAtIndexAsString( + const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->SetStringValue(new_value); + } + return false; +} + +OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString( + const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { + OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); + if (value_sp) + return value_sp->GetAsString(); + return nullptr; +} + +uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64( + const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const { + const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->GetUInt64Value(fail_value); + } + return fail_value; +} + +bool OptionValueProperties::SetPropertyAtIndexAsUInt64( + const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) { + const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); + if (property) { + OptionValue *value = property->GetValue().get(); + if (value) + return value->SetUInt64Value(new_value); + } + return false; +} + +bool OptionValueProperties::Clear() { + const size_t num_properties = m_properties.size(); + for (size_t i = 0; i < num_properties; ++i) + m_properties[i].GetValue()->Clear(); + return true; +} + +Error OptionValueProperties::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + + // Args args(value_cstr); + // const size_t argc = args.GetArgumentCount(); + switch (op) { + case eVarSetOperationClear: + Clear(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + case eVarSetOperationRemove: + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + + return error; +} + +void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + const size_t num_properties = m_properties.size(); + for (size_t i = 0; i < num_properties; ++i) { + const Property *property = GetPropertyAtIndex(exe_ctx, false, i); + if (property) { + OptionValue *option_value = property->GetValue().get(); + assert(option_value); + const bool transparent_value = option_value->ValueIsTransparent(); + property->Dump(exe_ctx, strm, dump_mask); + if (!transparent_value) + strm.EOL(); } - return nullptr; -} - -OptionValueSInt64 * -OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetAsSInt64(); + } +} + +Error OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx, + Stream &strm, + const char *property_path, + uint32_t dump_mask) { + Error error; + const bool will_modify = false; + lldb::OptionValueSP value_sp( + GetSubValue(exe_ctx, property_path, will_modify, error)); + if (value_sp) { + if (!value_sp->ValueIsTransparent()) { + if (dump_mask & eDumpOptionName) + strm.PutCString(property_path); + if (dump_mask & ~eDumpOptionName) + strm.PutChar(' '); } - return nullptr; -} - -int64_t -OptionValueProperties::GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetSInt64Value(fail_value); + value_sp->DumpValue(exe_ctx, strm, dump_mask); + } + return error; +} + +lldb::OptionValueSP OptionValueProperties::DeepCopy() const { + assert(!"this shouldn't happen"); + return lldb::OptionValueSP(); +} + +const Property *OptionValueProperties::GetPropertyAtPath( + const ExecutionContext *exe_ctx, bool will_modify, const char *name) const { + const Property *property = nullptr; + if (name && name[0]) { + const char *sub_name = nullptr; + ConstString key; + size_t key_len = ::strcspn(name, ".[{"); + + if (name[key_len]) { + key.SetCStringWithLength(name, key_len); + sub_name = name + key_len; + } else + key.SetCString(name); + + property = GetProperty(exe_ctx, will_modify, key); + if (sub_name && property) { + if (sub_name[0] == '.') { + OptionValueProperties *sub_properties = + property->GetValue()->GetAsProperties(); + if (sub_properties) + return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, + sub_name + 1); + } + property = nullptr; } - return fail_value; + } + return property; } -bool -OptionValueProperties::SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); +void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter, + Stream &strm) const { + size_t max_name_len = 0; + const size_t num_properties = m_properties.size(); + for (size_t i = 0; i < num_properties; ++i) { + const Property *property = ProtectedGetPropertyAtIndex(i); if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->SetSInt64Value(new_value); - } - return false; -} - -const char * -OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); + max_name_len = + std::max(property->GetName().GetLength(), max_name_len); + } + for (size_t i = 0; i < num_properties; ++i) { + const Property *property = ProtectedGetPropertyAtIndex(i); if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetStringValue(fail_value); - } - return fail_value; -} - -bool -OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->SetStringValue(new_value); - } - return false; -} - -OptionValueString * -OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const -{ - OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); - if (value_sp) - return value_sp->GetAsString(); - return nullptr; -} - - -uint64_t -OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const -{ - const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->GetUInt64Value(fail_value); - } - return fail_value; -} - -bool -OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) -{ - const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); - if (property) - { - OptionValue *value = property->GetValue().get(); - if (value) - return value->SetUInt64Value(new_value); - } - return false; -} - -bool -OptionValueProperties::Clear () -{ - const size_t num_properties = m_properties.size(); - for (size_t i=0; iClear(); - return true; -} - - -Error -OptionValueProperties::SetValueFromString (llvm::StringRef value, VarSetOperationType op) -{ - Error error; - -// Args args(value_cstr); -// const size_t argc = args.GetArgumentCount(); - switch (op) - { - case eVarSetOperationClear: - Clear (); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - case eVarSetOperationRemove: - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); - break; - } - - return error; -} - -void -OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ - const size_t num_properties = m_properties.size(); - for (size_t i=0; iGetValue().get(); - assert (option_value); - const bool transparent_value = option_value->ValueIsTransparent (); - property->Dump (exe_ctx, - strm, - dump_mask); - if (!transparent_value) - strm.EOL(); - } - } -} - -Error -OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx, - Stream &strm, - const char *property_path, - uint32_t dump_mask) -{ - Error error; - const bool will_modify = false; - lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error)); - if (value_sp) - { - if (!value_sp->ValueIsTransparent ()) - { - if (dump_mask & eDumpOptionName) - strm.PutCString (property_path); - if (dump_mask & ~eDumpOptionName) - strm.PutChar (' '); - } - value_sp->DumpValue (exe_ctx, strm, dump_mask); - } - return error; -} - -lldb::OptionValueSP -OptionValueProperties::DeepCopy () const -{ - assert(!"this shouldn't happen"); - return lldb::OptionValueSP(); -} - -const Property * -OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx, - bool will_modify, - const char *name) const -{ - const Property *property = nullptr; - if (name && name[0]) - { - const char *sub_name = nullptr; - ConstString key; - size_t key_len = ::strcspn (name, ".[{"); - - if (name[key_len]) - { - key.SetCStringWithLength (name, key_len); - sub_name = name + key_len; - } - else - key.SetCString (name); - - property = GetProperty (exe_ctx, will_modify, key); - if (sub_name && property) - { - if (sub_name[0] == '.') - { - OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties(); - if (sub_properties) - return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1); - } - property = nullptr; + property->DumpDescription(interpreter, strm, max_name_len, false); + } +} + +void OptionValueProperties::Apropos( + const char *keyword, + std::vector &matching_properties) const { + const size_t num_properties = m_properties.size(); + StreamString strm; + for (size_t i = 0; i < num_properties; ++i) { + const Property *property = ProtectedGetPropertyAtIndex(i); + if (property) { + const OptionValueProperties *properties = + property->GetValue()->GetAsProperties(); + if (properties) { + properties->Apropos(keyword, matching_properties); + } else { + bool match = false; + const char *name = property->GetName().GetCString(); + if (name && ::strcasestr(name, keyword)) + match = true; + else { + const char *desc = property->GetDescription(); + if (desc && ::strcasestr(desc, keyword)) + match = true; } - } - return property; -} - -void -OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter, - Stream &strm) const -{ - size_t max_name_len = 0; - const size_t num_properties = m_properties.size(); - for (size_t i=0; i(property->GetName().GetLength(), max_name_len); - } - for (size_t i=0; iDumpDescription (interpreter, strm, max_name_len, false); - } -} - -void -OptionValueProperties::Apropos (const char *keyword, std::vector &matching_properties) const -{ - const size_t num_properties = m_properties.size(); - StreamString strm; - for (size_t i=0; iGetValue()->GetAsProperties(); - if (properties) - { - properties->Apropos (keyword, matching_properties); - } - else - { - bool match = false; - const char *name = property->GetName().GetCString(); - if (name && ::strcasestr(name, keyword)) - match = true; - else - { - const char *desc = property->GetDescription(); - if (desc && ::strcasestr(desc, keyword)) - match = true; - } - if (match) - { - matching_properties.push_back (property); - } - } + if (match) { + matching_properties.push_back(property); } + } } + } } lldb::OptionValuePropertiesSP -OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx, - const ConstString &name) -{ - lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); - if (option_value_sp) - { - OptionValueProperties *ov_properties = option_value_sp->GetAsProperties (); - if (ov_properties) - return ov_properties->shared_from_this(); - } - return lldb::OptionValuePropertiesSP(); +OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx, + const ConstString &name) { + lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); + if (option_value_sp) { + OptionValueProperties *ov_properties = option_value_sp->GetAsProperties(); + if (ov_properties) + return ov_properties->shared_from_this(); + } + return lldb::OptionValuePropertiesSP(); } - - - diff --git a/lldb/source/Interpreter/OptionValueRegex.cpp b/lldb/source/Interpreter/OptionValueRegex.cpp index ebe7ae2feb9..9a19b842f6e 100644 --- a/lldb/source/Interpreter/OptionValueRegex.cpp +++ b/lldb/source/Interpreter/OptionValueRegex.cpp @@ -18,71 +18,57 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueRegex::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueRegex::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - if (m_regex.IsValid()) - { - const char *regex_text = m_regex.GetText(); - if (regex_text && regex_text[0]) - strm.Printf ("%s", regex_text); - } - else - { - - } + strm.PutCString(" = "); + if (m_regex.IsValid()) { + const char *regex_text = m_regex.GetText(); + if (regex_text && regex_text[0]) + strm.Printf("%s", regex_text); + } else { } + } } -Error -OptionValueRegex::SetValueFromString (llvm::StringRef value, - VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationInvalid: - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - error = OptionValue::SetValueFromString (value, op); - break; +Error OptionValueRegex::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationInvalid: + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + error = OptionValue::SetValueFromString(value, op); + break; - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; - case eVarSetOperationReplace: - case eVarSetOperationAssign: - if (m_regex.Compile (value.str().c_str())) - { - m_value_was_set = true; - NotifyValueChanged(); - } - else - { - char regex_error[1024]; - if (m_regex.GetErrorAsCString(regex_error, sizeof(regex_error))) - error.SetErrorString (regex_error); - else - error.SetErrorStringWithFormat ("regex error %u", m_regex.GetErrorCode()); - } - break; + case eVarSetOperationReplace: + case eVarSetOperationAssign: + if (m_regex.Compile(value.str().c_str())) { + m_value_was_set = true; + NotifyValueChanged(); + } else { + char regex_error[1024]; + if (m_regex.GetErrorAsCString(regex_error, sizeof(regex_error))) + error.SetErrorString(regex_error); + else + error.SetErrorStringWithFormat("regex error %u", + m_regex.GetErrorCode()); } - return error; + break; + } + return error; } - -lldb::OptionValueSP -OptionValueRegex::DeepCopy () const -{ - return OptionValueSP(new OptionValueRegex(m_regex.GetText())); +lldb::OptionValueSP OptionValueRegex::DeepCopy() const { + return OptionValueSP(new OptionValueRegex(m_regex.GetText())); } diff --git a/lldb/source/Interpreter/OptionValueSInt64.cpp b/lldb/source/Interpreter/OptionValueSInt64.cpp index 97cdf10b7c7..3f3844ae402 100644 --- a/lldb/source/Interpreter/OptionValueSInt64.cpp +++ b/lldb/source/Interpreter/OptionValueSInt64.cpp @@ -19,74 +19,62 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueSInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ - //printf ("%p: DumpValue (exe_ctx=%p, strm, mask) m_current_value = %" PRIi64 "\n", this, exe_ctx, m_current_value); +void OptionValueSInt64::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + // printf ("%p: DumpValue (exe_ctx=%p, strm, mask) m_current_value = %" PRIi64 + // "\n", this, exe_ctx, m_current_value); + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + // if (dump_mask & eDumpOptionName) + // DumpQualifiedName (strm); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); -// if (dump_mask & eDumpOptionName) -// DumpQualifiedName (strm); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - strm.Printf ("%" PRIi64, m_current_value); - } + strm.PutCString(" = "); + strm.Printf("%" PRIi64, m_current_value); + } } -Error -OptionValueSInt64::SetValueFromString (llvm::StringRef value_ref, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - bool success = false; - std::string value_str = value_ref.trim().str(); - int64_t value = StringConvert::ToSInt64 (value_str.c_str(), 0, 0, &success); - if (success) - { - if (value >= m_min_value && value <= m_max_value) - { - m_value_was_set = true; - m_current_value = value; - NotifyValueChanged(); - } - else - error.SetErrorStringWithFormat ("%" PRIi64 " is out of range, valid values must be between %" PRIi64 " and %" PRIi64 ".", - value, - m_min_value, - m_max_value); - } - else - { - error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'", - value_ref.str().c_str()); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value_ref, op); - break; +Error OptionValueSInt64::SetValueFromString(llvm::StringRef value_ref, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + bool success = false; + std::string value_str = value_ref.trim().str(); + int64_t value = StringConvert::ToSInt64(value_str.c_str(), 0, 0, &success); + if (success) { + if (value >= m_min_value && value <= m_max_value) { + m_value_was_set = true; + m_current_value = value; + NotifyValueChanged(); + } else + error.SetErrorStringWithFormat( + "%" PRIi64 " is out of range, valid values must be between %" PRIi64 + " and %" PRIi64 ".", + value, m_min_value, m_max_value); + } else { + error.SetErrorStringWithFormat("invalid int64_t string value: '%s'", + value_ref.str().c_str()); } - return error; + } break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value_ref, op); + break; + } + return error; } -lldb::OptionValueSP -OptionValueSInt64::DeepCopy () const -{ - return OptionValueSP(new OptionValueSInt64(*this)); +lldb::OptionValueSP OptionValueSInt64::DeepCopy() const { + return OptionValueSP(new OptionValueSInt64(*this)); } diff --git a/lldb/source/Interpreter/OptionValueString.cpp b/lldb/source/Interpreter/OptionValueString.cpp index 63f006e643f..d6e05da6846 100644 --- a/lldb/source/Interpreter/OptionValueString.cpp +++ b/lldb/source/Interpreter/OptionValueString.cpp @@ -1,4 +1,5 @@ -//===-- OptionValueString.cpp ------------------------------------*- C++ -*-===// +//===-- OptionValueString.cpp ------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -19,171 +20,136 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueString::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueString::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - if (!m_current_value.empty() || m_value_was_set) - { - if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) - { - std::string expanded_escape_value; - Args::ExpandEscapedCharacters(m_current_value.c_str(), expanded_escape_value); - if (dump_mask & eDumpOptionRaw) - strm.Printf ("%s", expanded_escape_value.c_str()); - else - strm.Printf ("\"%s\"", expanded_escape_value.c_str()); - } - else - { - if (dump_mask & eDumpOptionRaw) - strm.Printf ("%s", m_current_value.c_str()); - else - strm.Printf ("\"%s\"", m_current_value.c_str()); - } - } + strm.PutCString(" = "); + if (!m_current_value.empty() || m_value_was_set) { + if (m_options.Test(eOptionEncodeCharacterEscapeSequences)) { + std::string expanded_escape_value; + Args::ExpandEscapedCharacters(m_current_value.c_str(), + expanded_escape_value); + if (dump_mask & eDumpOptionRaw) + strm.Printf("%s", expanded_escape_value.c_str()); + else + strm.Printf("\"%s\"", expanded_escape_value.c_str()); + } else { + if (dump_mask & eDumpOptionRaw) + strm.Printf("%s", m_current_value.c_str()); + else + strm.Printf("\"%s\"", m_current_value.c_str()); + } } + } } -Error -OptionValueString::SetValueFromString (llvm::StringRef value, - VarSetOperationType op) -{ - Error error; +Error OptionValueString::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; - std::string value_str = value.str(); - value = value.trim(); - if (value.size() > 0) - { - switch (value.front()) - { - case '"': - case '\'': - { - if (value.size() <= 1 || value.back() != value.front()) - { - error.SetErrorString("mismatched quotes"); - return error; - } - value = value.drop_front().drop_back(); - } - break; - } - value_str = value.str(); + std::string value_str = value.str(); + value = value.trim(); + if (value.size() > 0) { + switch (value.front()) { + case '"': + case '\'': { + if (value.size() <= 1 || value.back() != value.front()) { + error.SetErrorString("mismatched quotes"); + return error; + } + value = value.drop_front().drop_back(); + } break; } + value_str = value.str(); + } - switch (op) - { - case eVarSetOperationInvalid: - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - if (m_validator) - { - error = m_validator(value_str.c_str(),m_validator_baton); - if (error.Fail()) - return error; - } - error = OptionValue::SetValueFromString (value, op); - break; + switch (op) { + case eVarSetOperationInvalid: + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + if (m_validator) { + error = m_validator(value_str.c_str(), m_validator_baton); + if (error.Fail()) + return error; + } + error = OptionValue::SetValueFromString(value, op); + break; - case eVarSetOperationAppend: - { - std::string new_value(m_current_value); - if (value.size() > 0) - { - if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) - { - std::string str; - Args::EncodeEscapeSequences (value_str.c_str(), str); - new_value.append(str); - } - else - new_value.append(value); - } - if (m_validator) - { - error = m_validator(new_value.c_str(),m_validator_baton); - if (error.Fail()) - return error; - } - m_current_value.assign(new_value); - NotifyValueChanged(); - } - break; + case eVarSetOperationAppend: { + std::string new_value(m_current_value); + if (value.size() > 0) { + if (m_options.Test(eOptionEncodeCharacterEscapeSequences)) { + std::string str; + Args::EncodeEscapeSequences(value_str.c_str(), str); + new_value.append(str); + } else + new_value.append(value); + } + if (m_validator) { + error = m_validator(new_value.c_str(), m_validator_baton); + if (error.Fail()) + return error; + } + m_current_value.assign(new_value); + NotifyValueChanged(); + } break; - case eVarSetOperationClear: - Clear (); - NotifyValueChanged(); - break; + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; - case eVarSetOperationReplace: - case eVarSetOperationAssign: - if (m_validator) - { - error = m_validator(value_str.c_str(), m_validator_baton); - if (error.Fail()) - return error; - } - m_value_was_set = true; - if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) - { - Args::EncodeEscapeSequences (value_str.c_str(), m_current_value); - } - else - { - SetCurrentValue (value_str.c_str()); - } - NotifyValueChanged(); - break; + case eVarSetOperationReplace: + case eVarSetOperationAssign: + if (m_validator) { + error = m_validator(value_str.c_str(), m_validator_baton); + if (error.Fail()) + return error; } - return error; + m_value_was_set = true; + if (m_options.Test(eOptionEncodeCharacterEscapeSequences)) { + Args::EncodeEscapeSequences(value_str.c_str(), m_current_value); + } else { + SetCurrentValue(value_str.c_str()); + } + NotifyValueChanged(); + break; + } + return error; } - -lldb::OptionValueSP -OptionValueString::DeepCopy () const -{ - return OptionValueSP(new OptionValueString(*this)); +lldb::OptionValueSP OptionValueString::DeepCopy() const { + return OptionValueSP(new OptionValueString(*this)); } -Error -OptionValueString::SetCurrentValue (const char *value) -{ - if (m_validator) - { - Error error(m_validator(value,m_validator_baton)); - if (error.Fail()) - return error; - } - if (value && value[0]) - m_current_value.assign (value); - else - m_current_value.clear(); - return Error(); +Error OptionValueString::SetCurrentValue(const char *value) { + if (m_validator) { + Error error(m_validator(value, m_validator_baton)); + if (error.Fail()) + return error; + } + if (value && value[0]) + m_current_value.assign(value); + else + m_current_value.clear(); + return Error(); } -Error -OptionValueString::AppendToCurrentValue (const char *value) -{ - if (value && value[0]) - { - if (m_validator) - { - std::string new_value(m_current_value); - new_value.append(value); - Error error(m_validator(value,m_validator_baton)); - if (error.Fail()) - return error; - m_current_value.assign(new_value); - } - else - m_current_value.append (value); - } - return Error(); +Error OptionValueString::AppendToCurrentValue(const char *value) { + if (value && value[0]) { + if (m_validator) { + std::string new_value(m_current_value); + new_value.append(value); + Error error(m_validator(value, m_validator_baton)); + if (error.Fail()) + return error; + m_current_value.assign(new_value); + } else + m_current_value.append(value); + } + return Error(); } diff --git a/lldb/source/Interpreter/OptionValueUInt64.cpp b/lldb/source/Interpreter/OptionValueUInt64.cpp index b414802b963..8296431fcc9 100644 --- a/lldb/source/Interpreter/OptionValueUInt64.cpp +++ b/lldb/source/Interpreter/OptionValueUInt64.cpp @@ -1,4 +1,5 @@ -//===-- OptionValueUInt64.cpp ------------------------------------*- C++ -*-===// +//===-- OptionValueUInt64.cpp ------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -19,74 +20,61 @@ using namespace lldb; using namespace lldb_private; -lldb::OptionValueSP -OptionValueUInt64::Create (const char *value_cstr, Error &error) -{ - lldb::OptionValueSP value_sp (new OptionValueUInt64()); - error = value_sp->SetValueFromString (value_cstr); - if (error.Fail()) - value_sp.reset(); - return value_sp; +lldb::OptionValueSP OptionValueUInt64::Create(const char *value_cstr, + Error &error) { + lldb::OptionValueSP value_sp(new OptionValueUInt64()); + error = value_sp->SetValueFromString(value_cstr); + if (error.Fail()) + value_sp.reset(); + return value_sp; } - -void -OptionValueUInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueUInt64::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - strm.Printf ("%" PRIu64, m_current_value); - } + strm.PutCString(" = "); + strm.Printf("%" PRIu64, m_current_value); + } } -Error -OptionValueUInt64::SetValueFromString (llvm::StringRef value_ref, VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear (); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - bool success = false; - std::string value_str = value_ref.trim().str(); - uint64_t value = StringConvert::ToUInt64 (value_str.c_str(), 0, 0, &success); - if (success) - { - m_value_was_set = true; - m_current_value = value; - NotifyValueChanged(); - } - else - { - error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_str.c_str()); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value_ref, op); - break; +Error OptionValueUInt64::SetValueFromString(llvm::StringRef value_ref, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + bool success = false; + std::string value_str = value_ref.trim().str(); + uint64_t value = StringConvert::ToUInt64(value_str.c_str(), 0, 0, &success); + if (success) { + m_value_was_set = true; + m_current_value = value; + NotifyValueChanged(); + } else { + error.SetErrorStringWithFormat("invalid uint64_t string value: '%s'", + value_str.c_str()); } - return error; -} + } break; -lldb::OptionValueSP -OptionValueUInt64::DeepCopy () const -{ - return OptionValueSP(new OptionValueUInt64(*this)); + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value_ref, op); + break; + } + return error; } +lldb::OptionValueSP OptionValueUInt64::DeepCopy() const { + return OptionValueSP(new OptionValueUInt64(*this)); +} diff --git a/lldb/source/Interpreter/OptionValueUUID.cpp b/lldb/source/Interpreter/OptionValueUUID.cpp index b16a9eb7e99..18132238118 100644 --- a/lldb/source/Interpreter/OptionValueUUID.cpp +++ b/lldb/source/Interpreter/OptionValueUUID.cpp @@ -21,105 +21,87 @@ using namespace lldb; using namespace lldb_private; -void -OptionValueUUID::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ +void OptionValueUUID::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.Printf ("(%s)", GetTypeAsCString ()); - if (dump_mask & eDumpOptionValue) - { - if (dump_mask & eDumpOptionType) - strm.PutCString (" = "); - m_uuid.Dump (&strm); - } + strm.PutCString(" = "); + m_uuid.Dump(&strm); + } } -Error -OptionValueUUID::SetValueFromString (llvm::StringRef value, - VarSetOperationType op) -{ - Error error; - switch (op) - { - case eVarSetOperationClear: - Clear(); - NotifyValueChanged(); - break; - - case eVarSetOperationReplace: - case eVarSetOperationAssign: - { - if (m_uuid.SetFromCString(value.str().c_str()) == 0) - error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value.str().c_str()); - else - { - m_value_was_set = true; - NotifyValueChanged(); - } - } - break; - - case eVarSetOperationInsertBefore: - case eVarSetOperationInsertAfter: - case eVarSetOperationRemove: - case eVarSetOperationAppend: - case eVarSetOperationInvalid: - error = OptionValue::SetValueFromString (value, op); - break; +Error OptionValueUUID::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Error error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: { + if (m_uuid.SetFromCString(value.str().c_str()) == 0) + error.SetErrorStringWithFormat("invalid uuid string value '%s'", + value.str().c_str()); + else { + m_value_was_set = true; + NotifyValueChanged(); } - return error; + } break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; } -lldb::OptionValueSP -OptionValueUUID::DeepCopy () const -{ - return OptionValueSP(new OptionValueUUID(*this)); +lldb::OptionValueSP OptionValueUUID::DeepCopy() const { + return OptionValueSP(new OptionValueUUID(*this)); } -size_t -OptionValueUUID::AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - matches.Clear(); - ExecutionContext exe_ctx(interpreter.GetExecutionContext()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) - { - UUID::ValueType uuid_bytes; - const size_t num_bytes_decoded = UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, nullptr); - for (size_t i=0; iGetImages().GetModuleAtIndex(i)); - if (module_sp) - { - const UUID &module_uuid = module_sp->GetUUID(); - if (module_uuid.IsValid()) - { - bool add_uuid = false; - if (num_bytes_decoded == 0) - add_uuid = true; - else - add_uuid = ::memcmp(module_uuid.GetBytes(), uuid_bytes, num_bytes_decoded) == 0; - if (add_uuid) - { - std::string uuid_str; - uuid_str = module_uuid.GetAsString(); - if (!uuid_str.empty()) - matches.AppendString(uuid_str.c_str()); - } - } - } +size_t OptionValueUUID::AutoComplete(CommandInterpreter &interpreter, + const char *s, int match_start_point, + int max_return_elements, + bool &word_complete, StringList &matches) { + word_complete = false; + matches.Clear(); + ExecutionContext exe_ctx(interpreter.GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + UUID::ValueType uuid_bytes; + const size_t num_bytes_decoded = + UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, nullptr); + for (size_t i = 0; i < num_modules; ++i) { + ModuleSP module_sp(target->GetImages().GetModuleAtIndex(i)); + if (module_sp) { + const UUID &module_uuid = module_sp->GetUUID(); + if (module_uuid.IsValid()) { + bool add_uuid = false; + if (num_bytes_decoded == 0) + add_uuid = true; + else + add_uuid = ::memcmp(module_uuid.GetBytes(), uuid_bytes, + num_bytes_decoded) == 0; + if (add_uuid) { + std::string uuid_str; + uuid_str = module_uuid.GetAsString(); + if (!uuid_str.empty()) + matches.AppendString(uuid_str.c_str()); } + } } + } } - return matches.GetSize(); + } + return matches.GetSize(); } - diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp index a868b251c55..91f1a5f937d 100644 --- a/lldb/source/Interpreter/Options.cpp +++ b/lldb/source/Interpreter/Options.cpp @@ -18,11 +18,11 @@ // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/CommandObject.h" -#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Core/StreamString.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -31,1086 +31,938 @@ using namespace lldb_private; //------------------------------------------------------------------------- // Options //------------------------------------------------------------------------- -Options::Options () : - m_getopt_table () -{ - BuildValidOptionSets(); -} +Options::Options() : m_getopt_table() { BuildValidOptionSets(); } -Options::~Options () -{ -} +Options::~Options() {} -void -Options::NotifyOptionParsingStarting(ExecutionContext *execution_context) -{ - m_seen_options.clear(); - // Let the subclass reset its option values - OptionParsingStarting(execution_context); +void Options::NotifyOptionParsingStarting(ExecutionContext *execution_context) { + m_seen_options.clear(); + // Let the subclass reset its option values + OptionParsingStarting(execution_context); } -Error -Options::NotifyOptionParsingFinished(ExecutionContext *execution_context) -{ - return OptionParsingFinished(execution_context); +Error Options::NotifyOptionParsingFinished( + ExecutionContext *execution_context) { + return OptionParsingFinished(execution_context); } -void -Options::OptionSeen (int option_idx) -{ - m_seen_options.insert (option_idx); -} +void Options::OptionSeen(int option_idx) { m_seen_options.insert(option_idx); } // Returns true is set_a is a subset of set_b; Otherwise returns false. -bool -Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b) -{ - bool is_a_subset = true; - OptionSet::const_iterator pos_a; - OptionSet::const_iterator pos_b; +bool Options::IsASubset(const OptionSet &set_a, const OptionSet &set_b) { + bool is_a_subset = true; + OptionSet::const_iterator pos_a; + OptionSet::const_iterator pos_b; - // set_a is a subset of set_b if every member of set_a is also a member of set_b + // set_a is a subset of set_b if every member of set_a is also a member of + // set_b - for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) - { - pos_b = set_b.find(*pos_a); - if (pos_b == set_b.end()) - is_a_subset = false; - } + for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) { + pos_b = set_b.find(*pos_a); + if (pos_b == set_b.end()) + is_a_subset = false; + } - return is_a_subset; + return is_a_subset; } -// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) } - -size_t -Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs) -{ - size_t num_diffs = 0; - OptionSet::const_iterator pos_a; - OptionSet::const_iterator pos_b; - - for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) - { - pos_b = set_b.find(*pos_a); - if (pos_b == set_b.end()) - { - ++num_diffs; - diffs.insert(*pos_a); - } +// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && +// !ElementOf (x, set_b) } + +size_t Options::OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b, + OptionSet &diffs) { + size_t num_diffs = 0; + OptionSet::const_iterator pos_a; + OptionSet::const_iterator pos_b; + + for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) { + pos_b = set_b.find(*pos_a); + if (pos_b == set_b.end()) { + ++num_diffs; + diffs.insert(*pos_a); } + } - return num_diffs; + return num_diffs; } -// Returns the union of set_a and set_b. Does not put duplicate members into the union. +// Returns the union of set_a and set_b. Does not put duplicate members into +// the union. -void -Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set) -{ - OptionSet::const_iterator pos; - OptionSet::iterator pos_union; +void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b, + OptionSet &union_set) { + OptionSet::const_iterator pos; + OptionSet::iterator pos_union; - // Put all the elements of set_a into the union. + // Put all the elements of set_a into the union. - for (pos = set_a.begin(); pos != set_a.end(); ++pos) - union_set.insert(*pos); + for (pos = set_a.begin(); pos != set_a.end(); ++pos) + union_set.insert(*pos); - // Put all the elements of set_b that are not already there into the union. - for (pos = set_b.begin(); pos != set_b.end(); ++pos) - { - pos_union = union_set.find(*pos); - if (pos_union == union_set.end()) - union_set.insert(*pos); - } + // Put all the elements of set_b that are not already there into the union. + for (pos = set_b.begin(); pos != set_b.end(); ++pos) { + pos_union = union_set.find(*pos); + if (pos_union == union_set.end()) + union_set.insert(*pos); + } } -bool -Options::VerifyOptions (CommandReturnObject &result) -{ - bool options_are_valid = false; - - int num_levels = GetRequiredOptions().size(); - if (num_levels) - { - for (int i = 0; i < num_levels && !options_are_valid; ++i) - { - // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i] - // (i.e. all the required options at this level are a subset of m_seen_options); AND - // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of - // m_seen_options are in the set of optional options at this level. - - // Check to see if all of m_required_options[i] are a subset of m_seen_options - if (IsASubset (GetRequiredOptions()[i], m_seen_options)) - { - // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]} - OptionSet remaining_options; - OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options); - // Check to see if remaining_options is a subset of m_optional_options[i] - if (IsASubset (remaining_options, GetOptionalOptions()[i])) - options_are_valid = true; - } - } - } - else - { - options_are_valid = true; - } - - if (options_are_valid) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("invalid combination of options for the given command"); - result.SetStatus (eReturnStatusFailed); +bool Options::VerifyOptions(CommandReturnObject &result) { + bool options_are_valid = false; + + int num_levels = GetRequiredOptions().size(); + if (num_levels) { + for (int i = 0; i < num_levels && !options_are_valid; ++i) { + // This is the correct set of options if: 1). m_seen_options contains all + // of m_required_options[i] + // (i.e. all the required options at this level are a subset of + // m_seen_options); AND + // 2). { m_seen_options - m_required_options[i] is a subset of + // m_options_options[i] (i.e. all the rest of + // m_seen_options are in the set of optional options at this level. + + // Check to see if all of m_required_options[i] are a subset of + // m_seen_options + if (IsASubset(GetRequiredOptions()[i], m_seen_options)) { + // Construct the set difference: remaining_options = {m_seen_options} - + // {m_required_options[i]} + OptionSet remaining_options; + OptionsSetDiff(m_seen_options, GetRequiredOptions()[i], + remaining_options); + // Check to see if remaining_options is a subset of + // m_optional_options[i] + if (IsASubset(remaining_options, GetOptionalOptions()[i])) + options_are_valid = true; + } } - - return options_are_valid; + } else { + options_are_valid = true; + } + + if (options_are_valid) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("invalid combination of options for the given command"); + result.SetStatus(eReturnStatusFailed); + } + + return options_are_valid; } -// This is called in the Options constructor, though we could call it lazily if that ends up being +// This is called in the Options constructor, though we could call it lazily if +// that ends up being // a performance problem. -void -Options::BuildValidOptionSets () -{ - // Check to see if we already did this. - if (m_required_options.size() != 0) - return; - - // Check to see if there are any options. - int num_options = NumCommandOptions (); - if (num_options == 0) - return; - - const OptionDefinition *opt_defs = GetDefinitions(); - m_required_options.resize(1); - m_optional_options.resize(1); - - // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS... - - uint32_t num_option_sets = 0; - - for (int i = 0; i < num_options; i++) - { - uint32_t this_usage_mask = opt_defs[i].usage_mask; - if (this_usage_mask == LLDB_OPT_SET_ALL) - { - if (num_option_sets == 0) - num_option_sets = 1; - } - else - { - for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) - { - if (this_usage_mask & (1 << j)) - { - if (num_option_sets <= j) - num_option_sets = j + 1; - } - } +void Options::BuildValidOptionSets() { + // Check to see if we already did this. + if (m_required_options.size() != 0) + return; + + // Check to see if there are any options. + int num_options = NumCommandOptions(); + if (num_options == 0) + return; + + const OptionDefinition *opt_defs = GetDefinitions(); + m_required_options.resize(1); + m_optional_options.resize(1); + + // First count the number of option sets we've got. Ignore + // LLDB_ALL_OPTION_SETS... + + uint32_t num_option_sets = 0; + + for (int i = 0; i < num_options; i++) { + uint32_t this_usage_mask = opt_defs[i].usage_mask; + if (this_usage_mask == LLDB_OPT_SET_ALL) { + if (num_option_sets == 0) + num_option_sets = 1; + } else { + for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) { + if (this_usage_mask & (1 << j)) { + if (num_option_sets <= j) + num_option_sets = j + 1; } + } } - - if (num_option_sets > 0) - { - m_required_options.resize(num_option_sets); - m_optional_options.resize(num_option_sets); - - for (int i = 0; i < num_options; ++i) - { - for (uint32_t j = 0; j < num_option_sets; j++) - { - if (opt_defs[i].usage_mask & 1 << j) - { - if (opt_defs[i].required) - m_required_options[j].insert(opt_defs[i].short_option); - else - m_optional_options[j].insert(opt_defs[i].short_option); - } - } + } + + if (num_option_sets > 0) { + m_required_options.resize(num_option_sets); + m_optional_options.resize(num_option_sets); + + for (int i = 0; i < num_options; ++i) { + for (uint32_t j = 0; j < num_option_sets; j++) { + if (opt_defs[i].usage_mask & 1 << j) { + if (opt_defs[i].required) + m_required_options[j].insert(opt_defs[i].short_option); + else + m_optional_options[j].insert(opt_defs[i].short_option); } + } } + } } -uint32_t -Options::NumCommandOptions () -{ - const OptionDefinition *opt_defs = GetDefinitions (); - if (opt_defs == nullptr) - return 0; - - int i = 0; - - if (opt_defs != nullptr) - { - while (opt_defs[i].long_option != nullptr) - ++i; - } +uint32_t Options::NumCommandOptions() { + const OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs == nullptr) + return 0; - return i; -} + int i = 0; -Option * -Options::GetLongOptions () -{ - // Check to see if this has already been done. - if (m_getopt_table.empty()) - { - // Check to see if there are any options. - const uint32_t num_options = NumCommandOptions(); - if (num_options == 0) - return nullptr; - - uint32_t i; - const OptionDefinition *opt_defs = GetDefinitions(); - - std::map option_seen; - - m_getopt_table.resize(num_options + 1); - for (i = 0; i < num_options; ++i) - { - const int short_opt = opt_defs[i].short_option; - - m_getopt_table[i].definition = &opt_defs[i]; - m_getopt_table[i].flag = nullptr; - m_getopt_table[i].val = short_opt; - - if (option_seen.find(short_opt) == option_seen.end()) - { - option_seen[short_opt] = i; - } - else if (short_opt) - { - m_getopt_table[i].val = 0; - std::map::const_iterator pos = option_seen.find(short_opt); - StreamString strm; - if (isprint8(short_opt)) - Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option -%c that conflicts with option[%u] --%s, short option won't be used for --%s\n", - i, - opt_defs[i].long_option, - short_opt, - pos->second, - m_getopt_table[pos->second].definition->long_option, - opt_defs[i].long_option); - else - Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n", - i, - opt_defs[i].long_option, - short_opt, - pos->second, - m_getopt_table[pos->second].definition->long_option, - opt_defs[i].long_option); - } - } + if (opt_defs != nullptr) { + while (opt_defs[i].long_option != nullptr) + ++i; + } - //getopt_long_only requires a NULL final entry in the table: + return i; +} - m_getopt_table[i].definition = nullptr; - m_getopt_table[i].flag = nullptr; - m_getopt_table[i].val = 0; - } +Option *Options::GetLongOptions() { + // Check to see if this has already been done. + if (m_getopt_table.empty()) { + // Check to see if there are any options. + const uint32_t num_options = NumCommandOptions(); + if (num_options == 0) + return nullptr; - if (m_getopt_table.empty()) - return nullptr; + uint32_t i; + const OptionDefinition *opt_defs = GetDefinitions(); - return &m_getopt_table.front(); -} + std::map option_seen; + + m_getopt_table.resize(num_options + 1); + for (i = 0; i < num_options; ++i) { + const int short_opt = opt_defs[i].short_option; + + m_getopt_table[i].definition = &opt_defs[i]; + m_getopt_table[i].flag = nullptr; + m_getopt_table[i].val = short_opt; + + if (option_seen.find(short_opt) == option_seen.end()) { + option_seen[short_opt] = i; + } else if (short_opt) { + m_getopt_table[i].val = 0; + std::map::const_iterator pos = + option_seen.find(short_opt); + StreamString strm; + if (isprint8(short_opt)) + Host::SystemLog(Host::eSystemLogError, + "option[%u] --%s has a short option -%c that " + "conflicts with option[%u] --%s, short option won't " + "be used for --%s\n", + i, opt_defs[i].long_option, short_opt, pos->second, + m_getopt_table[pos->second].definition->long_option, + opt_defs[i].long_option); + else + Host::SystemLog(Host::eSystemLogError, + "option[%u] --%s has a short option 0x%x that " + "conflicts with option[%u] --%s, short option won't " + "be used for --%s\n", + i, opt_defs[i].long_option, short_opt, pos->second, + m_getopt_table[pos->second].definition->long_option, + opt_defs[i].long_option); + } + } + // getopt_long_only requires a NULL final entry in the table: -// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is -// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on -// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces, -// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each -// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. + m_getopt_table[i].definition = nullptr; + m_getopt_table[i].flag = nullptr; + m_getopt_table[i].val = 0; + } + if (m_getopt_table.empty()) + return nullptr; -void -Options::OutputFormattedUsageText -( - Stream &strm, - const OptionDefinition &option_def, - uint32_t output_max_columns -) -{ - std::string actual_text; - if (option_def.validator) - { - const char *condition = option_def.validator->ShortConditionString(); - if (condition) - { - actual_text = "["; - actual_text.append(condition); - actual_text.append("] "); - } - } - actual_text.append(option_def.usage_text); + return &m_getopt_table.front(); +} - // Will it all fit on one line? +// This function takes INDENT, which tells how many spaces to output at the +// front of each line; SPACES, which is +// a string containing 80 spaces; and TEXT, which is the text that is to be +// output. It outputs the text, on +// multiple lines if necessary, to RESULT, with INDENT spaces at the front of +// each line. It breaks lines on spaces, +// tabs or newlines, shortening the line if necessary to not break in the middle +// of a word. It assumes that each +// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. - if (static_cast(actual_text.length() + strm.GetIndentLevel()) < output_max_columns) - { - // Output it as a single line. - strm.Indent (actual_text.c_str()); - strm.EOL(); +void Options::OutputFormattedUsageText(Stream &strm, + const OptionDefinition &option_def, + uint32_t output_max_columns) { + std::string actual_text; + if (option_def.validator) { + const char *condition = option_def.validator->ShortConditionString(); + if (condition) { + actual_text = "["; + actual_text.append(condition); + actual_text.append("] "); } - else - { - // We need to break it up into multiple lines. - - int text_width = output_max_columns - strm.GetIndentLevel() - 1; - int start = 0; - int end = start; - int final_end = actual_text.length(); - int sub_len; - - while (end < final_end) - { - // Don't start the 'text' on a space, since we're already outputting the indentation. - while ((start < final_end) && (actual_text[start] == ' ')) - start++; - - end = start + text_width; - if (end > final_end) - end = final_end; - else - { - // If we're not at the end of the text, make sure we break the line on white space. - while (end > start - && actual_text[end] != ' ' && actual_text[end] != '\t' && actual_text[end] != '\n') - end--; - } + } + actual_text.append(option_def.usage_text); + + // Will it all fit on one line? + + if (static_cast(actual_text.length() + strm.GetIndentLevel()) < + output_max_columns) { + // Output it as a single line. + strm.Indent(actual_text.c_str()); + strm.EOL(); + } else { + // We need to break it up into multiple lines. + + int text_width = output_max_columns - strm.GetIndentLevel() - 1; + int start = 0; + int end = start; + int final_end = actual_text.length(); + int sub_len; + + while (end < final_end) { + // Don't start the 'text' on a space, since we're already outputting the + // indentation. + while ((start < final_end) && (actual_text[start] == ' ')) + start++; + + end = start + text_width; + if (end > final_end) + end = final_end; + else { + // If we're not at the end of the text, make sure we break the line on + // white space. + while (end > start && actual_text[end] != ' ' && + actual_text[end] != '\t' && actual_text[end] != '\n') + end--; + } - sub_len = end - start; - if (start != 0) - strm.EOL(); - strm.Indent(); - assert (start < final_end); - assert (start + sub_len <= final_end); - strm.Write(actual_text.c_str() + start, sub_len); - start = end + 1; - } + sub_len = end - start; + if (start != 0) strm.EOL(); + strm.Indent(); + assert(start < final_end); + assert(start + sub_len <= final_end); + strm.Write(actual_text.c_str() + start, sub_len); + start = end + 1; } + strm.EOL(); + } } -bool -Options::SupportsLongOption (const char *long_option) -{ - if (long_option && long_option[0]) - { - const OptionDefinition *opt_defs = GetDefinitions (); - if (opt_defs) - { - const char *long_option_name = long_option; - if (long_option[0] == '-' && long_option[1] == '-') - long_option_name += 2; - - for (uint32_t i = 0; opt_defs[i].long_option; ++i) - { - if (strcmp(opt_defs[i].long_option, long_option_name) == 0) - return true; - } - } +bool Options::SupportsLongOption(const char *long_option) { + if (long_option && long_option[0]) { + const OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs) { + const char *long_option_name = long_option; + if (long_option[0] == '-' && long_option[1] == '-') + long_option_name += 2; + + for (uint32_t i = 0; opt_defs[i].long_option; ++i) { + if (strcmp(opt_defs[i].long_option, long_option_name) == 0) + return true; + } } - return false; + } + return false; } -enum OptionDisplayType -{ - eDisplayBestOption, - eDisplayShortOption, - eDisplayLongOption +enum OptionDisplayType { + eDisplayBestOption, + eDisplayShortOption, + eDisplayLongOption }; -static bool -PrintOption (const OptionDefinition &opt_def, - OptionDisplayType display_type, - const char *header, - const char *footer, - bool show_optional, - Stream &strm) -{ - const bool has_short_option = isprint8(opt_def.short_option) != 0; - - if (display_type == eDisplayShortOption && !has_short_option) - return false; - - if (header && header[0]) - strm.PutCString(header); - - if (show_optional && !opt_def.required) +static bool PrintOption(const OptionDefinition &opt_def, + OptionDisplayType display_type, const char *header, + const char *footer, bool show_optional, Stream &strm) { + const bool has_short_option = isprint8(opt_def.short_option) != 0; + + if (display_type == eDisplayShortOption && !has_short_option) + return false; + + if (header && header[0]) + strm.PutCString(header); + + if (show_optional && !opt_def.required) strm.PutChar('['); - const bool show_short_option = has_short_option && display_type != eDisplayLongOption; - if (show_short_option) - strm.Printf ("-%c", opt_def.short_option); - else - strm.Printf ("--%s", opt_def.long_option); - switch (opt_def.option_has_arg) - { - case OptionParser::eNoArgument: - break; - case OptionParser::eRequiredArgument: - strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type)); - break; - - case OptionParser::eOptionalArgument: - strm.Printf ("%s[<%s>]", - show_short_option ? "" : "=", - CommandObject::GetArgumentName (opt_def.argument_type)); - break; - } - if (show_optional && !opt_def.required) - strm.PutChar(']'); - if (footer && footer[0]) - strm.PutCString(footer); - return true; + const bool show_short_option = + has_short_option && display_type != eDisplayLongOption; + if (show_short_option) + strm.Printf("-%c", opt_def.short_option); + else + strm.Printf("--%s", opt_def.long_option); + switch (opt_def.option_has_arg) { + case OptionParser::eNoArgument: + break; + case OptionParser::eRequiredArgument: + strm.Printf(" <%s>", CommandObject::GetArgumentName(opt_def.argument_type)); + break; + + case OptionParser::eOptionalArgument: + strm.Printf("%s[<%s>]", show_short_option ? "" : "=", + CommandObject::GetArgumentName(opt_def.argument_type)); + break; + } + if (show_optional && !opt_def.required) + strm.PutChar(']'); + if (footer && footer[0]) + strm.PutCString(footer); + return true; } -void -Options::GenerateOptionUsage -( - Stream &strm, - CommandObject *cmd, - uint32_t screen_width -) -{ - const bool only_print_args = cmd->IsDashDashCommand(); +void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, + uint32_t screen_width) { + const bool only_print_args = cmd->IsDashDashCommand(); - const OptionDefinition *opt_defs = GetDefinitions(); - const uint32_t save_indent_level = strm.GetIndentLevel(); - const char *name; + const OptionDefinition *opt_defs = GetDefinitions(); + const uint32_t save_indent_level = strm.GetIndentLevel(); + const char *name; - StreamString arguments_str; + StreamString arguments_str; - if (cmd) - { - name = cmd->GetCommandName(); - cmd->GetFormattedCommandArguments (arguments_str); - } - else - name = ""; + if (cmd) { + name = cmd->GetCommandName(); + cmd->GetFormattedCommandArguments(arguments_str); + } else + name = ""; - strm.PutCString ("\nCommand Options Usage:\n"); + strm.PutCString("\nCommand Options Usage:\n"); - strm.IndentMore(2); + strm.IndentMore(2); - // First, show each usage level set of options, e.g. [options-for-level-0] - // [options-for-level-1] - // etc. + // First, show each usage level set of options, e.g. + // [options-for-level-0] + // + // [options-for-level-1] + // etc. - const uint32_t num_options = NumCommandOptions(); - if (num_options == 0) - return; - - uint32_t num_option_sets = GetRequiredOptions().size(); - - uint32_t i; - - if (!only_print_args) - { - for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) - { - uint32_t opt_set_mask; - - opt_set_mask = 1 << opt_set; - if (opt_set > 0) - strm.Printf ("\n"); - strm.Indent (name); - - // Different option sets may require different args. - StreamString args_str; - if (cmd) - cmd->GetFormattedCommandArguments(args_str, opt_set_mask); - - // First go through and print all options that take no arguments as - // a single string. If a command has "-a" "-b" and "-c", this will show - // up as [-abc] - - std::set options; - std::set::const_iterator options_pos, options_end; - for (i = 0; i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) - { - // Add current option to the end of out_stream. - - if (opt_defs[i].required == true && - opt_defs[i].option_has_arg == OptionParser::eNoArgument) - { - options.insert (opt_defs[i].short_option); - } - } - } + const uint32_t num_options = NumCommandOptions(); + if (num_options == 0) + return; - if (options.empty() == false) - { - // We have some required options with no arguments - strm.PutCString(" -"); - for (i=0; i<2; ++i) - for (options_pos = options.begin(), options_end = options.end(); - options_pos != options_end; - ++options_pos) - { - if (i==0 && ::islower (*options_pos)) - continue; - if (i==1 && ::isupper (*options_pos)) - continue; - strm << (char)*options_pos; - } - } + uint32_t num_option_sets = GetRequiredOptions().size(); - for (i = 0, options.clear(); i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) - { - // Add current option to the end of out_stream. - - if (opt_defs[i].required == false && - opt_defs[i].option_has_arg == OptionParser::eNoArgument) - { - options.insert (opt_defs[i].short_option); - } - } - } + uint32_t i; - if (options.empty() == false) - { - // We have some required options with no arguments - strm.PutCString(" [-"); - for (i=0; i<2; ++i) - for (options_pos = options.begin(), options_end = options.end(); - options_pos != options_end; - ++options_pos) - { - if (i==0 && ::islower (*options_pos)) - continue; - if (i==1 && ::isupper (*options_pos)) - continue; - strm << (char)*options_pos; - } - strm.PutChar(']'); - } + if (!only_print_args) { + for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) { + uint32_t opt_set_mask; - // First go through and print the required options (list them up front). - - for (i = 0; i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) - { - if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) - PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); - } - } + opt_set_mask = 1 << opt_set; + if (opt_set > 0) + strm.Printf("\n"); + strm.Indent(name); - // Now go through again, and this time only print the optional options. + // Different option sets may require different args. + StreamString args_str; + if (cmd) + cmd->GetFormattedCommandArguments(args_str, opt_set_mask); - for (i = 0; i < num_options; ++i) - { - if (opt_defs[i].usage_mask & opt_set_mask) - { - // Add current option to the end of out_stream. + // First go through and print all options that take no arguments as + // a single string. If a command has "-a" "-b" and "-c", this will show + // up as [-abc] - if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) - PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm); - } - } - - if (args_str.GetSize() > 0) - { - if (cmd->WantsRawCommandString() && !only_print_args) - strm.Printf(" --"); - - strm.Printf (" %s", args_str.GetData()); - if (only_print_args) - break; - } - } - } - - if (cmd && - (only_print_args || cmd->WantsRawCommandString()) && - arguments_str.GetSize() > 0) - { - if (!only_print_args) strm.PutChar('\n'); - strm.Indent(name); - strm.Printf(" %s", arguments_str.GetData()); - } - - strm.Printf ("\n\n"); + std::set options; + std::set::const_iterator options_pos, options_end; + for (i = 0; i < num_options; ++i) { + if (opt_defs[i].usage_mask & opt_set_mask && + isprint8(opt_defs[i].short_option)) { + // Add current option to the end of out_stream. - if (!only_print_args) - { - // Now print out all the detailed information about the various options: long form, short form and help text: - // -short ( --long_name ) - // help text - - // This variable is used to keep track of which options' info we've printed out, because some options can be in - // more than one usage level, but we only want to print the long form of its information once. - - std::multimap options_seen; - strm.IndentMore (5); - - // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option) - // when writing out detailed help for each option. - - for (i = 0; i < num_options; ++i) - options_seen.insert(std::make_pair(opt_defs[i].short_option, i)); - - // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option - // and write out the detailed help information for that option. - - bool first_option_printed = false;; - - for (auto pos : options_seen) - { - i = pos.second; - //Print out the help information for this option. - - // Put a newline separation between arguments - if (first_option_printed) - strm.EOL(); - else - first_option_printed = true; - - CommandArgumentType arg_type = opt_defs[i].argument_type; - - StreamString arg_name_str; - arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type)); - - strm.Indent (); - if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) - { - PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm); - PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); - } - else - { - // Short option is not printable, just print long option - PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm); - } - strm.EOL(); - - strm.IndentMore (5); - - if (opt_defs[i].usage_text) - OutputFormattedUsageText (strm, - opt_defs[i], - screen_width); - if (opt_defs[i].enum_values != nullptr) - { - strm.Indent (); - strm.Printf("Values: "); - for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++) - { - if (k == 0) - strm.Printf("%s", opt_defs[i].enum_values[k].string_value); - else - strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); - } - strm.EOL(); - } - strm.IndentLess (5); + if (opt_defs[i].required == true && + opt_defs[i].option_has_arg == OptionParser::eNoArgument) { + options.insert(opt_defs[i].short_option); + } } - } + } - // Restore the indent level - strm.SetIndentLevel (save_indent_level); -} + if (options.empty() == false) { + // We have some required options with no arguments + strm.PutCString(" -"); + for (i = 0; i < 2; ++i) + for (options_pos = options.begin(), options_end = options.end(); + options_pos != options_end; ++options_pos) { + if (i == 0 && ::islower(*options_pos)) + continue; + if (i == 1 && ::isupper(*options_pos)) + continue; + strm << (char)*options_pos; + } + } -// This function is called when we have been given a potentially incomplete set of -// options, such as when an alias has been defined (more options might be added at -// at the time the alias is invoked). We need to verify that the options in the set -// m_seen_options are all part of a set that may be used together, but m_seen_options -// may be missing some of the "required" options. + for (i = 0, options.clear(); i < num_options; ++i) { + if (opt_defs[i].usage_mask & opt_set_mask && + isprint8(opt_defs[i].short_option)) { + // Add current option to the end of out_stream. -bool -Options::VerifyPartialOptions (CommandReturnObject &result) -{ - bool options_are_valid = false; - - int num_levels = GetRequiredOptions().size(); - if (num_levels) - { - for (int i = 0; i < num_levels && !options_are_valid; ++i) - { - // In this case we are treating all options as optional rather than required. - // Therefore a set of options is correct if m_seen_options is a subset of the - // union of m_required_options and m_optional_options. - OptionSet union_set; - OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set); - if (IsASubset (m_seen_options, union_set)) - options_are_valid = true; + if (opt_defs[i].required == false && + opt_defs[i].option_has_arg == OptionParser::eNoArgument) { + options.insert(opt_defs[i].short_option); } + } } - return options_are_valid; -} + if (options.empty() == false) { + // We have some required options with no arguments + strm.PutCString(" [-"); + for (i = 0; i < 2; ++i) + for (options_pos = options.begin(), options_end = options.end(); + options_pos != options_end; ++options_pos) { + if (i == 0 && ::islower(*options_pos)) + continue; + if (i == 1 && ::isupper(*options_pos)) + continue; + strm << (char)*options_pos; + } + strm.PutChar(']'); + } -bool -Options::HandleOptionCompletion -( - Args &input, - OptionElementVector &opt_element_vector, - int cursor_index, - int char_pos, - int match_start_point, - int max_return_elements, - CommandInterpreter &interpreter, - bool &word_complete, - lldb_private::StringList &matches -) -{ - word_complete = true; - - // For now we just scan the completions to see if the cursor position is in - // an option or its argument. Otherwise we'll call HandleArgumentCompletion. - // In the future we can use completion to validate options as well if we want. + // First go through and print the required options (list them up front). - const OptionDefinition *opt_defs = GetDefinitions(); + for (i = 0; i < num_options; ++i) { + if (opt_defs[i].usage_mask & opt_set_mask && + isprint8(opt_defs[i].short_option)) { + if (opt_defs[i].required && + opt_defs[i].option_has_arg != OptionParser::eNoArgument) + PrintOption(opt_defs[i], eDisplayBestOption, " ", nullptr, true, + strm); + } + } - std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index)); - cur_opt_std_str.erase(char_pos); - const char *cur_opt_str = cur_opt_std_str.c_str(); - - for (size_t i = 0; i < opt_element_vector.size(); i++) - { - int opt_pos = opt_element_vector[i].opt_pos; - int opt_arg_pos = opt_element_vector[i].opt_arg_pos; - int opt_defs_index = opt_element_vector[i].opt_defs_index; - if (opt_pos == cursor_index) - { - // We're completing the option itself. - - if (opt_defs_index == OptionArgElement::eBareDash) - { - // We're completing a bare dash. That means all options are open. - // FIXME: We should scan the other options provided and only complete options - // within the option group they belong to. - char opt_str[3] = {'-', 'a', '\0'}; - - for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) - { - opt_str[1] = opt_defs[j].short_option; - matches.AppendString (opt_str); - } - return true; - } - else if (opt_defs_index == OptionArgElement::eBareDoubleDash) - { - std::string full_name ("--"); - for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) - { - full_name.erase(full_name.begin() + 2, full_name.end()); - full_name.append (opt_defs[j].long_option); - matches.AppendString (full_name.c_str()); - } - return true; - } - else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) - { - // We recognized it, if it an incomplete long option, complete it anyway (getopt_long_only is - // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return - // The string so the upper level code will know this is a full match and add the " ". - if (cur_opt_str && strlen (cur_opt_str) > 2 - && cur_opt_str[0] == '-' && cur_opt_str[1] == '-' - && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) - { - std::string full_name ("--"); - full_name.append (opt_defs[opt_defs_index].long_option); - matches.AppendString(full_name.c_str()); - return true; - } - else - { - matches.AppendString(input.GetArgumentAtIndex(cursor_index)); - return true; - } - } - else - { - // FIXME - not handling wrong options yet: - // Check to see if they are writing a long option & complete it. - // I think we will only get in here if the long option table has two elements - // that are not unique up to this point. getopt_long_only does shortest unique match - // for long options already. - - if (cur_opt_str && strlen (cur_opt_str) > 2 - && cur_opt_str[0] == '-' && cur_opt_str[1] == '-') - { - for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) - { - if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option) - { - std::string full_name ("--"); - full_name.append (opt_defs[j].long_option); - // The options definitions table has duplicates because of the - // way the grouping information is stored, so only add once. - bool duplicate = false; - for (size_t k = 0; k < matches.GetSize(); k++) - { - if (matches.GetStringAtIndex(k) == full_name) - { - duplicate = true; - break; - } - } - if (!duplicate) - matches.AppendString(full_name.c_str()); - } - } - } - return true; - } + // Now go through again, and this time only print the optional options. + for (i = 0; i < num_options; ++i) { + if (opt_defs[i].usage_mask & opt_set_mask) { + // Add current option to the end of out_stream. + if (!opt_defs[i].required && + opt_defs[i].option_has_arg != OptionParser::eNoArgument) + PrintOption(opt_defs[i], eDisplayBestOption, " ", nullptr, true, + strm); } - else if (opt_arg_pos == cursor_index) - { - // Okay the cursor is on the completion of an argument. - // See if it has a completion, otherwise return no matches. - - if (opt_defs_index != -1) - { - HandleOptionArgumentCompletion (input, - cursor_index, - strlen (input.GetArgumentAtIndex(cursor_index)), - opt_element_vector, - i, - match_start_point, - max_return_elements, - interpreter, - word_complete, - matches); - return true; - } - else - { - // No completion callback means no completions... - return true; - } + } - } - else - { - // Not the last element, keep going. - continue; - } - } - return false; -} + if (args_str.GetSize() > 0) { + if (cmd->WantsRawCommandString() && !only_print_args) + strm.Printf(" --"); -bool -Options::HandleOptionArgumentCompletion -( - Args &input, - int cursor_index, - int char_pos, - OptionElementVector &opt_element_vector, - int opt_element_index, - int match_start_point, - int max_return_elements, - CommandInterpreter &interpreter, - bool &word_complete, - lldb_private::StringList &matches -) -{ - const OptionDefinition *opt_defs = GetDefinitions(); - std::unique_ptr filter_ap; - - int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; - int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; - - // See if this is an enumeration type option, and if so complete it here: - - OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values; - if (enum_values != nullptr) - { - bool return_value = false; - std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos); - for (int i = 0; enum_values[i].string_value != nullptr; i++) - { - if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value) - { - matches.AppendString (enum_values[i].string_value); - return_value = true; - } - } - return return_value; + strm.Printf(" %s", args_str.GetData()); + if (only_print_args) + break; + } } + } - // If this is a source file or symbol type completion, and there is a - // -shlib option somewhere in the supplied arguments, then make a search filter - // for that shared library. - // FIXME: Do we want to also have an "OptionType" so we don't have to match string names? - - uint32_t completion_mask = opt_defs[opt_defs_index].completion_type; - - if (completion_mask == 0) - { - lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type; - if (option_arg_type != eArgTypeNone) - { - const CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type); - if (arg_entry) - completion_mask = arg_entry->completion_type; - } - } + if (cmd && (only_print_args || cmd->WantsRawCommandString()) && + arguments_str.GetSize() > 0) { + if (!only_print_args) + strm.PutChar('\n'); + strm.Indent(name); + strm.Printf(" %s", arguments_str.GetData()); + } - if (completion_mask & CommandCompletions::eSourceFileCompletion - || completion_mask & CommandCompletions::eSymbolCompletion) - { - for (size_t i = 0; i < opt_element_vector.size(); i++) - { - int cur_defs_index = opt_element_vector[i].opt_defs_index; - - // trying to use <0 indices will definitely cause problems - if (cur_defs_index == OptionArgElement::eUnrecognizedArg || - cur_defs_index == OptionArgElement::eBareDash || - cur_defs_index == OptionArgElement::eBareDoubleDash) - continue; - - int cur_arg_pos = opt_element_vector[i].opt_arg_pos; - const char *cur_opt_name = opt_defs[cur_defs_index].long_option; - - // If this is the "shlib" option and there was an argument provided, - // restrict it to that shared library. - if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1) - { - const char *module_name = input.GetArgumentAtIndex(cur_arg_pos); - if (module_name) - { - FileSpec module_spec(module_name, false); - lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - // Search filters require a target... - if (target_sp) - filter_ap.reset (new SearchFilterByModule (target_sp, module_spec)); - } - break; - } + strm.Printf("\n\n"); + + if (!only_print_args) { + // Now print out all the detailed information about the various options: + // long form, short form and help text: + // -short ( --long_name ) + // help text + + // This variable is used to keep track of which options' info we've printed + // out, because some options can be in + // more than one usage level, but we only want to print the long form of its + // information once. + + std::multimap options_seen; + strm.IndentMore(5); + + // Put the unique command options in a vector & sort it, so we can output + // them alphabetically (by short_option) + // when writing out detailed help for each option. + + for (i = 0; i < num_options; ++i) + options_seen.insert(std::make_pair(opt_defs[i].short_option, i)); + + // Go through the unique'd and alphabetically sorted vector of options, find + // the table entry for each option + // and write out the detailed help information for that option. + + bool first_option_printed = false; + ; + + for (auto pos : options_seen) { + i = pos.second; + // Print out the help information for this option. + + // Put a newline separation between arguments + if (first_option_printed) + strm.EOL(); + else + first_option_printed = true; + + CommandArgumentType arg_type = opt_defs[i].argument_type; + + StreamString arg_name_str; + arg_name_str.Printf("<%s>", CommandObject::GetArgumentName(arg_type)); + + strm.Indent(); + if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) { + PrintOption(opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, + strm); + PrintOption(opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); + } else { + // Short option is not printable, just print long option + PrintOption(opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, + strm); + } + strm.EOL(); + + strm.IndentMore(5); + + if (opt_defs[i].usage_text) + OutputFormattedUsageText(strm, opt_defs[i], screen_width); + if (opt_defs[i].enum_values != nullptr) { + strm.Indent(); + strm.Printf("Values: "); + for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; + k++) { + if (k == 0) + strm.Printf("%s", opt_defs[i].enum_values[k].string_value); + else + strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); } + strm.EOL(); + } + strm.IndentLess(5); } + } - return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, - completion_mask, - input.GetArgumentAtIndex (opt_arg_pos), - match_start_point, - max_return_elements, - filter_ap.get(), - word_complete, - matches); - + // Restore the indent level + strm.SetIndentLevel(save_indent_level); } +// This function is called when we have been given a potentially incomplete set +// of +// options, such as when an alias has been defined (more options might be added +// at +// at the time the alias is invoked). We need to verify that the options in the +// set +// m_seen_options are all part of a set that may be used together, but +// m_seen_options +// may be missing some of the "required" options. -void -OptionGroupOptions::Append (OptionGroup* group) -{ - const OptionDefinition* group_option_defs = group->GetDefinitions (); - const uint32_t group_option_count = group->GetNumDefinitions(); - for (uint32_t i=0; i 2 && cur_opt_str[0] == '-' && + cur_opt_str[1] == '-' && + strcmp(opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) { + std::string full_name("--"); + full_name.append(opt_defs[opt_defs_index].long_option); + matches.AppendString(full_name.c_str()); + return true; + } else { + matches.AppendString(input.GetArgumentAtIndex(cursor_index)); + return true; + } + } else { + // FIXME - not handling wrong options yet: + // Check to see if they are writing a long option & complete it. + // I think we will only get in here if the long option table has two + // elements + // that are not unique up to this point. getopt_long_only does shortest + // unique match + // for long options already. + + if (cur_opt_str && strlen(cur_opt_str) > 2 && cur_opt_str[0] == '-' && + cur_opt_str[1] == '-') { + for (int j = 0; opt_defs[j].short_option != 0; j++) { + if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == + opt_defs[j].long_option) { + std::string full_name("--"); + full_name.append(opt_defs[j].long_option); + // The options definitions table has duplicates because of the + // way the grouping information is stored, so only add once. + bool duplicate = false; + for (size_t k = 0; k < matches.GetSize(); k++) { + if (matches.GetStringAtIndex(k) == full_name) { + duplicate = true; + break; + } + } + if (!duplicate) + matches.AppendString(full_name.c_str()); + } + } + } + return true; + } + + } else if (opt_arg_pos == cursor_index) { + // Okay the cursor is on the completion of an argument. + // See if it has a completion, otherwise return no matches. + + if (opt_defs_index != -1) { + HandleOptionArgumentCompletion( + input, cursor_index, strlen(input.GetArgumentAtIndex(cursor_index)), + opt_element_vector, i, match_start_point, max_return_elements, + interpreter, word_complete, matches); + return true; + } else { + // No completion callback means no completions... + return true; + } + + } else { + // Not the last element, keep going. + continue; } - return nullptr; + } + return false; } -void -OptionGroupOptions::Append (OptionGroup* group, - uint32_t src_mask, - uint32_t dst_mask) -{ - const OptionDefinition* group_option_defs = group->GetDefinitions (); - const uint32_t group_option_count = group->GetNumDefinitions(); - for (uint32_t i=0; i filter_ap; + + int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; + int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; + + // See if this is an enumeration type option, and if so complete it here: + + OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values; + if (enum_values != nullptr) { + bool return_value = false; + std::string match_string(input.GetArgumentAtIndex(opt_arg_pos), + input.GetArgumentAtIndex(opt_arg_pos) + char_pos); + for (int i = 0; enum_values[i].string_value != nullptr; i++) { + if (strstr(enum_values[i].string_value, match_string.c_str()) == + enum_values[i].string_value) { + matches.AppendString(enum_values[i].string_value); + return_value = true; + } + } + return return_value; + } + + // If this is a source file or symbol type completion, and there is a + // -shlib option somewhere in the supplied arguments, then make a search + // filter + // for that shared library. + // FIXME: Do we want to also have an "OptionType" so we don't have to match + // string names? + + uint32_t completion_mask = opt_defs[opt_defs_index].completion_type; + + if (completion_mask == 0) { + lldb::CommandArgumentType option_arg_type = + opt_defs[opt_defs_index].argument_type; + if (option_arg_type != eArgTypeNone) { + const CommandObject::ArgumentTableEntry *arg_entry = + CommandObject::FindArgumentDataByType( + opt_defs[opt_defs_index].argument_type); + if (arg_entry) + completion_mask = arg_entry->completion_type; + } + } + + if (completion_mask & CommandCompletions::eSourceFileCompletion || + completion_mask & CommandCompletions::eSymbolCompletion) { + for (size_t i = 0; i < opt_element_vector.size(); i++) { + int cur_defs_index = opt_element_vector[i].opt_defs_index; + + // trying to use <0 indices will definitely cause problems + if (cur_defs_index == OptionArgElement::eUnrecognizedArg || + cur_defs_index == OptionArgElement::eBareDash || + cur_defs_index == OptionArgElement::eBareDoubleDash) + continue; + + int cur_arg_pos = opt_element_vector[i].opt_arg_pos; + const char *cur_opt_name = opt_defs[cur_defs_index].long_option; + + // If this is the "shlib" option and there was an argument provided, + // restrict it to that shared library. + if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 && + cur_arg_pos != -1) { + const char *module_name = input.GetArgumentAtIndex(cur_arg_pos); + if (module_name) { + FileSpec module_spec(module_name, false); + lldb::TargetSP target_sp = + interpreter.GetDebugger().GetSelectedTarget(); + // Search filters require a target... + if (target_sp) + filter_ap.reset(new SearchFilterByModule(target_sp, module_spec)); } + break; + } } + } + + return CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, completion_mask, input.GetArgumentAtIndex(opt_arg_pos), + match_start_point, max_return_elements, filter_ap.get(), word_complete, + matches); } -void -OptionGroupOptions::Finalize () -{ - m_did_finalize = true; - OptionDefinition empty_option_def = { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }; - m_option_defs.push_back (empty_option_def); +void OptionGroupOptions::Append(OptionGroup *group) { + const OptionDefinition *group_option_defs = group->GetDefinitions(); + const uint32_t group_option_count = group->GetNumDefinitions(); + for (uint32_t i = 0; i < group_option_count; ++i) { + m_option_infos.push_back(OptionInfo(group, i)); + m_option_defs.push_back(group_option_defs[i]); + } } -Error -OptionGroupOptions::SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) -{ - // After calling OptionGroupOptions::Append(...), you must finalize the groups - // by calling OptionGroupOptions::Finlize() - assert (m_did_finalize); - assert (m_option_infos.size() + 1 == m_option_defs.size()); - Error error; - if (option_idx < m_option_infos.size()) - { - error = m_option_infos[option_idx].option_group->SetOptionValue (m_option_infos[option_idx].option_index, - option_value, - execution_context); - - } - else - { - error.SetErrorString ("invalid option index"); // Shouldn't happen... +const OptionGroup *OptionGroupOptions::GetGroupWithOption(char short_opt) { + for (uint32_t i = 0; i < m_option_defs.size(); i++) { + OptionDefinition opt_def = m_option_defs[i]; + if (opt_def.short_option == short_opt) + return m_option_infos[i].option_group; + } + return nullptr; +} + +void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask, + uint32_t dst_mask) { + const OptionDefinition *group_option_defs = group->GetDefinitions(); + const uint32_t group_option_count = group->GetNumDefinitions(); + for (uint32_t i = 0; i < group_option_count; ++i) { + if (group_option_defs[i].usage_mask & src_mask) { + m_option_infos.push_back(OptionInfo(group, i)); + m_option_defs.push_back(group_option_defs[i]); + m_option_defs.back().usage_mask = dst_mask; } - return error; + } } -void -OptionGroupOptions::OptionParsingStarting (ExecutionContext *execution_context) -{ - std::set group_set; - OptionInfos::iterator pos, end = m_option_infos.end(); - for (pos = m_option_infos.begin(); pos != end; ++pos) - { - OptionGroup* group = pos->option_group; - if (group_set.find(group) == group_set.end()) - { - group->OptionParsingStarting(execution_context); - group_set.insert(group); - } +void OptionGroupOptions::Finalize() { + m_did_finalize = true; + OptionDefinition empty_option_def = { + 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}; + m_option_defs.push_back(empty_option_def); +} + +Error OptionGroupOptions::SetOptionValue(uint32_t option_idx, + const char *option_value, + ExecutionContext *execution_context) { + // After calling OptionGroupOptions::Append(...), you must finalize the groups + // by calling OptionGroupOptions::Finlize() + assert(m_did_finalize); + assert(m_option_infos.size() + 1 == m_option_defs.size()); + Error error; + if (option_idx < m_option_infos.size()) { + error = m_option_infos[option_idx].option_group->SetOptionValue( + m_option_infos[option_idx].option_index, option_value, + execution_context); + + } else { + error.SetErrorString("invalid option index"); // Shouldn't happen... + } + return error; +} + +void OptionGroupOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + std::set group_set; + OptionInfos::iterator pos, end = m_option_infos.end(); + for (pos = m_option_infos.begin(); pos != end; ++pos) { + OptionGroup *group = pos->option_group; + if (group_set.find(group) == group_set.end()) { + group->OptionParsingStarting(execution_context); + group_set.insert(group); } + } } -Error -OptionGroupOptions::OptionParsingFinished (ExecutionContext *execution_context) -{ - std::set group_set; - Error error; - OptionInfos::iterator pos, end = m_option_infos.end(); - for (pos = m_option_infos.begin(); pos != end; ++pos) - { - OptionGroup* group = pos->option_group; - if (group_set.find(group) == group_set.end()) - { - error = group->OptionParsingFinished (execution_context); - group_set.insert(group); - if (error.Fail()) - return error; - } +Error OptionGroupOptions::OptionParsingFinished( + ExecutionContext *execution_context) { + std::set group_set; + Error error; + OptionInfos::iterator pos, end = m_option_infos.end(); + for (pos = m_option_infos.begin(); pos != end; ++pos) { + OptionGroup *group = pos->option_group; + if (group_set.find(group) == group_set.end()) { + error = group->OptionParsingFinished(execution_context); + group_set.insert(group); + if (error.Fail()) + return error; } - return error; + } + return error; } diff --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp index b9fe28620a4..1958949c0b0 100644 --- a/lldb/source/Interpreter/Property.cpp +++ b/lldb/source/Interpreter/Property.cpp @@ -22,289 +22,280 @@ using namespace lldb; using namespace lldb_private; -Property::Property (const PropertyDefinition &definition) : - m_name (definition.name), - m_description (definition.description), - m_value_sp (), - m_is_global (definition.global) -{ - switch (definition.type) - { - case OptionValue::eTypeInvalid: - case OptionValue::eTypeProperties: - break; - case OptionValue::eTypeArch: - // "definition.default_uint_value" is not used - // "definition.default_cstr_value" as a string value that represents the default string value for the architecture/triple - m_value_sp.reset (new OptionValueArch(definition.default_cstr_value)); - break; - - case OptionValue::eTypeArgs: - // "definition.default_uint_value" is always a OptionValue::Type - m_value_sp.reset (new OptionValueArgs()); - break; - - case OptionValue::eTypeArray: - // "definition.default_uint_value" is always a OptionValue::Type - m_value_sp.reset (new OptionValueArray(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value))); - break; - - case OptionValue::eTypeBoolean: - // "definition.default_uint_value" is the default boolean value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - if (definition.default_cstr_value) - m_value_sp.reset (new OptionValueBoolean(Args::StringToBoolean (definition.default_cstr_value, false, nullptr))); - else - m_value_sp.reset (new OptionValueBoolean(definition.default_uint_value != 0)); - break; +Property::Property(const PropertyDefinition &definition) + : m_name(definition.name), m_description(definition.description), + m_value_sp(), m_is_global(definition.global) { + switch (definition.type) { + case OptionValue::eTypeInvalid: + case OptionValue::eTypeProperties: + break; + case OptionValue::eTypeArch: + // "definition.default_uint_value" is not used + // "definition.default_cstr_value" as a string value that represents the + // default string value for the architecture/triple + m_value_sp.reset(new OptionValueArch(definition.default_cstr_value)); + break; - case OptionValue::eTypeChar: - m_value_sp.reset(new OptionValueChar(Args::StringToChar(definition.default_cstr_value, '\0', nullptr))); - break; + case OptionValue::eTypeArgs: + // "definition.default_uint_value" is always a OptionValue::Type + m_value_sp.reset(new OptionValueArgs()); + break; - case OptionValue::eTypeDictionary: - // "definition.default_uint_value" is always a OptionValue::Type - m_value_sp.reset (new OptionValueDictionary(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value))); - break; - - case OptionValue::eTypeEnum: - // "definition.default_uint_value" is the default enumeration value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - { - OptionValueEnumeration *enum_value = new OptionValueEnumeration(definition.enum_values, definition.default_uint_value); - m_value_sp.reset (enum_value); - if (definition.default_cstr_value) - { - if (enum_value->SetValueFromString(definition.default_cstr_value).Success()) - { - enum_value->SetDefaultValue(enum_value->GetCurrentValue()); - // Call Clear() since we don't want the value to appear as - // having been set since we called SetValueFromString() above. - // Clear will set the current value to the default and clear - // the boolean that says that the value has been set. - enum_value->Clear(); - } - } - } - break; - - case OptionValue::eTypeFileSpec: - { - // "definition.default_uint_value" represents if the "definition.default_cstr_value" should - // be resolved or not - const bool resolve = definition.default_uint_value != 0; - m_value_sp.reset (new OptionValueFileSpec(FileSpec(definition.default_cstr_value, resolve), resolve)); - break; - } - - case OptionValue::eTypeFileSpecList: - // "definition.default_uint_value" is not used for a OptionValue::eTypeFileSpecList - m_value_sp.reset (new OptionValueFileSpecList()); - break; - - case OptionValue::eTypeFormat: - // "definition.default_uint_value" is the default format enumeration value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - { - Format new_format = eFormatInvalid; - if (definition.default_cstr_value) - Args::StringToFormat (definition.default_cstr_value, new_format, nullptr); - else - new_format = (Format)definition.default_uint_value; - m_value_sp.reset (new OptionValueFormat(new_format)); - } - break; - - case OptionValue::eTypeLanguage: - // "definition.default_uint_value" is the default language enumeration value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - { - LanguageType new_lang = eLanguageTypeUnknown; - if (definition.default_cstr_value) - Language::GetLanguageTypeFromString(definition.default_cstr_value); - else - new_lang = (LanguageType)definition.default_uint_value; - m_value_sp.reset (new OptionValueLanguage(new_lang)); + case OptionValue::eTypeArray: + // "definition.default_uint_value" is always a OptionValue::Type + m_value_sp.reset(new OptionValueArray(OptionValue::ConvertTypeToMask( + (OptionValue::Type)definition.default_uint_value))); + break; + + case OptionValue::eTypeBoolean: + // "definition.default_uint_value" is the default boolean value if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + if (definition.default_cstr_value) + m_value_sp.reset(new OptionValueBoolean(Args::StringToBoolean( + definition.default_cstr_value, false, nullptr))); + else + m_value_sp.reset( + new OptionValueBoolean(definition.default_uint_value != 0)); + break; + + case OptionValue::eTypeChar: + m_value_sp.reset(new OptionValueChar( + Args::StringToChar(definition.default_cstr_value, '\0', nullptr))); + break; + + case OptionValue::eTypeDictionary: + // "definition.default_uint_value" is always a OptionValue::Type + m_value_sp.reset(new OptionValueDictionary(OptionValue::ConvertTypeToMask( + (OptionValue::Type)definition.default_uint_value))); + break; + + case OptionValue::eTypeEnum: + // "definition.default_uint_value" is the default enumeration value if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + { + OptionValueEnumeration *enum_value = new OptionValueEnumeration( + definition.enum_values, definition.default_uint_value); + m_value_sp.reset(enum_value); + if (definition.default_cstr_value) { + if (enum_value->SetValueFromString(definition.default_cstr_value) + .Success()) { + enum_value->SetDefaultValue(enum_value->GetCurrentValue()); + // Call Clear() since we don't want the value to appear as + // having been set since we called SetValueFromString() above. + // Clear will set the current value to the default and clear + // the boolean that says that the value has been set. + enum_value->Clear(); } - break; - - case OptionValue::eTypeFormatEntity: - // "definition.default_cstr_value" as a string value that represents the default - m_value_sp.reset (new OptionValueFormatEntity(definition.default_cstr_value)); - break; + } + } + break; - case OptionValue::eTypePathMap: - // "definition.default_uint_value" tells us if notifications should occur for - // path mappings - m_value_sp.reset (new OptionValuePathMappings(definition.default_uint_value != 0)); - break; - - case OptionValue::eTypeRegex: - // "definition.default_uint_value" is used to the regular expression flags - // "definition.default_cstr_value" the default regular expression value - // value. - m_value_sp.reset (new OptionValueRegex(definition.default_cstr_value)); - break; - - case OptionValue::eTypeSInt64: - // "definition.default_uint_value" is the default integer value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - m_value_sp.reset (new OptionValueSInt64(definition.default_cstr_value ? StringConvert::ToSInt64 (definition.default_cstr_value) : definition.default_uint_value)); - break; - - case OptionValue::eTypeUInt64: - // "definition.default_uint_value" is the default unsigned integer value if - // "definition.default_cstr_value" is NULL, otherwise interpret - // "definition.default_cstr_value" as a string value that represents the default - // value. - m_value_sp.reset (new OptionValueUInt64(definition.default_cstr_value ? StringConvert::ToUInt64 (definition.default_cstr_value) : definition.default_uint_value)); - break; - - case OptionValue::eTypeUUID: - // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID - // "definition.default_cstr_value" can contain a default UUID value - { - UUID uuid; - if (definition.default_cstr_value) - uuid.SetFromCString (definition.default_cstr_value); - m_value_sp.reset (new OptionValueUUID(uuid)); - } - break; - - case OptionValue::eTypeString: - // "definition.default_uint_value" can contain the string option flags OR'ed together - // "definition.default_cstr_value" can contain a default string value - { - OptionValueString *string_value = new OptionValueString(definition.default_cstr_value); - if (definition.default_uint_value != 0) - string_value->GetOptions().Reset(definition.default_uint_value); - m_value_sp.reset (string_value); - } - break; + case OptionValue::eTypeFileSpec: { + // "definition.default_uint_value" represents if the + // "definition.default_cstr_value" should + // be resolved or not + const bool resolve = definition.default_uint_value != 0; + m_value_sp.reset(new OptionValueFileSpec( + FileSpec(definition.default_cstr_value, resolve), resolve)); + break; + } + + case OptionValue::eTypeFileSpecList: + // "definition.default_uint_value" is not used for a + // OptionValue::eTypeFileSpecList + m_value_sp.reset(new OptionValueFileSpecList()); + break; + + case OptionValue::eTypeFormat: + // "definition.default_uint_value" is the default format enumeration value + // if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + { + Format new_format = eFormatInvalid; + if (definition.default_cstr_value) + Args::StringToFormat(definition.default_cstr_value, new_format, + nullptr); + else + new_format = (Format)definition.default_uint_value; + m_value_sp.reset(new OptionValueFormat(new_format)); } -} + break; -Property::Property (const ConstString &name, - const ConstString &desc, - bool is_global, - const lldb::OptionValueSP &value_sp) : - m_name (name), - m_description (desc), - m_value_sp (value_sp), - m_is_global (is_global) -{ -} + case OptionValue::eTypeLanguage: + // "definition.default_uint_value" is the default language enumeration value + // if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + { + LanguageType new_lang = eLanguageTypeUnknown; + if (definition.default_cstr_value) + Language::GetLanguageTypeFromString(definition.default_cstr_value); + else + new_lang = (LanguageType)definition.default_uint_value; + m_value_sp.reset(new OptionValueLanguage(new_lang)); + } + break; + + case OptionValue::eTypeFormatEntity: + // "definition.default_cstr_value" as a string value that represents the + // default + m_value_sp.reset( + new OptionValueFormatEntity(definition.default_cstr_value)); + break; + + case OptionValue::eTypePathMap: + // "definition.default_uint_value" tells us if notifications should occur + // for + // path mappings + m_value_sp.reset( + new OptionValuePathMappings(definition.default_uint_value != 0)); + break; -bool -Property::DumpQualifiedName(Stream &strm) const -{ - if (m_name) + case OptionValue::eTypeRegex: + // "definition.default_uint_value" is used to the regular expression flags + // "definition.default_cstr_value" the default regular expression value + // value. + m_value_sp.reset(new OptionValueRegex(definition.default_cstr_value)); + break; + + case OptionValue::eTypeSInt64: + // "definition.default_uint_value" is the default integer value if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + m_value_sp.reset(new OptionValueSInt64( + definition.default_cstr_value + ? StringConvert::ToSInt64(definition.default_cstr_value) + : definition.default_uint_value)); + break; + + case OptionValue::eTypeUInt64: + // "definition.default_uint_value" is the default unsigned integer value if + // "definition.default_cstr_value" is NULL, otherwise interpret + // "definition.default_cstr_value" as a string value that represents the + // default + // value. + m_value_sp.reset(new OptionValueUInt64( + definition.default_cstr_value + ? StringConvert::ToUInt64(definition.default_cstr_value) + : definition.default_uint_value)); + break; + + case OptionValue::eTypeUUID: + // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID + // "definition.default_cstr_value" can contain a default UUID value { - if (m_value_sp->DumpQualifiedName(strm)) - strm.PutChar('.'); - strm << m_name; - return true; + UUID uuid; + if (definition.default_cstr_value) + uuid.SetFromCString(definition.default_cstr_value); + m_value_sp.reset(new OptionValueUUID(uuid)); } - return false; + break; + + case OptionValue::eTypeString: + // "definition.default_uint_value" can contain the string option flags OR'ed + // together + // "definition.default_cstr_value" can contain a default string value + { + OptionValueString *string_value = + new OptionValueString(definition.default_cstr_value); + if (definition.default_uint_value != 0) + string_value->GetOptions().Reset(definition.default_uint_value); + m_value_sp.reset(string_value); + } + break; + } } +Property::Property(const ConstString &name, const ConstString &desc, + bool is_global, const lldb::OptionValueSP &value_sp) + : m_name(name), m_description(desc), m_value_sp(value_sp), + m_is_global(is_global) {} -void -Property::Dump (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) const -{ - if (m_value_sp) - { - const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription; - const bool transparent = m_value_sp->ValueIsTransparent (); - if (dump_desc || !transparent) - { - if ((dump_mask & OptionValue::eDumpOptionName) && m_name) - { - DumpQualifiedName(strm); - if (dump_mask & ~OptionValue::eDumpOptionName) - strm.PutChar(' '); - } - } - if (dump_desc) - { - const char *desc = GetDescription(); - if (desc) - strm.Printf ("-- %s", desc); - - if (transparent && (dump_mask == (OptionValue::eDumpOptionName | OptionValue::eDumpOptionDescription))) - strm.EOL(); - } - m_value_sp->DumpValue(exe_ctx, strm, dump_mask); +bool Property::DumpQualifiedName(Stream &strm) const { + if (m_name) { + if (m_value_sp->DumpQualifiedName(strm)) + strm.PutChar('.'); + strm << m_name; + return true; + } + return false; +} + +void Property::Dump(const ExecutionContext *exe_ctx, Stream &strm, + uint32_t dump_mask) const { + if (m_value_sp) { + const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription; + const bool transparent = m_value_sp->ValueIsTransparent(); + if (dump_desc || !transparent) { + if ((dump_mask & OptionValue::eDumpOptionName) && m_name) { + DumpQualifiedName(strm); + if (dump_mask & ~OptionValue::eDumpOptionName) + strm.PutChar(' '); + } + } + if (dump_desc) { + const char *desc = GetDescription(); + if (desc) + strm.Printf("-- %s", desc); + + if (transparent && (dump_mask == (OptionValue::eDumpOptionName | + OptionValue::eDumpOptionDescription))) + strm.EOL(); } + m_value_sp->DumpValue(exe_ctx, strm, dump_mask); + } } +void Property::DumpDescription(CommandInterpreter &interpreter, Stream &strm, + uint32_t output_width, + bool display_qualified_name) const { + if (m_value_sp) { + const char *desc = GetDescription(); -void -Property::DumpDescription (CommandInterpreter &interpreter, - Stream &strm, - uint32_t output_width, - bool display_qualified_name) const -{ - if (m_value_sp) - { - const char *desc = GetDescription(); + if (desc) { + StreamString qualified_name; + const OptionValueProperties *sub_properties = + m_value_sp->GetAsProperties(); + if (sub_properties) { + strm.EOL(); - if (desc) - { + if (m_value_sp->DumpQualifiedName(qualified_name)) + strm.Printf("'%s' variables:\n\n", + qualified_name.GetString().c_str()); + sub_properties->DumpAllDescriptions(interpreter, strm); + } else { + if (desc) { + if (display_qualified_name) { StreamString qualified_name; - const OptionValueProperties *sub_properties = m_value_sp->GetAsProperties(); - if (sub_properties) - { - strm.EOL(); - - if (m_value_sp->DumpQualifiedName(qualified_name)) - strm.Printf("'%s' variables:\n\n", qualified_name.GetString().c_str()); - sub_properties->DumpAllDescriptions(interpreter, strm); - } - else - { - if (desc) - { - if (display_qualified_name) - { - StreamString qualified_name; - DumpQualifiedName(qualified_name); - interpreter.OutputFormattedHelpText (strm, - qualified_name.GetString().c_str(), - "--", - desc, - output_width); - } - else - { - interpreter.OutputFormattedHelpText (strm, - m_name.GetCString(), - "--", - desc, - output_width); - } - } - } + DumpQualifiedName(qualified_name); + interpreter.OutputFormattedHelpText( + strm, qualified_name.GetString().c_str(), "--", desc, + output_width); + } else { + interpreter.OutputFormattedHelpText(strm, m_name.GetCString(), "--", + desc, output_width); + } } + } } + } } - -void -Property::SetValueChangedCallback (OptionValueChangedCallback callback, void *baton) -{ - if (m_value_sp) - m_value_sp->SetValueChangedCallback (callback, baton); +void Property::SetValueChangedCallback(OptionValueChangedCallback callback, + void *baton) { + if (m_value_sp) + m_value_sp->SetValueChangedCallback(callback, baton); } - - diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index f1ec50e663f..87f4daceac9 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -9,9 +9,9 @@ #include "lldb/Interpreter/ScriptInterpreter.h" -#include -#include #include +#include +#include #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" @@ -22,88 +22,68 @@ using namespace lldb; using namespace lldb_private; -ScriptInterpreter::ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang) : - m_interpreter (interpreter), - m_script_lang (script_lang) -{ -} +ScriptInterpreter::ScriptInterpreter(CommandInterpreter &interpreter, + lldb::ScriptLanguage script_lang) + : m_interpreter(interpreter), m_script_lang(script_lang) {} -ScriptInterpreter::~ScriptInterpreter () -{ -} +ScriptInterpreter::~ScriptInterpreter() {} -CommandInterpreter & -ScriptInterpreter::GetCommandInterpreter () -{ - return m_interpreter; +CommandInterpreter &ScriptInterpreter::GetCommandInterpreter() { + return m_interpreter; } -void -ScriptInterpreter::CollectDataForBreakpointCommandCallback -( +void ScriptInterpreter::CollectDataForBreakpointCommandCallback( std::vector &bp_options_vec, - CommandReturnObject &result -) -{ - result.SetStatus (eReturnStatusFailed); - result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented."); + CommandReturnObject &result) { + result.SetStatus(eReturnStatusFailed); + result.AppendError( + "ScriptInterpreter::GetScriptCommands(StringList &) is not implemented."); } -void -ScriptInterpreter::CollectDataForWatchpointCommandCallback -( - WatchpointOptions *bp_options, - CommandReturnObject &result -) -{ - result.SetStatus (eReturnStatusFailed); - result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented."); +void ScriptInterpreter::CollectDataForWatchpointCommandCallback( + WatchpointOptions *bp_options, CommandReturnObject &result) { + result.SetStatus(eReturnStatusFailed); + result.AppendError( + "ScriptInterpreter::GetScriptCommands(StringList &) is not implemented."); } -std::string -ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language) -{ - std::string return_value; +std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) { + std::string return_value; - switch (language) - { - case eScriptLanguageNone: - return_value = "None"; - break; - case eScriptLanguagePython: - return_value = "Python"; - break; - } + switch (language) { + case eScriptLanguageNone: + return_value = "None"; + break; + case eScriptLanguagePython: + return_value = "Python"; + break; + } - return return_value; + return return_value; } -Error -ScriptInterpreter::SetBreakpointCommandCallback (std::vector &bp_options_vec, - const char *callback_text) -{ - Error return_error; - for (BreakpointOptions *bp_options : bp_options_vec) - { - return_error = SetBreakpointCommandCallback(bp_options, callback_text); - if (return_error.Success()) - break; - } - return return_error; +Error ScriptInterpreter::SetBreakpointCommandCallback( + std::vector &bp_options_vec, + const char *callback_text) { + Error return_error; + for (BreakpointOptions *bp_options : bp_options_vec) { + return_error = SetBreakpointCommandCallback(bp_options, callback_text); + if (return_error.Success()) + break; + } + return return_error; } -void -ScriptInterpreter::SetBreakpointCommandCallbackFunction (std::vector &bp_options_vec, - const char *function_name) -{ - for (BreakpointOptions *bp_options : bp_options_vec) - { - SetBreakpointCommandCallbackFunction(bp_options, function_name); - } +void ScriptInterpreter::SetBreakpointCommandCallbackFunction( + std::vector &bp_options_vec, + const char *function_name) { + for (BreakpointOptions *bp_options : bp_options_vec) { + SetBreakpointCommandCallbackFunction(bp_options, function_name); + } } std::unique_ptr -ScriptInterpreter::AcquireInterpreterLock () -{ - return std::unique_ptr(new ScriptInterpreterLocker()); +ScriptInterpreter::AcquireInterpreterLock() { + return std::unique_ptr( + new ScriptInterpreterLocker()); } diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py index 8ba539a2b0c..c103b7e2e1d 100644 --- a/lldb/source/Interpreter/embedded_interpreter.py +++ b/lldb/source/Interpreter/embedded_interpreter.py @@ -25,16 +25,21 @@ else: g_builtin_override_called = False + class LLDBQuitter(object): + def __init__(self, name): self.name = name + def __repr__(self): self() + def __call__(self, code=None): global g_builtin_override_called g_builtin_override_called = True raise SystemExit(-1) + def setquit(): '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.''' # This function will be called prior to each interactive @@ -56,21 +61,25 @@ g_run_one_line_str = None def get_terminal_size(fd): try: - import fcntl, termios, struct + import fcntl + import termios + import struct hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) except: - hw = (0,0) + hw = (0, 0) return hw + def readfunc_stdio(prompt): sys.stdout.write(prompt) return sys.stdin.readline().rstrip() -def run_python_interpreter (local_dict): + +def run_python_interpreter(local_dict): # Pass in the dictionary, for continuity from one session to the next. setquit() try: - fd = sys.stdin.fileno(); + fd = sys.stdin.fileno() interacted = False if get_terminal_size(fd)[1] == 0: try: @@ -83,33 +92,42 @@ def run_python_interpreter (local_dict): try: termios.tcsetattr(fd, termios.TCSADRAIN, new) interacted = True - code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", readfunc=readfunc_stdio, local=local_dict) + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", + readfunc=readfunc_stdio, + local=local_dict) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old) except: pass # Don't need to turn off echoing if not interacted: - code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc_stdio, local=local_dict) + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", + readfunc=readfunc_stdio, + local=local_dict) else: # We have a real interactive terminal - code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", local=local_dict) + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", + local=local_dict) except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print('Script exited with %s' %(e)) + print('Script exited with %s' % (e)) + -def run_one_line (local_dict, input_string): +def run_one_line(local_dict, input_string): global g_run_one_line_str setquit() try: - repl = code.InteractiveConsole(local_dict); + repl = code.InteractiveConsole(local_dict) if input_string: - repl.runsource (input_string) + repl.runsource(input_string) elif g_run_one_line_str: - repl.runsource (g_run_one_line_str) + repl.runsource(g_run_one_line_str) except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print('Script exited with %s' %(e)) + print('Script exited with %s' % (e)) -- cgit v1.2.3