diff options
Diffstat (limited to 'source/Interpreter')
41 files changed, 1436 insertions, 1006 deletions
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index 4f0219fb858b..2258c26e6c39 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes #include <cstdlib> // C++ Includes @@ -33,25 +31,15 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Args constructor //---------------------------------------------------------------------- -Args::Args (const char *command) : +Args::Args (llvm::StringRef command) : m_args(), m_argv(), m_args_quote_char() { - if (command) - SetCommandString (command); + SetCommandString (command); } -Args::Args (const char *command, size_t len) : - m_args(), - m_argv(), - m_args_quote_char() -{ - if (command && len) - SetCommandString (command, len); -} - //---------------------------------------------------------------------- // 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 @@ -146,214 +134,158 @@ Args::GetQuotedCommandString (std::string &command) const return argc > 0; } -void -Args::SetCommandString (const char *command, size_t len) +// 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 +// quote. +static llvm::StringRef +ParseDoubleQuotes(llvm::StringRef quoted, std::string &result) { - // Use std::string to make sure we get a NULL terminated string we can use - // as "command" could point to a string within a large string.... - std::string null_terminated_command(command, len); - SetCommandString(null_terminated_command.c_str()); + // 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 += '\\'; + + result += quoted.front(); + quoted = quoted.drop_front(); + } + + return quoted; } -void -Args::SetCommandString (const char *command) +// 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 +// character. +llvm::StringRef +Args::ParseSingleArgument(llvm::StringRef command) { - m_args.clear(); - m_argv.clear(); - m_args_quote_char.clear(); - - if (command && command[0]) + // 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 { - static const char *k_space_separators = " \t"; - static const char *k_escapable_characters = " \t\\'\""; - const char *arg_end = nullptr; - const char *arg_pos; - for (arg_pos = command; - arg_pos && arg_pos[0]; - arg_pos = arg_end) + // 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) { - // Skip any leading space separators - const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos; - - // If there were only space separators to the end of the line, then - // we're done. - if (*arg_start == '\0') + case '\\': + if (command.empty()) + { + arg += '\\'; break; + } - // Arguments 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. So we need to keep track of the - // current start of each argument piece in "arg_piece_start" - const char *arg_piece_start = arg_start; - arg_pos = arg_piece_start; - - 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'; - char quote_char = '\0'; - bool arg_complete = false; - - do - { - arg_end = ::strcspn (arg_pos, k_escapable_characters) + arg_pos; + // 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 += '\\'; - switch (arg_end[0]) - { - default: - assert (!"Unhandled case statement, we must handle this..."); - break; + arg += command.front(); + command = command.drop_front(); - case '\0': - // End of C string - if (arg_piece_start && arg_piece_start[0]) - arg.append (arg_piece_start); - arg_complete = true; - break; - case '\\': - // Backslash character - switch (arg_end[1]) - { - case '\0': - arg.append (arg_piece_start); - ++arg_end; - arg_complete = true; - break; - - default: - // Only consider this two-character sequence an escape sequence if we're unquoted and - // the character after the backslash is a whitelisted escapable character. Otherwise - // leave the character sequence untouched. - if (quote_char == '\0' && (nullptr != strchr(k_escapable_characters, arg_end[1]))) - { - arg.append (arg_piece_start, arg_end - arg_piece_start); - arg.append (arg_end + 1, 1); - arg_pos = arg_end + 2; - arg_piece_start = arg_pos; - } - else - arg_pos = arg_end + 2; - break; - } - break; - case '"': - case '\'': - case '`': - // Quote characters - if (quote_char) - { - // We found a quote character while inside a quoted - // character argument. If it matches our current quote - // character, this ends the effect of the quotes. If it - // doesn't we ignore it. - if (quote_char == arg_end[0]) - { - arg.append (arg_piece_start, arg_end - arg_piece_start); - // Clear the quote character and let parsing - // continue (we need to watch for things like: - // "Hello ""World" - // "Hello "World - // "Hello "'World' - // All of which will result in a single argument "Hello World" - quote_char = '\0'; // Note that we are no longer inside quotes - arg_pos = arg_end + 1; // Skip the quote character - arg_piece_start = arg_pos; // Note we are starting from later in the string - } - else - { - // different quote, skip it and keep going - arg_pos = arg_end + 1; - } - } - else - { - // We found the start of a quote scope. - // Make sure there isn't a string that precedes - // the start of a quote scope like: - // Hello" World" - // If so, then add the "Hello" to the arg - if (arg_end > arg_piece_start) - arg.append (arg_piece_start, arg_end - arg_piece_start); - - // Enter into a quote scope - quote_char = arg_end[0]; - - if (first_quote_char == '\0') - first_quote_char = quote_char; + break; - arg_pos = arg_end; - ++arg_pos; // Skip the quote character - arg_piece_start = arg_pos; // Note we are starting from later in the string - - // Skip till the next quote character - const char *end_quote = ::strchr (arg_piece_start, quote_char); - while (end_quote && end_quote[-1] == '\\') - { - // Don't skip the quote character if it is - // preceded by a '\' character - end_quote = ::strchr (end_quote + 1, quote_char); - } - - if (end_quote) - { - if (end_quote > arg_piece_start) - arg.append (arg_piece_start, end_quote - arg_piece_start); + case ' ': + case '\t': + // We are not inside any quotes, we just found a space after an + // argument. We are done. + arg_complete = true; + break; - // If the next character is a space or the end of - // string, this argument is complete... - if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0') - { - arg_complete = true; - arg_end = end_quote + 1; - } - else - { - arg_pos = end_quote + 1; - arg_piece_start = arg_pos; - } - quote_char = '\0'; - } - else - { - // Consume the rest of the string as there was no terminating quote - arg.append(arg_piece_start); - arg_end = arg_piece_start + strlen(arg_piece_start); - arg_complete = true; - } - } - break; + case '"': + case '\'': + case '`': + // We found the start of a quote scope. + if (first_quote_char == '\0') + first_quote_char = special; - case ' ': - case '\t': - if (quote_char) - { - // We are currently processing a quoted character and found - // a space character, skip any spaces and keep trying to find - // the end of the argument. - arg_pos = ::strspn (arg_end, k_space_separators) + arg_end; - } - else - { - // We are not inside any quotes, we just found a space after an - // argument - if (arg_end > arg_piece_start) - arg.append (arg_piece_start, arg_end - arg_piece_start); - arg_complete = true; - } - break; - } - } while (!arg_complete); + 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); + } - m_args.push_back(arg); - m_args_quote_char.push_back (first_quote_char); + // If we found a closing quote, skip it. + if (! command.empty()) + command = command.drop_front(); + + break; } - UpdateArgvFromArgs(); + } while (!arg_complete); + + 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(); + + 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); } + + UpdateArgvFromArgs(); } void @@ -478,7 +410,8 @@ Args::AppendArguments (const Args &rhs) { const size_t rhs_argc = rhs.GetArgumentCount(); for (size_t i=0; i<rhs_argc; ++i) - AppendArgument(rhs.GetArgumentAtIndex(i)); + AppendArgument(rhs.GetArgumentAtIndex(i), + rhs.GetArgumentQuoteCharAtIndex(i)); } void @@ -870,26 +803,24 @@ Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null bool Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr) { - if (s && s[0]) + llvm::StringRef ref = llvm::StringRef(s).trim(); + if (ref.equals_lower("false") || + ref.equals_lower("off") || + ref.equals_lower("no") || + ref.equals_lower("0")) { - if (::strcasecmp (s, "false") == 0 || - ::strcasecmp (s, "off") == 0 || - ::strcasecmp (s, "no") == 0 || - ::strcmp (s, "0") == 0) - { - if (success_ptr) - *success_ptr = true; - return false; - } - else - if (::strcasecmp (s, "true") == 0 || - ::strcasecmp (s, "on") == 0 || - ::strcasecmp (s, "yes") == 0 || - ::strcmp (s, "1") == 0) - { - if (success_ptr) *success_ptr = true; - return true; - } + 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; return fail_value; @@ -1205,7 +1136,7 @@ Args::IsPositionalArgument (const char *arg) return false; bool is_positional = true; - char *cptr = (char *) arg; + const char *cptr = arg; if (cptr[0] == '%') { diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 6318b80a29ed..1da541b8c00f 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include <string> #include <vector> #include <stdlib.h> @@ -19,6 +17,7 @@ #include "../Commands/CommandObjectApropos.h" #include "../Commands/CommandObjectArgs.h" #include "../Commands/CommandObjectBreakpoint.h" +#include "../Commands/CommandObjectBugreport.h" #include "../Commands/CommandObjectDisassemble.h" #include "../Commands/CommandObjectExpression.h" #include "../Commands/CommandObjectFrame.h" @@ -40,6 +39,7 @@ #include "../Commands/CommandObjectType.h" #include "../Commands/CommandObjectVersion.h" #include "../Commands/CommandObjectWatchpoint.h" +#include "../Commands/CommandObjectLanguage.h" #include "lldb/Core/Debugger.h" @@ -60,6 +60,8 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Property.h" #include "lldb/Interpreter/ScriptInterpreterNone.h" #include "lldb/Interpreter/ScriptInterpreterPython.h" @@ -77,6 +79,7 @@ using namespace lldb; using namespace lldb_private; +static const char *k_white_space = " \t\v"; static PropertyDefinition g_properties[] = @@ -107,7 +110,7 @@ CommandInterpreter::CommandInterpreter ScriptLanguage script_language, bool synchronous_execution ) : - Broadcaster (&debugger, "lldb.command-interpreter"), + Broadcaster (&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand), m_debugger (debugger), @@ -147,6 +150,24 @@ CommandInterpreter::GetPromptOnQuit () const 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 { @@ -401,6 +422,7 @@ CommandInterpreter::LoadCommandDictionary () 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)); @@ -422,6 +444,7 @@ CommandInterpreter::LoadCommandDictionary () 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'"}, @@ -438,8 +461,14 @@ CommandInterpreter::LoadCommandDictionary () std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-break", - "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", - "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", + "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n", + "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12 // Break on line 12 of main.c\n" + "_regexp-break <linenum> # _regexp-break 12 // Break on line 12 of current file\n" + "_regexp-break <address> # _regexp-break 0x1234000 // Break on address 0x1234000\n" + "_regexp-break <name> # _regexp-break main // Break in 'main' after the prologue\n" + "_regexp-break &<name> # _regexp-break &main // Break on the first instruction in 'main'\n" + "_regexp-break <module>`<name> # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n" + "_regexp-break /<source-regex>/ # _regexp-break /break here/ // Break on all lines that match the regular expression 'break here' in the current file.\n", 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, @@ -1243,8 +1272,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) // eventually be invoked by the given command line. CommandObject *cmd_obj = nullptr; - std::string white_space (" \t\v"); - size_t start = command_string.find_first_not_of (white_space); + size_t start = command_string.find_first_not_of (k_white_space); size_t end = 0; bool done = false; while (!done) @@ -1252,7 +1280,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) if (start != std::string::npos) { // Get the next word from command_string. - end = command_string.find_first_of (white_space, start); + 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); @@ -1267,7 +1295,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 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 donee + else // cmd_word was not a valid sub-command word, so we are done done = true; } else @@ -1281,7 +1309,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) done = true; else - start = command_string.find_first_not_of (white_space, end); + start = command_string.find_first_not_of (k_white_space, end); } else // Unable to find any more words. @@ -1296,7 +1324,6 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) return cmd_obj; } -static const char *k_white_space = " \t\v"; static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; static void StripLeadingSpaces (std::string &s) @@ -1412,7 +1439,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name, CommandReturnObject &result) { CommandObject *alias_cmd_obj = nullptr; - Args cmd_args (raw_input_string.c_str()); + Args cmd_args (raw_input_string); alias_cmd_obj = GetCommandObject (alias_name); StreamString result_str; @@ -1442,10 +1469,10 @@ CommandInterpreter::BuildAliasResult (const char *alias_name, else { result_str.Printf (" %s", option.c_str()); - if (value_type != OptionParser::eOptionalArgument) - result_str.Printf (" "); - if (value.compare ("<OptionParser::eNoArgument>") != 0) + 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()); @@ -1456,7 +1483,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name, ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", index); result.SetStatus (eReturnStatusFailed); - return alias_cmd_obj; + return nullptr; } else { @@ -1481,7 +1508,7 @@ 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 proprocessed is anyting enclosed + // 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: @@ -1493,7 +1520,7 @@ CommandInterpreter::PreprocessCommand (std::string &command) { if (start_backtick > 0 && command[start_backtick-1] == '\\') { - // The backtick was preceeded by a '\' character, remove the slash + // 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 @@ -1622,9 +1649,6 @@ CommandInterpreter::HandleCommand (const char *command_line, { - bool done = false; - CommandObject *cmd_obj = nullptr; - bool wants_raw_input = false; std::string command_string (command_line); std::string original_command_string (command_line); @@ -1724,192 +1748,34 @@ CommandInterpreter::HandleCommand (const char *command_line, result.SetStatus(eReturnStatusFailed); return false; } - // Phase 1. - - // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object - // is for the specified command, and whether or not it wants raw input. 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 & replacement, resulting in three things: 1). the command - // object whose Execute method will actually be called; 2). a revised command string, with all substitutions & - // replacements taken care of; 3). whether or not the Execute function wants raw input or not. - - StreamString revised_command_line; - size_t actual_cmd_name_len = 0; - std::string next_word; - StringList matches; - while (!done) - { - char quote_char = '\0'; - std::string suffix; - ExtractCommand (command_string, next_word, suffix, quote_char); - if (cmd_obj == nullptr) - { - std::string full_name; - if (GetAliasFullName(next_word.c_str(), full_name)) - { - std::string alias_result; - cmd_obj = BuildAliasResult (full_name.c_str(), command_string, 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 - { - cmd_obj = GetCommandObject (next_word.c_str(), &matches); - if (cmd_obj) - { - actual_cmd_name_len += next_word.length(); - revised_command_line.Printf ("%s", next_word.c_str()); - 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) - { - actual_cmd_name_len += next_word.length() + 1; - revised_command_line.Printf (" %s", next_word.c_str()); - 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 { - // 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 false; - } - 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; - } - } - 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); + // Phase 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; - } + // 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 (!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 false; - } - } - break; - - default: - result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n", - suffix.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - - } - } - } - if (command_string.length() == 0) - done = true; - - } - - if (!command_string.empty()) - revised_command_line.Printf (" %s", command_string.c_str()); - - // End of Phase 1. - // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command - // specified was valid; revised_command_line contains the complete command line (including command name(s)), - // fully translated with all substitutions & translations taken care of (still in raw text format); and - // wants_raw_input specifies whether the Execute method expects raw input or not. - - if (log) { - log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); - log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData()); - log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); + log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); + 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. @@ -1920,7 +1786,7 @@ CommandInterpreter::HandleCommand (const char *command_line, { if (add_to_history) { - Args command_args (revised_command_line.GetData()); + 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); @@ -1930,18 +1796,13 @@ CommandInterpreter::HandleCommand (const char *command_line, m_command_history.AppendString (original_command_string); } - command_string = revised_command_line.GetData(); - std::string command_name (cmd_obj->GetCommandName()); 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); // Note: 'actual_cmd_name_len' may be considerably shorter - // than cmd_obj->GetCommandName(), because name completion - // allows users to enter short versions of the names, - // e.g. 'br s' for 'breakpoint set'. + remainder = command_string.substr (actual_cmd_name_len); // Remove any initial spaces - std::string white_space (" \t\v"); - size_t pos = remainder.find_first_not_of (white_space); + size_t pos = remainder.find_first_not_of (k_white_space); if (pos != 0 && pos != std::string::npos) remainder.erase(0, pos); @@ -1953,7 +1814,7 @@ CommandInterpreter::HandleCommand (const char *command_line, else { // We didn't find the first command object, so complete the first argument. - Args command_args (revised_command_line.GetData()); + Args command_args (command_string); StringList matches; int num_matches; int cursor_index = 0; @@ -2082,8 +1943,8 @@ CommandInterpreter::HandleCompletion (const char *current_line, // 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(current_line, last_char - current_line); - Args partial_parsed_line(current_line, cursor - current_line); + 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. @@ -2386,7 +2247,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, } cmd_args.Clear(); - cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); + cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); } else { @@ -2397,7 +2258,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, if (wants_raw_input) { cmd_args.Clear(); - cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); + cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); } return; } @@ -2413,7 +2274,7 @@ 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. - char *cptr = (char *) in_string; + const char *cptr = in_string; // Does it start with '%' if (cptr[0] == '%') @@ -3355,7 +3216,7 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, bool spawn_thread, CommandInterpreterRunOptions &options) { - // Always re-create the command intepreter when we run it in case + // 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)); @@ -3370,7 +3231,7 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, } else { - m_debugger.ExecuteIOHanders(); + m_debugger.ExecuteIOHandlers(); if (auto_handle_events) m_debugger.StopEventHandlerThread(); @@ -3378,3 +3239,179 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, } +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; + if (GetAliasFullName(next_word.c_str(), full_name)) + { + 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 + { + 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 { + // 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 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; + } + } + } + if (scratch_command.empty()) + done = true; + } + + if (!scratch_command.empty()) + revised_command_line.Printf(" %s", scratch_command.c_str()); + + if (cmd_obj != NULL) + command_line = revised_command_line.GetData(); + + return cmd_obj; +} diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index 753e720b0f6e..d67f76eba7b6 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/CommandObject.h" #include <string> @@ -25,13 +23,12 @@ // 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/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" using namespace lldb; using namespace lldb_private; @@ -123,6 +120,12 @@ CommandObject::SetHelp (const char *cstr) } void +CommandObject::SetHelp (std::string str) +{ + m_cmd_help_short = str; +} + +void CommandObject::SetHelpLong (const char *cstr) { m_cmd_help_long = cstr; @@ -221,20 +224,20 @@ CommandObject::CheckRequirements (CommandReturnObject &result) m_exe_ctx = m_interpreter.GetExecutionContext(); const uint32_t flags = GetFlags().Get(); - if (flags & (eFlagRequiresTarget | - eFlagRequiresProcess | - eFlagRequiresThread | - eFlagRequiresFrame | - eFlagTryTargetAPILock )) + if (flags & (eCommandRequiresTarget | + eCommandRequiresProcess | + eCommandRequiresThread | + eCommandRequiresFrame | + eCommandTryTargetAPILock )) { - if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope()) + if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) { result.AppendError (GetInvalidTargetDescription()); return false; } - if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope()) + if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) { if (!m_exe_ctx.HasTargetScope()) result.AppendError (GetInvalidTargetDescription()); @@ -243,7 +246,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result) return false; } - if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope()) + if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) { if (!m_exe_ctx.HasTargetScope()) result.AppendError (GetInvalidTargetDescription()); @@ -254,7 +257,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result) return false; } - if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope()) + if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) { if (!m_exe_ctx.HasTargetScope()) result.AppendError (GetInvalidTargetDescription()); @@ -267,13 +270,13 @@ CommandObject::CheckRequirements (CommandReturnObject &result) return false; } - if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr)) + if ((flags & eCommandRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr)) { result.AppendError (GetInvalidRegContextDescription()); return false; } - if (flags & eFlagTryTargetAPILock) + if (flags & eCommandTryTargetAPILock) { Target *target = m_exe_ctx.GetTargetPtr(); if (target) @@ -281,13 +284,13 @@ CommandObject::CheckRequirements (CommandReturnObject &result) } } - if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused)) + 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(CommandObject::eFlagProcessMustBeLaunched)) + if (GetFlags().Test(eCommandProcessMustBeLaunched)) { result.AppendError ("Process must exist."); result.SetStatus (eReturnStatusFailed); @@ -311,7 +314,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result) case eStateDetached: case eStateExited: case eStateUnloaded: - if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched)) + if (GetFlags().Test(eCommandProcessMustBeLaunched)) { result.AppendError ("Process must be launched."); result.SetStatus (eReturnStatusFailed); @@ -321,7 +324,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result) case eStateRunning: case eStateStepping: - if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused)) + if (GetFlags().Test(eCommandProcessMustBePaused)) { result.AppendError ("Process is running. Use 'process interrupt' to pause execution."); result.SetStatus (eReturnStatusFailed); @@ -499,14 +502,14 @@ CommandObject::GetArgumentEntryAtIndex (int idx) return nullptr; } -CommandObject::ArgumentTableEntry * +const CommandObject::ArgumentTableEntry * 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 (ArgumentTableEntry *) &(table[i]); + return &(table[i]); return nullptr; } @@ -515,7 +518,7 @@ void CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter) { const ArgumentTableEntry* table = CommandObject::GetArgumentTable(); - ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]); + const ArgumentTableEntry *entry = &(table[arg_type]); // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up... @@ -549,7 +552,7 @@ CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, Comma const char * CommandObject::GetArgumentName (CommandArgumentType arg_type) { - ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[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... @@ -843,12 +846,9 @@ LanguageTypeHelpTextCallback () StreamString sstr; sstr << "One of the following languages:\n"; - - for (unsigned int l = eLanguageTypeUnknown; l < eNumLanguageTypes; ++l) - { - sstr << " " << LanguageRuntime::GetNameForLanguageType(static_cast<LanguageType>(l)) << "\n"; - } - + + LanguageRuntime::PrintAllLanguages(sstr, " ", "\n"); + sstr.Flush(); std::string data = sstr.GetString(); @@ -1020,18 +1020,15 @@ CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType const char * CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type) { - if (arg_type >=0 && arg_type < eArgTypeLastArg) - return g_arguments_data[arg_type].arg_name; - return nullptr; - + 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) { - if (arg_type >=0 && arg_type < eArgTypeLastArg) - return g_arguments_data[arg_type].help_text; - return nullptr; + assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentDescriptionAsCString"); + return g_arguments_data[arg_type].help_text; } Target * @@ -1192,6 +1189,7 @@ CommandObject::g_arguments_data[] = { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." }, { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." }, { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." }, + { eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A type name." }, { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." }, { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." }, diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp index bde7f58b4cb0..1c3c3cdd5fdc 100644 --- a/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/source/Interpreter/CommandObjectRegexCommand.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/CommandObjectRegexCommand.h" // C Includes diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp index 9c67e4253301..31e5311ab441 100644 --- a/source/Interpreter/CommandObjectScript.cpp +++ b/source/Interpreter/CommandObjectScript.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectScript.h" // C Includes diff --git a/source/Interpreter/OptionGroupBoolean.cpp b/source/Interpreter/OptionGroupBoolean.cpp index 0c502cc364b4..6bd2743a6681 100644 --- a/source/Interpreter/OptionGroupBoolean.cpp +++ b/source/Interpreter/OptionGroupBoolean.cpp @@ -56,7 +56,7 @@ OptionGroupBoolean::SetOptionValue (CommandInterpreter &interpreter, } else { - error = m_value.SetValueFromCString (option_arg); + error = m_value.SetValueFromString (option_arg); } return error; } diff --git a/source/Interpreter/OptionGroupFile.cpp b/source/Interpreter/OptionGroupFile.cpp index 9bfe8ddf0282..a4b56409698e 100644 --- a/source/Interpreter/OptionGroupFile.cpp +++ b/source/Interpreter/OptionGroupFile.cpp @@ -47,7 +47,7 @@ OptionGroupFile::SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, const char *option_arg) { - Error error (m_file.SetValueFromCString (option_arg)); + Error error (m_file.SetValueFromString (option_arg)); return error; } @@ -88,7 +88,7 @@ OptionGroupFileList::SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, const char *option_arg) { - Error error (m_file_list.SetValueFromCString (option_arg)); + Error error (m_file_list.SetValueFromString (option_arg)); return error; } diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp index 601a78458730..08ff262d5428 100644 --- a/source/Interpreter/OptionGroupFormat.cpp +++ b/source/Interpreter/OptionGroupFormat.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionGroupFormat.h" // C Includes @@ -78,7 +76,7 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter, switch (short_option) { case 'f': - error = m_format.SetValueFromCString (option_arg); + error = m_format.SetValueFromString (option_arg); break; case 'c': @@ -88,7 +86,7 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter, } else { - error = m_count.SetValueFromCString (option_arg); + error = m_count.SetValueFromString (option_arg); if (m_count.GetCurrentValue() == 0) error.SetErrorStringWithFormat("invalid --count option value '%s'", option_arg); } @@ -101,7 +99,7 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter, } else { - error = m_byte_size.SetValueFromCString (option_arg); + error = m_byte_size.SetValueFromString (option_arg); if (m_byte_size.GetCurrentValue() == 0) error.SetErrorStringWithFormat("invalid --size option value '%s'", option_arg); } diff --git a/source/Interpreter/OptionGroupOutputFile.cpp b/source/Interpreter/OptionGroupOutputFile.cpp index ec9e166d2f05..e95cd35976ec 100644 --- a/source/Interpreter/OptionGroupOutputFile.cpp +++ b/source/Interpreter/OptionGroupOutputFile.cpp @@ -36,7 +36,7 @@ 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 the file specified with '--outfile <path>'."}, + "Append to the file specified with '--outfile <path>'."}, }; uint32_t @@ -62,7 +62,7 @@ OptionGroupOutputFile::SetOptionValue (CommandInterpreter &interpreter, switch (short_option) { case 'o': - error = m_file.SetValueFromCString (option_arg); + error = m_file.SetValueFromString (option_arg); break; case SHORT_OPTION_APND: diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp index 6bb36552d06b..6fa06d1eb8ed 100644 --- a/source/Interpreter/OptionGroupPlatform.cpp +++ b/source/Interpreter/OptionGroupPlatform.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionGroupPlatform.h" // C Includes diff --git a/source/Interpreter/OptionGroupString.cpp b/source/Interpreter/OptionGroupString.cpp index 9bc1c94d3a5a..e0291b154be2 100644 --- a/source/Interpreter/OptionGroupString.cpp +++ b/source/Interpreter/OptionGroupString.cpp @@ -48,7 +48,7 @@ OptionGroupString::SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, const char *option_arg) { - Error error (m_value.SetValueFromCString (option_arg)); + Error error (m_value.SetValueFromString (option_arg)); return error; } diff --git a/source/Interpreter/OptionGroupUInt64.cpp b/source/Interpreter/OptionGroupUInt64.cpp index 440c2a740c26..a922ab255968 100644 --- a/source/Interpreter/OptionGroupUInt64.cpp +++ b/source/Interpreter/OptionGroupUInt64.cpp @@ -48,7 +48,7 @@ OptionGroupUInt64::SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, const char *option_arg) { - Error error (m_value.SetValueFromCString (option_arg)); + Error error (m_value.SetValueFromString (option_arg)); return error; } diff --git a/source/Interpreter/OptionGroupUUID.cpp b/source/Interpreter/OptionGroupUUID.cpp index 43f7386c9ca6..609967a83e79 100644 --- a/source/Interpreter/OptionGroupUUID.cpp +++ b/source/Interpreter/OptionGroupUUID.cpp @@ -56,7 +56,7 @@ OptionGroupUUID::SetOptionValue (CommandInterpreter &interpreter, switch (short_option) { case 'u': - error = m_uuid.SetValueFromCString (option_arg); + error = m_uuid.SetValueFromString (option_arg); if (error.Success()) m_uuid.SetOptionWasSet(); break; diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 72d7ff597ab2..e5a5c004b2da 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" // C Includes diff --git a/source/Interpreter/OptionGroupVariable.cpp b/source/Interpreter/OptionGroupVariable.cpp index 05cf3f73bfed..092d60af9eb0 100644 --- a/source/Interpreter/OptionGroupVariable.cpp +++ b/source/Interpreter/OptionGroupVariable.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionGroupVariable.h" // C Includes diff --git a/source/Interpreter/OptionGroupWatchpoint.cpp b/source/Interpreter/OptionGroupWatchpoint.cpp index f4d8df1e6ba7..c6f4b8f8c8ea 100644 --- a/source/Interpreter/OptionGroupWatchpoint.cpp +++ b/source/Interpreter/OptionGroupWatchpoint.cpp @@ -41,7 +41,7 @@ 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, "xsize", 'x', OptionParser::eRequiredArgument, nullptr, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."} + { LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, nullptr, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."} }; @@ -87,7 +87,7 @@ OptionGroupWatchpoint::SetOptionValue (CommandInterpreter &interpreter, } break; } - case 'x': + case 's': watch_size = (uint32_t) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); break; diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp index 1e4ea23cc075..8f136a5b1c57 100644 --- a/source/Interpreter/OptionValue.cpp +++ b/source/Interpreter/OptionValue.cpp @@ -222,6 +222,22 @@ OptionValue::GetAsFormat () const return nullptr; } +OptionValueLanguage * +OptionValue::GetAsLanguage () +{ + if (GetType () == OptionValue::eTypeLanguage) + return static_cast<OptionValueLanguage *>(this); + return NULL; +} + +const OptionValueLanguage * +OptionValue::GetAsLanguage () const +{ + if (GetType () == OptionValue::eTypeLanguage) + return static_cast<const OptionValueLanguage *>(this); + return NULL; +} + OptionValueFormatEntity * OptionValue::GetAsFormatEntity () { @@ -468,6 +484,27 @@ OptionValue::SetFormatValue (lldb::Format new_value) 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 { @@ -589,6 +626,7 @@ OptionValue::GetBuiltinTypeAsCString (Type t) 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"; @@ -615,6 +653,7 @@ OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t 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; @@ -622,7 +661,7 @@ OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t } if (value_sp) - error = value_sp->SetValueFromCString (value_cstr, eVarSetOperationAssign); + error = value_sp->SetValueFromString (value_cstr, eVarSetOperationAssign); else error.SetErrorString("unsupported type mask"); return value_sp; @@ -664,7 +703,7 @@ OptionValue::AutoComplete (CommandInterpreter &interpreter, } Error -OptionValue::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValue::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; switch (op) diff --git a/source/Interpreter/OptionValueArch.cpp b/source/Interpreter/OptionValueArch.cpp index 7df149234bda..0e1ca07afd2e 100644 --- a/source/Interpreter/OptionValueArch.cpp +++ b/source/Interpreter/OptionValueArch.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueArch.h" // C Includes @@ -43,7 +41,7 @@ OptionValueArch::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint3 } Error -OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +OptionValueArch::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; switch (op) @@ -55,28 +53,23 @@ OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationTyp case eVarSetOperationReplace: case eVarSetOperationAssign: - if (value_cstr && value_cstr[0]) { - if (m_current_value.SetTriple (value_cstr)) + 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_cstr); - } - else - { - error.SetErrorString("invalid value string"); + error.SetErrorStringWithFormat("unsupported architecture '%s'", value_str.c_str()); + break; } - break; - case eVarSetOperationInsertBefore: case eVarSetOperationInsertAfter: case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp index 86d49c9ba3b4..aabe457534d6 100644 --- a/source/Interpreter/OptionValueArray.cpp +++ b/source/Interpreter/OptionValueArray.cpp @@ -74,11 +74,13 @@ OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint } Error -OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValueArray::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { - Args args(value); - NotifyValueChanged(); - return SetArgs (args, op); + Args args(value.str().c_str()); + Error error = SetArgs (args, op); + if (error.Success()) + NotifyValueChanged(); + return error; } @@ -342,6 +344,8 @@ OptionValueArray::DeepCopy () const { OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump); lldb::OptionValueSP copied_value_sp(copied_array); + *static_cast<OptionValue *>(copied_array) = *this; + copied_array->m_callback = m_callback; const uint32_t size = m_values.size(); for (uint32_t i = 0; i<size; ++i) { diff --git a/source/Interpreter/OptionValueBoolean.cpp b/source/Interpreter/OptionValueBoolean.cpp index 71cc2afb98e1..dae1f4b7a76d 100644 --- a/source/Interpreter/OptionValueBoolean.cpp +++ b/source/Interpreter/OptionValueBoolean.cpp @@ -37,7 +37,7 @@ OptionValueBoolean::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, ui } Error -OptionValueBoolean::SetValueFromCString (const char *value_cstr, +OptionValueBoolean::SetValueFromString (llvm::StringRef value_str, VarSetOperationType op) { Error error; @@ -52,7 +52,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, case eVarSetOperationAssign: { bool success = false; - bool value = Args::StringToBoolean(value_cstr, false, &success); + bool value = Args::StringToBoolean(value_str.str().c_str(), false, &success); if (success) { m_value_was_set = true; @@ -61,12 +61,11 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, } else { - if (value_cstr == nullptr) - error.SetErrorString ("invalid boolean string value: NULL"); - else if (value_cstr[0] == '\0') + if (value_str.size() == 0) error.SetErrorString ("invalid boolean string value <empty>"); else - error.SetErrorStringWithFormat ("invalid boolean string value: '%s'", value_cstr); + error.SetErrorStringWithFormat ("invalid boolean string value: '%s'", + value_str.str().c_str()); } } break; @@ -76,7 +75,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value_str, op); break; } return error; diff --git a/source/Interpreter/OptionValueChar.cpp b/source/Interpreter/OptionValueChar.cpp index 7a0135314c81..b5ef1d346aea 100644 --- a/source/Interpreter/OptionValueChar.cpp +++ b/source/Interpreter/OptionValueChar.cpp @@ -39,7 +39,7 @@ OptionValueChar::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint3 } Error -OptionValueChar::SetValueFromCString (const char *value_cstr, +OptionValueChar::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; @@ -53,19 +53,19 @@ OptionValueChar::SetValueFromCString (const char *value_cstr, case eVarSetOperationAssign: { bool success = false; - char char_value = Args::StringToChar(value_cstr, '\0', &success); + char char_value = Args::StringToChar(value.str().c_str(), '\0', &success); if (success) { m_current_value = char_value; m_value_was_set = true; } else - error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character", value_cstr); + error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character", value.str().c_str()); } break; default: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value.str().c_str(), op); break; } return error; diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp index e5299f8cc390..24eeec3b3285 100644 --- a/source/Interpreter/OptionValueDictionary.cpp +++ b/source/Interpreter/OptionValueDictionary.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueDictionary.h" // C Includes @@ -119,6 +117,12 @@ OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op) 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<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('=')); llvm::StringRef key = kvp.first; bool key_valid = false; @@ -126,7 +130,7 @@ OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op) { if (key.front() == '[') { - // Key name starts with '[', so the the key value must be in single or double quotes like: + // Key name starts with '[', so the key value must be in single or double quotes like: // ['<key>'] // ["<key>"] if ((key.size() > 2) && (key.back() == ']')) @@ -211,16 +215,16 @@ OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op) case eVarSetOperationInsertBefore: case eVarSetOperationInsertAfter: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (nullptr, op); + error = OptionValue::SetValueFromString (llvm::StringRef(), op); break; } return error; } Error -OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +OptionValueDictionary::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { - Args args(value_cstr); + Args args(value.str().c_str()); Error error = SetArgs (args, op); if (error.Success()) NotifyValueChanged(); @@ -320,7 +324,7 @@ OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char } if (!value_sp && error.AsCString() == nullptr) { - error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimitted by single or double quotes", + error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimited by single or double quotes", name, GetTypeAsCString()); } @@ -335,7 +339,7 @@ OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOpera const bool will_modify = true; lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); if (value_sp) - error = value_sp->SetValueFromCString(value, op); + error = value_sp->SetValueFromString(value, op); else { if (error.AsCString() == nullptr) @@ -381,7 +385,7 @@ OptionValueDictionary::SetStringValueForKey (const ConstString &key, return false; if (pos->second->GetType() == OptionValue::eTypeString) { - pos->second->SetValueFromCString(value); + pos->second->SetValueFromString(value); return true; } } diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp index dbaeb185fa3a..0f163d1c4f74 100644 --- a/source/Interpreter/OptionValueEnumeration.cpp +++ b/source/Interpreter/OptionValueEnumeration.cpp @@ -55,7 +55,7 @@ OptionValueEnumeration::DumpValue (const ExecutionContext *exe_ctx, Stream &strm } Error -OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValueEnumeration::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; switch (op) @@ -67,9 +67,8 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT case eVarSetOperationReplace: case eVarSetOperationAssign: - if (value && value[0]) { - ConstString const_enumerator_name(value); + ConstString const_enumerator_name(value.trim()); const EnumerationMapEntry *enumerator_entry = m_enumerations.FindFirstValueForName (const_enumerator_name.GetCString()); if (enumerator_entry) { @@ -79,7 +78,7 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT else { StreamString error_strm; - error_strm.Printf("invalid enumeration value '%s'", value); + error_strm.Printf("invalid enumeration value '%s'", value.str().c_str()); const size_t count = m_enumerations.GetSize (); if (count) { @@ -91,19 +90,15 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT } error.SetErrorString(error_strm.GetData()); } + break; } - else - { - error.SetErrorString("invalid enumeration value"); - } - break; case eVarSetOperationInsertBefore: case eVarSetOperationInsertAfter: case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp index 3f466985a83a..3a282f177fea 100644 --- a/source/Interpreter/OptionValueFileSpec.cpp +++ b/source/Interpreter/OptionValueFileSpec.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueFileSpec.h" // C Includes @@ -24,31 +22,39 @@ using namespace lldb; using namespace lldb_private; -OptionValueFileSpec::OptionValueFileSpec () : +OptionValueFileSpec::OptionValueFileSpec (bool resolve) : OptionValue(), m_current_value (), m_default_value (), m_data_sp(), - m_completion_mask (CommandCompletions::eDiskFileCompletion) + m_data_mod_time (), + m_completion_mask (CommandCompletions::eDiskFileCompletion), + m_resolve (resolve) { } -OptionValueFileSpec::OptionValueFileSpec (const FileSpec &value) : +OptionValueFileSpec::OptionValueFileSpec (const FileSpec &value, + bool resolve) : OptionValue(), m_current_value (value), m_default_value (value), m_data_sp(), - m_completion_mask (CommandCompletions::eDiskFileCompletion) + m_data_mod_time (), + m_completion_mask (CommandCompletions::eDiskFileCompletion), + m_resolve (resolve) { } OptionValueFileSpec::OptionValueFileSpec (const FileSpec ¤t_value, - const FileSpec &default_value) : + const FileSpec &default_value, + bool resolve) : OptionValue(), m_current_value (current_value), m_default_value (default_value), m_data_sp(), - m_completion_mask (CommandCompletions::eDiskFileCompletion) + m_data_mod_time (), + m_completion_mask (CommandCompletions::eDiskFileCompletion), + m_resolve (resolve) { } @@ -70,7 +76,7 @@ OptionValueFileSpec::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, u } Error -OptionValueFileSpec::SetValueFromCString (const char *value_cstr, +OptionValueFileSpec::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; @@ -83,24 +89,18 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, case eVarSetOperationReplace: case eVarSetOperationAssign: - if (value_cstr && value_cstr[0]) + 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. - std::string filepath(value_cstr); - auto prefix_chars_to_trim = filepath.find_first_not_of ("\"' \t"); - if (prefix_chars_to_trim != std::string::npos && prefix_chars_to_trim > 0) - filepath.erase(0, prefix_chars_to_trim); - auto suffix_chars_to_trim = filepath.find_last_not_of ("\"' \t"); - if (suffix_chars_to_trim != std::string::npos && suffix_chars_to_trim < filepath.size()) - filepath.erase (suffix_chars_to_trim + 1); - + value = value.trim("\"' \t"); m_value_was_set = true; - m_current_value.SetFile(filepath.c_str(), true); + m_current_value.SetFile(value.str().c_str(), m_resolve); m_data_sp.reset(); + m_data_mod_time.Clear(); NotifyValueChanged(); } else @@ -114,7 +114,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; @@ -153,12 +153,16 @@ OptionValueFileSpec::AutoComplete (CommandInterpreter &interpreter, const lldb::DataBufferSP & OptionValueFileSpec::GetFileContents(bool null_terminate) { - if (!m_data_sp && m_current_value) + 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/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecLIst.cpp index 0e696ca91db6..669d3ee33acc 100644 --- a/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/source/Interpreter/OptionValueFileSpecLIst.cpp @@ -42,10 +42,10 @@ OptionValueFileSpecList::DumpValue (const ExecutionContext *exe_ctx, Stream &str } Error -OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValueFileSpecList::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; - Args args(value); + Args args(value.str().c_str()); const size_t argc = args.GetArgumentCount(); switch (op) @@ -174,7 +174,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation break; case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/OptionValueFormat.cpp b/source/Interpreter/OptionValueFormat.cpp index d91f10b0edeb..1d73d58ce8e1 100644 --- a/source/Interpreter/OptionValueFormat.cpp +++ b/source/Interpreter/OptionValueFormat.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueFormat.h" // C Includes @@ -36,7 +34,7 @@ OptionValueFormat::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uin } Error -OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +OptionValueFormat::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; switch (op) @@ -50,7 +48,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationAssign: { Format new_format; - error = Args::StringToFormat (value_cstr, new_format, nullptr); + error = Args::StringToFormat (value.str().c_str(), new_format, nullptr); if (error.Success()) { m_value_was_set = true; @@ -65,7 +63,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/OptionValueFormatEntity.cpp b/source/Interpreter/OptionValueFormatEntity.cpp index fb8c682a03f8..66d8d8419ed8 100644 --- a/source/Interpreter/OptionValueFormatEntity.cpp +++ b/source/Interpreter/OptionValueFormatEntity.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueFormatEntity.h" // C Includes @@ -67,8 +65,8 @@ OptionValueFormatEntity::DumpValue (const ExecutionContext *exe_ctx, Stream &str } Error -OptionValueFormatEntity::SetValueFromCString (const char *value_cstr, - VarSetOperationType op) +OptionValueFormatEntity::SetValueFromString (llvm::StringRef value_str, + VarSetOperationType op) { Error error; switch (op) @@ -81,13 +79,31 @@ OptionValueFormatEntity::SetValueFromCString (const char *value_cstr, 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; - llvm::StringRef value_str(value_cstr); error = FormatEntity::Parse(value_str, entry); if (error.Success()) { m_current_entry = std::move(entry); - m_current_format = value_cstr; + m_current_format = value_str; m_value_was_set = true; NotifyValueChanged(); } @@ -99,7 +115,7 @@ OptionValueFormatEntity::SetValueFromCString (const char *value_cstr, case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value_str, op); break; } return error; diff --git a/source/Interpreter/OptionValueLanguage.cpp b/source/Interpreter/OptionValueLanguage.cpp new file mode 100644 index 000000000000..fd46553dabde --- /dev/null +++ b/source/Interpreter/OptionValueLanguage.cpp @@ -0,0 +1,73 @@ +//===-- OptionValueFormat.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Interpreter/OptionValueLanguage.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Stream.h" +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Target/LanguageRuntime.h" + +using namespace lldb; +using namespace lldb_private; + +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.PutCString (" = "); + strm.PutCString (LanguageRuntime::GetNameForLanguageType(m_current_value)); + } +} + +Error +OptionValueLanguage::SetValueFromString (llvm::StringRef value, VarSetOperationType op) +{ + Error error; + switch (op) + { + case eVarSetOperationClear: + Clear(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + { + LanguageType new_type = LanguageRuntime::GetLanguageTypeFromString(value.data()); + m_value_was_set = true; + m_current_value = new_type; + } + break; + + 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/source/Interpreter/OptionValuePathMappings.cpp b/source/Interpreter/OptionValuePathMappings.cpp index b1e714e97073..722d6a144279 100644 --- a/source/Interpreter/OptionValuePathMappings.cpp +++ b/source/Interpreter/OptionValuePathMappings.cpp @@ -34,10 +34,10 @@ OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &str } Error -OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; - Args args(value); + Args args(value.str().c_str()); const size_t argc = args.GetArgumentCount(); switch (op) @@ -175,7 +175,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation break; case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp index cf7abaa6ac25..e8d870a99cf8 100644 --- a/source/Interpreter/OptionValueProperties.cpp +++ b/source/Interpreter/OptionValueProperties.cpp @@ -226,7 +226,7 @@ OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx, const bool will_modify = true; lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); if (value_sp) - error = value_sp->SetValueFromCString(value, op); + error = value_sp->SetValueFromString(value ? llvm::StringRef(value) : llvm::StringRef(), op); else { if (error.AsCString() == nullptr) @@ -600,7 +600,7 @@ OptionValueProperties::Clear () Error -OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationType op) +OptionValueProperties::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; @@ -619,7 +619,7 @@ OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationTy case eVarSetOperationInsertAfter: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value, op); + error = OptionValue::SetValueFromString (value, op); break; } diff --git a/source/Interpreter/OptionValueRegex.cpp b/source/Interpreter/OptionValueRegex.cpp index fab462f0e704..ebe7ae2feb91 100644 --- a/source/Interpreter/OptionValueRegex.cpp +++ b/source/Interpreter/OptionValueRegex.cpp @@ -41,7 +41,7 @@ OptionValueRegex::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint } Error -OptionValueRegex::SetValueFromCString (const char *value_cstr, +OptionValueRegex::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; @@ -52,7 +52,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, case eVarSetOperationInsertAfter: case eVarSetOperationRemove: case eVarSetOperationAppend: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; case eVarSetOperationClear: @@ -62,7 +62,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, case eVarSetOperationReplace: case eVarSetOperationAssign: - if (m_regex.Compile (value_cstr)) + if (m_regex.Compile (value.str().c_str())) { m_value_was_set = true; NotifyValueChanged(); diff --git a/source/Interpreter/OptionValueSInt64.cpp b/source/Interpreter/OptionValueSInt64.cpp index c69172921a6d..97cdf10b7c75 100644 --- a/source/Interpreter/OptionValueSInt64.cpp +++ b/source/Interpreter/OptionValueSInt64.cpp @@ -36,9 +36,8 @@ OptionValueSInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uin } Error -OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +OptionValueSInt64::SetValueFromString (llvm::StringRef value_ref, VarSetOperationType op) { - //printf ("%p: SetValueFromCString (s=\"%s\", op=%i)\n", this, value_cstr, op); Error error; switch (op) { @@ -51,7 +50,8 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationAssign: { bool success = false; - int64_t value = StringConvert::ToSInt64 (value_cstr, 0, 0, &success); + 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) @@ -68,7 +68,8 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT } else { - error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'", value_cstr); + error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'", + value_ref.str().c_str()); } } break; @@ -78,7 +79,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value_ref, op); break; } return error; diff --git a/source/Interpreter/OptionValueString.cpp b/source/Interpreter/OptionValueString.cpp index a1b80d8fc4f6..63f006e643f9 100644 --- a/source/Interpreter/OptionValueString.cpp +++ b/source/Interpreter/OptionValueString.cpp @@ -51,30 +51,30 @@ OptionValueString::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uin } Error -OptionValueString::SetValueFromCString (const char *value_cstr, +OptionValueString::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; - std::string value_str_no_quotes; - if (value_cstr) + std::string value_str = value.str(); + value = value.trim(); + if (value.size() > 0) { - switch (value_cstr[0]) + switch (value.front()) { case '"': case '\'': { - size_t len = strlen(value_cstr); - if (len <= 1 || value_cstr[len-1] != value_cstr[0]) + if (value.size() <= 1 || value.back() != value.front()) { error.SetErrorString("mismatched quotes"); return error; } - value_str_no_quotes.assign (value_cstr + 1, len - 2); - value_cstr = value_str_no_quotes.c_str(); + value = value.drop_front().drop_back(); } break; } + value_str = value.str(); } switch (op) @@ -85,26 +85,26 @@ OptionValueString::SetValueFromCString (const char *value_cstr, case eVarSetOperationRemove: if (m_validator) { - error = m_validator(value_cstr,m_validator_baton); + error = m_validator(value_str.c_str(),m_validator_baton); if (error.Fail()) return error; } - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; case eVarSetOperationAppend: { std::string new_value(m_current_value); - if (value_cstr && value_cstr[0]) + if (value.size() > 0) { if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) { std::string str; - Args::EncodeEscapeSequences (value_cstr, str); + Args::EncodeEscapeSequences (value_str.c_str(), str); new_value.append(str); } else - new_value.append(value_cstr); + new_value.append(value); } if (m_validator) { @@ -126,18 +126,18 @@ OptionValueString::SetValueFromCString (const char *value_cstr, case eVarSetOperationAssign: if (m_validator) { - error = m_validator(value_cstr,m_validator_baton); + 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_cstr, m_current_value); + Args::EncodeEscapeSequences (value_str.c_str(), m_current_value); } else { - SetCurrentValue (value_cstr); + SetCurrentValue (value_str.c_str()); } NotifyValueChanged(); break; diff --git a/source/Interpreter/OptionValueUInt64.cpp b/source/Interpreter/OptionValueUInt64.cpp index 48de433d36c1..b414802b963b 100644 --- a/source/Interpreter/OptionValueUInt64.cpp +++ b/source/Interpreter/OptionValueUInt64.cpp @@ -23,7 +23,7 @@ lldb::OptionValueSP OptionValueUInt64::Create (const char *value_cstr, Error &error) { lldb::OptionValueSP value_sp (new OptionValueUInt64()); - error = value_sp->SetValueFromCString (value_cstr); + error = value_sp->SetValueFromString (value_cstr); if (error.Fail()) value_sp.reset(); return value_sp; @@ -44,7 +44,7 @@ OptionValueUInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uin } Error -OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationType op) +OptionValueUInt64::SetValueFromString (llvm::StringRef value_ref, VarSetOperationType op) { Error error; switch (op) @@ -58,7 +58,8 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationAssign: { bool success = false; - uint64_t value = StringConvert::ToUInt64 (value_cstr, 0, 0, &success); + 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; @@ -67,7 +68,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT } else { - error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_cstr); + error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_str.c_str()); } } break; @@ -77,7 +78,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value_ref, op); break; } return error; diff --git a/source/Interpreter/OptionValueUUID.cpp b/source/Interpreter/OptionValueUUID.cpp index c228cf6e415e..b16a9eb7e994 100644 --- a/source/Interpreter/OptionValueUUID.cpp +++ b/source/Interpreter/OptionValueUUID.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/OptionValueUUID.h" // C Includes @@ -37,7 +35,7 @@ OptionValueUUID::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint3 } Error -OptionValueUUID::SetValueFromCString (const char *value_cstr, +OptionValueUUID::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; @@ -51,8 +49,8 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, case eVarSetOperationReplace: case eVarSetOperationAssign: { - if (m_uuid.SetFromCString(value_cstr) == 0) - error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr); + 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; @@ -66,7 +64,7 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, case eVarSetOperationRemove: case eVarSetOperationAppend: case eVarSetOperationInvalid: - error = OptionValue::SetValueFromCString (value_cstr, op); + error = OptionValue::SetValueFromString (value, op); break; } return error; diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp index a8766f5f8615..7f0e0abc03ea 100644 --- a/source/Interpreter/Options.cpp +++ b/source/Interpreter/Options.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/Options.h" // C Includes @@ -944,7 +942,7 @@ Options::HandleOptionArgumentCompletion lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type; if (option_arg_type != eArgTypeNone) { - CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type); + const CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type); if (arg_entry) completion_mask = arg_entry->completion_type; } diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp index 5679ef8dd3ba..077fcbc54cc3 100644 --- a/source/Interpreter/Property.cpp +++ b/source/Interpreter/Property.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/Property.h" // C Includes @@ -19,6 +17,7 @@ #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValues.h" +#include "lldb/Target/LanguageRuntime.h" using namespace lldb; using namespace lldb_private; @@ -80,11 +79,11 @@ Property::Property (const PropertyDefinition &definition) : m_value_sp.reset (enum_value); if (definition.default_cstr_value) { - if (enum_value->SetValueFromCString(definition.default_cstr_value).Success()) + 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 SetValueFromCString() above. + // 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(); @@ -94,10 +93,13 @@ Property::Property (const PropertyDefinition &definition) : break; case OptionValue::eTypeFileSpec: + { // "definition.default_uint_value" represents if the "definition.default_cstr_value" should // be resolved or not - m_value_sp.reset (new OptionValueFileSpec(FileSpec(definition.default_cstr_value, definition.default_uint_value != 0))); + 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 @@ -119,6 +121,21 @@ Property::Property (const PropertyDefinition &definition) : } 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) + LanguageRuntime::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)); diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp index 3ea6c0dbe3e5..a581a0b3601a 100644 --- a/source/Interpreter/PythonDataObjects.cpp +++ b/source/Interpreter/PythonDataObjects.cpp @@ -23,19 +23,20 @@ #include "lldb/Host/File.h" #include "lldb/Interpreter/PythonDataObjects.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" using namespace lldb_private; using namespace lldb; +void +StructuredPythonObject::Dump(Stream &s) const +{ + s << "Python Obj: 0x" << GetValue(); +} + //---------------------------------------------------------------------- // PythonObject //---------------------------------------------------------------------- -PythonObject::PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp) : - m_py_obj (nullptr) -{ - if (script_object_sp) - Reset ((PyObject *)script_object_sp->GetObject()); -} void PythonObject::Dump (Stream &strm) const @@ -62,6 +63,23 @@ PythonObject::Dump (Stream &strm) const strm.PutCString ("NULL"); } +PyObjectType +PythonObject::GetObjectType() const +{ + if (IsNULLOrNone()) + return PyObjectType::None; + + if (PyList_Check(m_py_obj)) + return PyObjectType::List; + if (PyDict_Check(m_py_obj)) + return PyObjectType::Dictionary; + if (PyString_Check(m_py_obj)) + return PyObjectType::String; + if (PyInt_Check(m_py_obj) || PyLong_Check(m_py_obj)) + return PyObjectType::Integer; + return PyObjectType::Unknown; +} + PythonString PythonObject::Repr () { @@ -90,6 +108,26 @@ PythonObject::IsNULLOrNone () const return ((m_py_obj == nullptr) || (m_py_obj == Py_None)); } +StructuredData::ObjectSP +PythonObject::CreateStructuredObject() const +{ + switch (GetObjectType()) + { + case PyObjectType::Dictionary: + return PythonDictionary(m_py_obj).CreateStructuredDictionary(); + case PyObjectType::Integer: + return PythonInteger(m_py_obj).CreateStructuredInteger(); + case PyObjectType::List: + return PythonList(m_py_obj).CreateStructuredArray(); + case PyObjectType::String: + return PythonString(m_py_obj).CreateStructuredString(); + case PyObjectType::None: + return StructuredData::ObjectSP(); + default: + return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); + } +} + //---------------------------------------------------------------------- // PythonString //---------------------------------------------------------------------- @@ -106,14 +144,12 @@ PythonString::PythonString (const PythonObject &object) : Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string } -PythonString::PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp) : - PythonObject() +PythonString::PythonString (llvm::StringRef string) : + PythonObject(PyString_FromStringAndSize(string.data(), string.size())) { - if (script_object_sp) - Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a string } -PythonString::PythonString (const char* string) : +PythonString::PythonString(const char *string) : PythonObject(PyString_FromString(string)) { } @@ -137,12 +173,12 @@ PythonString::Reset (PyObject *py_obj) return py_obj == nullptr; } -const char* +llvm::StringRef PythonString::GetString() const { if (m_py_obj) - return PyString_AsString(m_py_obj); - return nullptr; + return llvm::StringRef(PyString_AsString(m_py_obj), GetSize()); + return llvm::StringRef(); } size_t @@ -154,9 +190,17 @@ PythonString::GetSize() const } void -PythonString::SetString (const char* string) +PythonString::SetString (llvm::StringRef string) { - PythonObject::Reset(PyString_FromString(string)); + PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size())); +} + +StructuredData::StringSP +PythonString::CreateStructuredString() const +{ + StructuredData::StringSP result(new StructuredData::String); + result->SetValue(GetString()); + return result; } //---------------------------------------------------------------------- @@ -175,13 +219,6 @@ PythonInteger::PythonInteger (const PythonObject &object) : Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type } -PythonInteger::PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp) : - PythonObject() -{ - if (script_object_sp) - Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a string -} - PythonInteger::PythonInteger (int64_t value) : PythonObject() { @@ -207,7 +244,7 @@ PythonInteger::Reset (PyObject *py_obj) } int64_t -PythonInteger::GetInteger() +PythonInteger::GetInteger() const { if (m_py_obj) { @@ -225,6 +262,14 @@ PythonInteger::SetInteger (int64_t value) PythonObject::Reset(PyLong_FromLongLong(value)); } +StructuredData::IntegerSP +PythonInteger::CreateStructuredInteger() const +{ + StructuredData::IntegerSP result(new StructuredData::Integer); + result->SetValue(GetInteger()); + return result; +} + //---------------------------------------------------------------------- // PythonList //---------------------------------------------------------------------- @@ -252,13 +297,6 @@ PythonList::PythonList (const PythonObject &object) : Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list } -PythonList::PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp) : - PythonObject() -{ - if (script_object_sp) - Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a list -} - PythonList::~PythonList () { } @@ -274,7 +312,7 @@ PythonList::Reset (PyObject *py_obj) } uint32_t -PythonList::GetSize() +PythonList::GetSize() const { if (m_py_obj) return PyList_GET_SIZE(m_py_obj); @@ -282,7 +320,7 @@ PythonList::GetSize() } PythonObject -PythonList::GetItemAtIndex (uint32_t index) +PythonList::GetItemAtIndex(uint32_t index) const { if (m_py_obj) return PythonObject(PyList_GetItem(m_py_obj, index)); @@ -303,6 +341,19 @@ PythonList::AppendItem (const PythonObject &object) PyList_Append(m_py_obj, object.get()); } +StructuredData::ArraySP +PythonList::CreateStructuredArray() const +{ + StructuredData::ArraySP result(new StructuredData::Array); + uint32_t count = GetSize(); + for (uint32_t i = 0; i < count; ++i) + { + PythonObject obj = GetItemAtIndex(i); + result->AddItem(obj.CreateStructuredObject()); + } + return result; +} + //---------------------------------------------------------------------- // PythonDictionary //---------------------------------------------------------------------- @@ -325,13 +376,6 @@ PythonDictionary::PythonDictionary (const PythonObject &object) : Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary } -PythonDictionary::PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp) : - PythonObject () -{ - if (script_object_sp) - Reset((PyObject *)script_object_sp->GetObject()); // Use "Reset()" to ensure that py_obj is a dictionary -} - PythonDictionary::~PythonDictionary () { } @@ -347,7 +391,7 @@ PythonDictionary::Reset (PyObject *py_obj) } uint32_t -PythonDictionary::GetSize() +PythonDictionary::GetSize() const { if (m_py_obj) return PyDict_Size(m_py_obj); @@ -460,4 +504,21 @@ PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &va PyDict_SetItem(m_py_obj, key.get(), value.get()); } +StructuredData::DictionarySP +PythonDictionary::CreateStructuredDictionary() const +{ + StructuredData::DictionarySP result(new StructuredData::Dictionary); + PythonList keys(GetKeys()); + uint32_t num_keys = keys.GetSize(); + for (uint32_t i = 0; i < num_keys; ++i) + { + PythonObject key = keys.GetItemAtIndex(i); + PythonString key_str = key.Str(); + PythonObject value = GetItemForKey(key); + StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); + result->AddItem(key_str.GetString(), structured_value); + } + return result; +} + #endif diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp index 45e3b44cc0ac..f1ec50e663fd 100644 --- a/source/Interpreter/ScriptInterpreter.cpp +++ b/source/Interpreter/ScriptInterpreter.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/ScriptInterpreter.h" #include <string> @@ -19,7 +17,6 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StringList.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Utility/PseudoTerminal.h" using namespace lldb; @@ -110,57 +107,3 @@ ScriptInterpreter::AcquireInterpreterLock () { return std::unique_ptr<ScriptInterpreterLocker>(new ScriptInterpreterLocker()); } - -void -ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction swig_breakpoint_callback, - SWIGWatchpointCallbackFunction swig_watchpoint_callback, - SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, - SWIGPythonCreateSyntheticProvider swig_synthetic_script, - SWIGPythonCalculateNumChildren swig_calc_children, - SWIGPythonGetChildAtIndex swig_get_child_index, - SWIGPythonGetIndexOfChildWithName swig_get_index_child, - SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , - SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, - SWIGPythonUpdateSynthProviderInstance swig_update_provider, - SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, - SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, - SWIGPythonCallCommand swig_call_command, - SWIGPythonCallModuleInit swig_call_module_init, - SWIGPythonCreateOSPlugin swig_create_os_plugin, - SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, - SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, - SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, - SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, - SWIGPython_GetDynamicSetting swig_plugin_get, - SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, - SWIGPythonCallThreadPlan swig_call_thread_plan) -{ -#ifndef LLDB_DISABLE_PYTHON - ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, - swig_breakpoint_callback, - swig_watchpoint_callback, - swig_typescript_callback, - swig_synthetic_script, - swig_calc_children, - swig_get_child_index, - swig_get_index_child, - swig_cast_to_sbvalue , - swig_get_valobj_sp_from_sbvalue, - swig_update_provider, - swig_mighthavechildren_provider, - swig_getvalue_provider, - swig_call_command, - swig_call_module_init, - swig_create_os_plugin, - swig_run_script_keyword_process, - swig_run_script_keyword_thread, - swig_run_script_keyword_target, - swig_run_script_keyword_frame, - swig_run_script_keyword_value, - swig_plugin_get, - swig_thread_plan_script, - swig_call_thread_plan); -#endif // #ifndef LLDB_DISABLE_PYTHON -} diff --git a/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp index e33480d1a6d5..909a1161c9c1 100644 --- a/source/Interpreter/ScriptInterpreterNone.cpp +++ b/source/Interpreter/ScriptInterpreterNone.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/ScriptInterpreterNone.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp index 8155cbb189fe..8f60793550c3 100644 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ b/source/Interpreter/ScriptInterpreterPython.cpp @@ -30,6 +30,8 @@ #include "lldb/Core/Communication.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" @@ -43,34 +45,39 @@ #include "lldb/Host/windows/ConnectionGenericFileWindows.h" #endif +#include "llvm/ADT/StringRef.h" + using namespace lldb; using namespace lldb_private; - -static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = nullptr; -static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; -static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; -static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; -static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; -static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; -static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; -static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; -static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; -static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; -static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; -static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; -static ScriptInterpreter::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; -static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr; -static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; -static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; -static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; -static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; -static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; -static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; -static ScriptInterpreter::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; -static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; -static ScriptInterpreter::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; -static ScriptInterpreter::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; +static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr; +static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; +static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; +static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr; +static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; +static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; +static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; +static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; +static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; +static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr; +static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr; +static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; +static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; +static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; + +static bool g_initialized = false; static std::string ReadPythonBacktrace (PyObject* py_backtrace); @@ -171,8 +178,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete m_lock_count (0), m_command_thread_state (nullptr) { - - ScriptInterpreterPython::InitializePrivate (); + assert(g_initialized && "ScriptInterpreterPython created but initialize has not been called!"); m_dictionary_name.append("_dict"); StreamString run_string; @@ -185,17 +191,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete run_string.Clear(); - // Importing 'lldb' module calls SBDebugger::Initialize, which calls Debugger::Initialize, which increments a - // global debugger ref-count; therefore we need to check the ref-count before and after importing lldb, and if the - // ref-count increased we need to call Debugger::Terminate here to decrement the ref-count so that when the final - // call to Debugger::Terminate is made, the ref-count has the correct value. - // - // Bonus question: Why doesn't the ref-count always increase? Because sometimes lldb has already been imported, in - // which case the code inside it, including the call to SBDebugger::Initialize(), does not get executed. - - int old_count = Debugger::TestDebuggerRefCount(); - - run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); + run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); PyRun_SimpleString (run_string.GetData()); // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set @@ -205,11 +201,6 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete PyRun_SimpleString (run_string.GetData()); run_string.Clear(); - int new_count = Debugger::TestDebuggerRefCount(); - - if (new_count > old_count) - Debugger::Terminate(); - run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str()); PyRun_SimpleString (run_string.GetData()); run_string.Clear(); @@ -393,6 +384,13 @@ ScriptInterpreterPython::LeaveSession () m_session_is_active = false; } +static PyObject * +PyFile_FromFile_Const(FILE *fp, const char *name, const char *mode, int (*close)(FILE *)) +{ + // Read through the Python source, doesn't seem to modify these strings + return PyFile_FromFile(fp, const_cast<char*>(name), const_cast<char*>(mode), close); +} + bool ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, FILE *in, @@ -458,7 +456,7 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, { m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); // This call can deadlock your process if the file is locked - PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); + PyObject *new_file = PyFile_FromFile_Const (in, "", "r", nullptr); sys_module_dict.SetItemForKey ("stdin", new_file); Py_DECREF (new_file); } @@ -470,7 +468,7 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, { m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout")); - PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", nullptr); + PyObject *new_file = PyFile_FromFile_Const (out, "", "w", nullptr); sys_module_dict.SetItemForKey ("stdout", new_file); Py_DECREF (new_file); } @@ -483,7 +481,7 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, { m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr")); - PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", nullptr); + PyObject *new_file = PyFile_FromFile_Const (err, "", "w", nullptr); sys_module_dict.SetItemForKey ("stderr", new_file); Py_DECREF (new_file); } @@ -738,22 +736,21 @@ public: } - virtual - ~IOHandlerPythonInterpreter() + ~IOHandlerPythonInterpreter() override { } - virtual ConstString - GetControlSequence (char ch) + ConstString + GetControlSequence (char ch) override { if (ch == 'd') return ConstString("quit()\n"); return ConstString(); } - virtual void - Run () + void + Run () override { if (m_python) { @@ -799,32 +796,20 @@ public: SetIsDone(true); } - virtual void - Hide () - { - - } - - virtual void - Refresh () - { - - } - - virtual void - Cancel () + void + Cancel () override { } - virtual bool - Interrupt () + bool + Interrupt () override { return m_python->Interrupt(); } - virtual void - GotEOF() + void + GotEOF() override { } @@ -1348,15 +1333,15 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st return true; } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp) +StructuredData::GenericSP +ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) { if (class_name == nullptr || class_name[0] == '\0') - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::GenericSP(); + if (!process_sp) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::GenericSP(); + void* ret_val; { @@ -1367,12 +1352,12 @@ ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, ll m_dictionary_name.c_str(), process_sp); } - - return MakeScriptObject(ret_val); + + return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) +StructuredData::DictionarySP +ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, @@ -1381,13 +1366,17 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP static char callee_name[] = "get_register_info"; if (!os_plugin_object_sp) - return lldb::ScriptInterpreterObjectSP(); - - PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - + return StructuredData::DictionarySP(); + + StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); + if (!generic) + return nullptr; + + PyObject *implementor = (PyObject *)generic->GetValue(); + if (implementor == nullptr || implementor == Py_None) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::DictionarySP(); + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); if (PyErr_Occurred()) @@ -1398,7 +1387,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } if (PyCallable_Check(pmeth) == 0) @@ -1409,7 +1398,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP } Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } if (PyErr_Occurred()) @@ -1428,27 +1417,31 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP PyErr_Print(); PyErr_Clear(); } - - return MakeScriptObject(py_return); + + PythonDictionary result_dict(py_return); + return result_dict.CreateStructuredDictionary(); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) +StructuredData::ArraySP +ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock (this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_thread_info"; - + if (!os_plugin_object_sp) - return lldb::ScriptInterpreterObjectSP(); - - PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - + return StructuredData::ArraySP(); + + StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); + if (!generic) + return nullptr; + PyObject *implementor = (PyObject *)generic->GetValue(); + if (implementor == nullptr || implementor == Py_None) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ArraySP(); + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); if (PyErr_Occurred()) @@ -1459,7 +1452,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ArraySP(); } if (PyCallable_Check(pmeth) == 0) @@ -1470,7 +1463,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o } Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ArraySP(); } if (PyErr_Occurred()) @@ -1489,8 +1482,9 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o PyErr_Print(); PyErr_Clear(); } - - return MakeScriptObject(py_return); + + PythonList ResultList(py_return); + return ResultList.CreateStructuredArray(); } // GetPythonValueFormatString provides a system independent type safe way to @@ -1519,9 +1513,8 @@ template <> const char *GetPythonValueFormatString (unsigned long long) { return template <> const char *GetPythonValueFormatString (float t) { return "f"; } template <> const char *GetPythonValueFormatString (double t) { return "d"; } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t tid) +StructuredData::StringSP +ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { Locker py_lock (this, Locker::AcquireLock | Locker::NoSTDIN, @@ -1531,12 +1524,15 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid)); if (!os_plugin_object_sp) - return lldb::ScriptInterpreterObjectSP(); - - PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - + return StructuredData::StringSP(); + + StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); + if (!generic) + return nullptr; + PyObject *implementor = (PyObject *)generic->GetValue(); + if (implementor == nullptr || implementor == Py_None) - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::StringSP(); PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); @@ -1548,7 +1544,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::StringSP(); } if (PyCallable_Check(pmeth) == 0) @@ -1559,7 +1555,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb } Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::StringSP(); } if (PyErr_Occurred()) @@ -1578,14 +1574,12 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb PyErr_Print(); PyErr_Clear(); } - - return MakeScriptObject(py_return); + PythonString result_string(py_return); + return result_string.CreateStructuredString(); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t tid, - lldb::addr_t context) +StructuredData::DictionarySP +ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, @@ -1597,13 +1591,16 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP param_format += GetPythonValueFormatString(context); if (!os_plugin_object_sp) - return lldb::ScriptInterpreterObjectSP(); - - PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - + return StructuredData::DictionarySP(); + + StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); + if (!generic) + return nullptr; + PyObject *implementor = (PyObject *)generic->GetValue(); + if (implementor == nullptr || implementor == Py_None) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::DictionarySP(); + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); if (PyErr_Occurred()) @@ -1614,7 +1611,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } if (PyCallable_Check(pmeth) == 0) @@ -1625,7 +1622,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP } Py_XDECREF(pmeth); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } if (PyErr_Occurred()) @@ -1644,27 +1641,27 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP PyErr_Print(); PyErr_Clear(); } - - return MakeScriptObject(py_return); + + PythonDictionary result_dict(py_return); + return result_dict.CreateStructuredDictionary(); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name, - lldb::ThreadPlanSP thread_plan_sp) +StructuredData::ObjectSP +ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ObjectSP(); + if (!thread_plan_sp.get()) - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ObjectSP(); Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter); if (!script_interpreter) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ObjectSP(); + void* ret_val; { @@ -1674,20 +1671,21 @@ ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name, python_interpreter->m_dictionary_name.c_str(), thread_plan_sp); } - - return MakeScriptObject(ret_val); + + return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); } bool -ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) +ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool explains_stop = true; + StructuredData::Generic *generic = nullptr; if (implementor_sp) + generic = implementor_sp->GetAsGeneric(); + if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - explains_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "explains_stop", event, script_error); + explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error); if (script_error) return true; } @@ -1695,15 +1693,16 @@ ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreter } bool -ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) +ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool should_stop = true; + StructuredData::Generic *generic = nullptr; if (implementor_sp) + generic = implementor_sp->GetAsGeneric(); + if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_stop", event, script_error); + should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error); if (script_error) return true; } @@ -1711,14 +1710,16 @@ ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterOb } lldb::StateType -ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, - bool &script_error) +ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) { bool should_step = false; + StructuredData::Generic *generic = nullptr; if (implementor_sp) + generic = implementor_sp->GetAsGeneric(); + if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_step = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_step", NULL, script_error); + should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error); if (script_error) should_step = true; } @@ -1728,72 +1729,69 @@ ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterO return lldb::eStateRunning; } - -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec, - lldb_private::Error& error) +StructuredData::ObjectSP +ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) { if (!file_spec.Exists()) { error.SetErrorString("no such file"); - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ObjectSP(); } - ScriptInterpreterObjectSP module_sp; - + StructuredData::ObjectSP module_sp; + if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp)) return module_sp; - - return lldb::ScriptInterpreterObjectSP(); + + return StructuredData::ObjectSP(); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, - Target* target, - const char* setting_name, - lldb_private::Error& error) +StructuredData::DictionarySP +ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, + lldb_private::Error &error) { - if (!plugin_module_sp || !target || !setting_name || !setting_name[0]) - return lldb::ScriptInterpreterObjectSP(); - - if (!g_swig_plugin_get) - return lldb::ScriptInterpreterObjectSP(); - + if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get) + return StructuredData::DictionarySP(); + StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); + if (!generic) + return StructuredData::DictionarySP(); + PyObject *reply_pyobj = nullptr; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); TargetSP target_sp(target->shared_from_this()); - reply_pyobj = (PyObject*)g_swig_plugin_get(plugin_module_sp->GetObject(),setting_name,target_sp); + reply_pyobj = (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp); } - - return MakeScriptObject(reply_pyobj); + + PythonDictionary py_dict(reply_pyobj); + + return py_dict.CreateStructuredDictionary(); } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name, - lldb::ValueObjectSP valobj) +StructuredData::ObjectSP +ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) { if (class_name == nullptr || class_name[0] == '\0') - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ObjectSP(); + if (!valobj.get()) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ObjectSP(); + ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); if (!target) - return lldb::ScriptInterpreterObjectSP(); - + return StructuredData::ObjectSP(); + Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; if (!script_interpreter) - return lldb::ScriptInterpreterObjectSP(); - - void* ret_val; + return StructuredData::ObjectSP(); + + void *ret_val = nullptr; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); @@ -1801,8 +1799,31 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name python_interpreter->m_dictionary_name.c_str(), valobj); } + + return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); +} + +StructuredData::GenericSP +ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name) +{ + DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this()); + + if (class_name == nullptr || class_name[0] == '\0') + return StructuredData::GenericSP(); + + if (!debugger_sp.get()) + return StructuredData::GenericSP(); + + void* ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + ret_val = g_swig_create_cmd (class_name, + m_dictionary_name.c_str(), + debugger_sp); + } - return MakeScriptObject(ret_val); + return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } bool @@ -1869,11 +1890,9 @@ ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user } bool -ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, - lldb::ValueObjectSP valobj, - lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, - const TypeSummaryOptions& options, - std::string& retval) +ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj, + StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, + std::string &retval) { Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); @@ -1883,13 +1902,19 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, retval.assign("<no object>"); return false; } - - void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : nullptr); + + void *old_callee = nullptr; + StructuredData::Generic *generic = nullptr; + if (callee_wrapper_sp) + { + generic = callee_wrapper_sp->GetAsGeneric(); + if (generic) + old_callee = generic->GetValue(); + } void* new_callee = old_callee; bool ret_val; - if (python_function_name - && *python_function_name) + if (python_function_name && *python_function_name) { { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); @@ -1913,10 +1938,9 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, } if (new_callee && old_callee != new_callee) - callee_wrapper_sp = MakeScriptObject(new_callee); - + callee_wrapper_sp.reset(new StructuredPythonObject(new_callee)); + return ret_val; - } void @@ -2042,20 +2066,21 @@ ScriptInterpreterPython::WatchpointCallbackFunction } size_t -ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor_sp) +ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp) { if (!implementor_sp) return 0; - - void* implementor = implementor_sp->GetObject(); - + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return 0; + void *implementor = generic->GetValue(); if (!implementor) return 0; if (!g_swig_calc_children) return 0; - uint32_t ret_val = 0; + size_t ret_val = 0; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); @@ -2066,13 +2091,15 @@ ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObje } lldb::ValueObjectSP -ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor_sp, uint32_t idx) +ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx) { if (!implementor_sp) return lldb::ValueObjectSP(); - - void* implementor = implementor_sp->GetObject(); - + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return lldb::ValueObjectSP(); + void *implementor = generic->GetValue(); if (!implementor) return lldb::ValueObjectSP(); @@ -2102,13 +2129,15 @@ ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& } int -ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor_sp, const char* child_name) +ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name) { if (!implementor_sp) return UINT32_MAX; - - void* implementor = implementor_sp->GetObject(); - + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return UINT32_MAX; + void *implementor = generic->GetValue(); if (!implementor) return UINT32_MAX; @@ -2126,15 +2155,17 @@ ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterO } bool -ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp) +ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; if (!implementor_sp) return ret_val; - - void* implementor = implementor_sp->GetObject(); - + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return ret_val; + void *implementor = generic->GetValue(); if (!implementor) return ret_val; @@ -2150,15 +2181,17 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpre } bool -ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp) +ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; if (!implementor_sp) return ret_val; - - void* implementor = implementor_sp->GetObject(); - + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return ret_val; + void *implementor = generic->GetValue(); if (!implementor) return ret_val; @@ -2174,15 +2207,17 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr } lldb::ValueObjectSP -ScriptInterpreterPython::GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor_sp) +ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp) { lldb::ValueObjectSP ret_val(nullptr); if (!implementor_sp) return ret_val; - - void* implementor = implementor_sp->GetObject(); - + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return ret_val; + void *implementor = generic->GetValue(); if (!implementor) return ret_val; @@ -2440,11 +2475,8 @@ uint64_t replace_all(std::string& str, const std::string& oldStr, const std::str } bool -ScriptInterpreterPython::LoadScriptingModule (const char* pathname, - bool can_reload, - bool init_session, - lldb_private::Error& error, - lldb::ScriptInterpreterObjectSP* module_sp) +ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error, + StructuredData::ObjectSP *module_sp) { if (!pathname || !pathname[0]) { @@ -2575,17 +2607,36 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname, command_stream.Printf("%s",basename.c_str()); void* module_pyobj = nullptr; if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj) - *module_sp = MakeScriptObject(module_pyobj); + module_sp->reset(new StructuredPythonObject(module_pyobj)); } return true; } } -lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::MakeScriptObject (void* object) +bool +ScriptInterpreterPython::IsReservedWord (const char* word) { - return lldb::ScriptInterpreterObjectSP(new ScriptInterpreterPythonObject(object)); + if (!word || !word[0]) + return false; + + llvm::StringRef word_sr(word); + + // filter out a few characters that would just confuse us + // and that are clearly not keyword material anyway + if (word_sr.find_first_of("'\"") != llvm::StringRef::npos) + return false; + + StreamString command_stream; + command_stream.Printf("keyword.iskeyword('%s')", word); + bool result; + ExecuteScriptOptions options; + options.SetEnableIO(false); + options.SetMaskoutErrors(true); + options.SetSetLLDBGlobals(false); + if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options)) + return result; + return false; } ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp, @@ -2663,6 +2714,62 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, return ret_val; } +bool +ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, + const char* args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error, + const lldb_private::ExecutionContext& exe_ctx) +{ + if (!impl_obj_sp || !impl_obj_sp->IsValid()) + { + error.SetErrorString("no function to execute"); + return false; + } + + if (!g_swig_call_command_object) + { + error.SetErrorString("no helper function to run scripted commands"); + return false; + } + + lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); + lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); + + if (!debugger_sp.get()) + { + error.SetErrorString("invalid Debugger pointer"); + return false; + } + + bool ret_val = false; + + std::string err_msg; + + { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), + Locker::FreeLock | Locker::TearDownSession); + + SynchronicityHandler synch_handler(debugger_sp, + synchronicity); + + ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(), + debugger_sp, + args, + cmd_retobj, + exe_ctx_ref_sp); + } + + if (!ret_val) + error.SetErrorString("unable to execute script function"); + else + error.Clear(); + + return ret_val; +} + // in Python, a special attribute __doc__ contains the docstring // for an object (function, method, class, ...) if any is defined // Otherwise, the attribute's value is None @@ -2695,6 +2802,228 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& } } +bool +ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, + std::string& dest) +{ + bool got_string = false; + dest.clear(); + + Locker py_lock (this, + Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + static char callee_name[] = "get_short_help"; + + if (!cmd_obj_sp) + return false; + + PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); + + if (implementor == nullptr || implementor == Py_None) + return false; + + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + if (pmeth == nullptr || pmeth == Py_None) + { + Py_XDECREF(pmeth); + return false; + } + + if (PyCallable_Check(pmeth) == 0) + { + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + return false; + } + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + + // right now we know this function exists and is callable.. + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + if (py_return != nullptr && py_return != Py_None) + { + if (PyString_Check(py_return)) + { + dest.assign(PyString_AsString(py_return)); + got_string = true; + } + } + Py_XDECREF(py_return); + + return got_string; +} + +uint32_t +ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) +{ + uint32_t result = 0; + + Locker py_lock (this, + Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + static char callee_name[] = "get_flags"; + + if (!cmd_obj_sp) + return result; + + PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); + + if (implementor == nullptr || implementor == Py_None) + return result; + + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + if (pmeth == nullptr || pmeth == Py_None) + { + Py_XDECREF(pmeth); + return result; + } + + if (PyCallable_Check(pmeth) == 0) + { + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + return result; + } + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + + // right now we know this function exists and is callable.. + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + if (py_return != nullptr && py_return != Py_None) + { + if (PyInt_Check(py_return)) + result = (uint32_t)PyInt_AsLong(py_return); + else if (PyLong_Check(py_return)) + result = (uint32_t)PyLong_AsLong(py_return); + } + Py_XDECREF(py_return); + + return result; +} + +bool +ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, + std::string& dest) +{ + bool got_string = false; + dest.clear(); + + Locker py_lock (this, + Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + static char callee_name[] = "get_long_help"; + + if (!cmd_obj_sp) + return false; + + PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); + + if (implementor == nullptr || implementor == Py_None) + return false; + + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + if (pmeth == nullptr || pmeth == Py_None) + { + Py_XDECREF(pmeth); + return false; + } + + if (PyCallable_Check(pmeth) == 0) + { + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + return false; + } + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + + // right now we know this function exists and is callable.. + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + if (py_return != nullptr && py_return != Py_None) + { + if (PyString_Check(py_return)) + { + dest.assign(PyString_AsString(py_return)); + got_string = true; + } + } + Py_XDECREF(py_return); + + return got_string; +} + std::unique_ptr<ScriptInterpreterLocker> ScriptInterpreterPython::AcquireInterpreterLock () { @@ -2710,6 +3039,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGWatchpointCallbackFunction swig_watchpoint_callback, SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, SWIGPythonCreateSyntheticProvider swig_synthetic_script, + SWIGPythonCreateCommandObject swig_create_cmd, SWIGPythonCalculateNumChildren swig_calc_children, SWIGPythonGetChildAtIndex swig_get_child_index, SWIGPythonGetIndexOfChildWithName swig_get_index_child, @@ -2719,6 +3049,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, + SWIGPythonCallCommandObject swig_call_command_object, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, @@ -2735,6 +3066,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_watchpoint_callback = swig_watchpoint_callback; g_swig_typescript_callback = swig_typescript_callback; g_swig_synthetic_script = swig_synthetic_script; + g_swig_create_cmd = swig_create_cmd; g_swig_calc_children = swig_calc_children; g_swig_get_child_index = swig_get_child_index; g_swig_get_index_child = swig_get_index_child; @@ -2744,6 +3076,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; g_swig_getvalue_provider = swig_getvalue_provider; g_swig_call_command = swig_call_command; + g_swig_call_command_object = swig_call_command_object; g_swig_call_module_init = swig_call_module_init; g_swig_create_os_plugin = swig_create_os_plugin; g_swig_run_script_keyword_process = swig_run_script_keyword_process; @@ -2759,11 +3092,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb void ScriptInterpreterPython::InitializePrivate () { - static int g_initialized = false; - - if (g_initialized) - return; - + assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!"); g_initialized = true; Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); @@ -2773,6 +3102,9 @@ ScriptInterpreterPython::InitializePrivate () TerminalState stdin_tty_state; stdin_tty_state.Save(STDIN_FILENO, false); +#if defined(LLDB_PYTHON_HOME) + Py_SetPythonHome(LLDB_PYTHON_HOME); +#endif PyGILState_STATE gstate; Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); bool threads_already_initialized = false; @@ -2787,43 +3119,23 @@ ScriptInterpreterPython::InitializePrivate () } Py_InitializeEx (0); - // Initialize SWIG after setting up python if (g_swig_init_callback) g_swig_init_callback (); // Update the path python uses to search for modules to include the current directory. PyRun_SimpleString ("import sys"); - PyRun_SimpleString ("sys.path.append ('.')"); - - // Find the module that owns this code and use that path we get to - // set the sys.path appropriately. + AddToSysPath(AddLocation::End, "."); FileSpec file_spec; - char python_dir_path[PATH_MAX]; + // Don't denormalize paths when calling file_spec.GetPath(). On platforms that use + // a backslash as the path separator, this will result in executing python code containing + // paths with unescaped backslashes. But Python also accepts forward slashes, so to make + // life easier we just use that. if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) - { - std::string python_path("sys.path.insert(0,\""); - size_t orig_len = python_path.length(); - if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path))) - { - python_path.append (python_dir_path); - python_path.append ("\")"); - PyRun_SimpleString (python_path.c_str()); - python_path.resize (orig_len); - } - - if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) - { - if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path))) - { - python_path.append (python_dir_path); - python_path.append ("\")"); - PyRun_SimpleString (python_path.c_str()); - python_path.resize (orig_len); - } - } - } + AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); + if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) + AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line"); @@ -2839,6 +3151,28 @@ ScriptInterpreterPython::InitializePrivate () stdin_tty_state.Restore(); } +void +ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path) +{ + std::string path_copy; + + std::string statement; + if (location == AddLocation::Beginning) + { + statement.assign("sys.path.insert(0,\""); + statement.append (path); + statement.append ("\")"); + } + else + { + statement.assign("sys.path.append(\""); + statement.append(path); + statement.append("\")"); + } + PyRun_SimpleString (statement.c_str()); +} + + //void //ScriptInterpreterPython::Terminate () //{ |