diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp | 253 |
1 files changed, 213 insertions, 40 deletions
diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp index 00e9ccb762c3..301bf949feef 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp @@ -744,8 +744,10 @@ void CommandInterpreter::LoadCommandDictionary() { std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up( new CommandObjectRegexCommand( *this, "gdb-remote", - "Connect to a process via remote GDB server. " - "If no host is specifed, localhost is assumed.", + "Connect to a process via remote GDB server.\n" + "If no host is specifed, localhost is assumed.\n" + "gdb-remote is an abbreviation for 'process connect --plugin " + "gdb-remote connect://<hostname>:<port>'\n", "gdb-remote [<hostname>:]<portnum>", 2, 0, false)); if (connect_gdb_remote_cmd_up) { if (connect_gdb_remote_cmd_up->AddRegexCommand( @@ -762,9 +764,10 @@ void CommandInterpreter::LoadCommandDictionary() { std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up( new CommandObjectRegexCommand( *this, "kdp-remote", - "Connect to a process via remote KDP server. " - "If no UDP port is specified, port 41139 is " - "assumed.", + "Connect to a process via remote KDP server.\n" + "If no UDP port is specified, port 41139 is assumed.\n" + "kdp-remote is an abbreviation for 'process connect --plugin " + "kdp-remote udp://<hostname>:<port>'\n", "kdp-remote <hostname>[:<portnum>]", 2, 0, false)); if (connect_kdp_remote_cmd_up) { if (connect_kdp_remote_cmd_up->AddRegexCommand( @@ -897,6 +900,63 @@ int CommandInterpreter::GetCommandNamesMatchingPartialString( return matches.GetSize(); } +CommandObjectMultiword *CommandInterpreter::VerifyUserMultiwordCmdPath( + Args &path, bool leaf_is_command, Status &result) { + result.Clear(); + + auto get_multi_or_report_error = + [&result](CommandObjectSP cmd_sp, + const char *name) -> CommandObjectMultiword * { + if (!cmd_sp) { + result.SetErrorStringWithFormat("Path component: '%s' not found", name); + return nullptr; + } + if (!cmd_sp->IsUserCommand()) { + result.SetErrorStringWithFormat("Path component: '%s' is not a user " + "command", + name); + return nullptr; + } + CommandObjectMultiword *cmd_as_multi = cmd_sp->GetAsMultiwordCommand(); + if (!cmd_as_multi) { + result.SetErrorStringWithFormat("Path component: '%s' is not a container " + "command", + name); + return nullptr; + } + return cmd_as_multi; + }; + + size_t num_args = path.GetArgumentCount(); + if (num_args == 0) { + result.SetErrorString("empty command path"); + return nullptr; + } + + if (num_args == 1 && leaf_is_command) { + // We just got a leaf command to be added to the root. That's not an error, + // just return null for the container. + return nullptr; + } + + // Start by getting the root command from the interpreter. + const char *cur_name = path.GetArgumentAtIndex(0); + CommandObjectSP cur_cmd_sp = GetCommandSPExact(cur_name); + CommandObjectMultiword *cur_as_multi = + get_multi_or_report_error(cur_cmd_sp, cur_name); + if (cur_as_multi == nullptr) + return nullptr; + + size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0); + for (size_t cursor = 1; cursor < num_path_elements && cur_as_multi != nullptr; + cursor++) { + cur_name = path.GetArgumentAtIndex(cursor); + cur_cmd_sp = cur_as_multi->GetSubcommandSPExact(cur_name); + cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name); + } + return cur_as_multi; +} + CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases, bool exact, StringList *matches, @@ -923,10 +983,17 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases, command_sp = pos->second; } + if (HasUserMultiwordCommands()) { + auto pos = m_user_mw_dict.find(cmd); + if (pos != m_user_mw_dict.end()) + command_sp = pos->second; + } + if (!exact && !command_sp) { // We will only get into here if we didn't find any exact matches. - CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; + CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp, + real_match_sp; StringList local_matches; if (matches == nullptr) @@ -935,6 +1002,7 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases, unsigned int num_cmd_matches = 0; unsigned int num_alias_matches = 0; unsigned int num_user_matches = 0; + unsigned int num_user_mw_matches = 0; // Look through the command dictionaries one by one, and if we get only one // match from any of them in toto, then return that, otherwise return an @@ -978,14 +1046,32 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases, user_match_sp = pos->second; } + if (HasUserMultiwordCommands()) { + num_user_mw_matches = AddNamesMatchingPartialString( + m_user_mw_dict, cmd_str, *matches, descriptions); + } + + if (num_user_mw_matches == 1) { + cmd.assign(matches->GetStringAtIndex(num_cmd_matches + num_alias_matches + + num_user_matches)); + + auto pos = m_user_mw_dict.find(cmd); + if (pos != m_user_mw_dict.end()) + user_mw_match_sp = pos->second; + } + // If we got exactly one match, return that, otherwise return the match // list. - if (num_user_matches + num_cmd_matches + num_alias_matches == 1) { + if (num_user_matches + num_user_mw_matches + num_cmd_matches + + num_alias_matches == + 1) { if (num_cmd_matches) return real_match_sp; else if (num_alias_matches) return alias_match_sp; + else if (num_user_mw_matches) + return user_mw_match_sp; else return user_match_sp; } @@ -1008,6 +1094,8 @@ bool CommandInterpreter::AddCommand(llvm::StringRef name, if (name.empty()) return false; + cmd_sp->SetIsUserCommand(false); + std::string name_sstr(name); auto name_iter = m_command_dict.find(name_sstr); if (name_iter != m_command_dict.end()) { @@ -1020,33 +1108,49 @@ bool CommandInterpreter::AddCommand(llvm::StringRef name, return true; } -bool CommandInterpreter::AddUserCommand(llvm::StringRef name, - const lldb::CommandObjectSP &cmd_sp, - bool can_replace) { +Status CommandInterpreter::AddUserCommand(llvm::StringRef name, + const lldb::CommandObjectSP &cmd_sp, + bool can_replace) { + Status result; if (cmd_sp.get()) lldbassert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); - - if (!name.empty()) { - // do not allow replacement of internal commands - if (CommandExists(name)) { - if (!can_replace) - return false; - if (!m_command_dict[std::string(name)]->IsRemovable()) - return false; + if (name.empty()) { + result.SetErrorString("can't use the empty string for a command name"); + return result; + } + // do not allow replacement of internal commands + if (CommandExists(name)) { + result.SetErrorString("can't replace builtin command"); + return result; + } + + if (UserCommandExists(name)) { + if (!can_replace) { + result.SetErrorString("user command exists and force replace not set"); + return result; + } + if (cmd_sp->IsMultiwordObject()) { + if (!m_user_mw_dict[std::string(name)]->IsRemovable()) { + result.SetErrorString( + "can't replace explicitly non-removable multi-word command"); + return result; + } + } else { + if (!m_user_dict[std::string(name)]->IsRemovable()) { + result.SetErrorString("can't replace explicitly non-removable command"); + return result; + } } + } - if (UserCommandExists(name)) { - if (!can_replace) - return false; - if (!m_user_dict[std::string(name)]->IsRemovable()) - return false; - } + cmd_sp->SetIsUserCommand(true); + if (cmd_sp->IsMultiwordObject()) + m_user_mw_dict[std::string(name)] = cmd_sp; + else m_user_dict[std::string(name)] = cmd_sp; - return true; - } - return false; + return result; } CommandObjectSP @@ -1127,6 +1231,42 @@ CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, return GetCommandSP(cmd_str, true, false, matches, descriptions).get(); } +CommandObject *CommandInterpreter::GetUserCommandObject( + llvm::StringRef cmd, StringList *matches, StringList *descriptions) const { + std::string cmd_str(cmd); + auto find_exact = [&](const CommandObject::CommandMap &map) { + auto found_elem = map.find(std::string(cmd)); + if (found_elem == map.end()) + return (CommandObject *)nullptr; + CommandObject *exact_cmd = found_elem->second.get(); + if (exact_cmd) { + if (matches) + matches->AppendString(exact_cmd->GetCommandName()); + if (descriptions) + descriptions->AppendString(exact_cmd->GetHelp()); + return exact_cmd; + } + return (CommandObject *)nullptr; + }; + + CommandObject *exact_cmd = find_exact(GetUserCommands()); + if (exact_cmd) + return exact_cmd; + + exact_cmd = find_exact(GetUserMultiwordCommands()); + if (exact_cmd) + return exact_cmd; + + // We didn't have an exact command, so now look for partial matches. + StringList tmp_list; + StringList *matches_ptr = matches ? matches : &tmp_list; + AddNamesMatchingPartialString(GetUserCommands(), cmd_str, *matches_ptr); + AddNamesMatchingPartialString(GetUserMultiwordCommands(), + cmd_str, *matches_ptr); + + return {}; +} + bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const { return m_command_dict.find(std::string(cmd)) != m_command_dict.end(); } @@ -1169,6 +1309,10 @@ bool CommandInterpreter::UserCommandExists(llvm::StringRef cmd) const { return m_user_dict.find(std::string(cmd)) != m_user_dict.end(); } +bool CommandInterpreter::UserMultiwordCommandExists(llvm::StringRef cmd) const { + return m_user_mw_dict.find(std::string(cmd)) != m_user_mw_dict.end(); +} + CommandAlias * CommandInterpreter::AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, @@ -1209,9 +1353,10 @@ bool CommandInterpreter::RemoveCommand(llvm::StringRef cmd) { } return false; } -bool CommandInterpreter::RemoveUser(llvm::StringRef alias_name) { + +bool CommandInterpreter::RemoveUser(llvm::StringRef user_name) { CommandObject::CommandMap::iterator pos = - m_user_dict.find(std::string(alias_name)); + m_user_dict.find(std::string(user_name)); if (pos != m_user_dict.end()) { m_user_dict.erase(pos); return true; @@ -1219,6 +1364,16 @@ bool CommandInterpreter::RemoveUser(llvm::StringRef alias_name) { return false; } +bool CommandInterpreter::RemoveUserMultiword(llvm::StringRef multi_name) { + CommandObject::CommandMap::iterator pos = + m_user_mw_dict.find(std::string(multi_name)); + if (pos != m_user_mw_dict.end()) { + m_user_mw_dict.erase(pos); + return true; + } + return false; +} + void CommandInterpreter::GetHelp(CommandReturnObject &result, uint32_t cmd_types) { llvm::StringRef help_prologue(GetDebugger().GetIOHandlerHelpPrologue()); @@ -1274,6 +1429,18 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result, result.AppendMessage(""); } + if (!m_user_mw_dict.empty() && + ((cmd_types & eCommandTypesUserMW) == eCommandTypesUserMW)) { + result.AppendMessage("Current user-defined container commands:"); + result.AppendMessage(""); + max_len = FindLongestCommandWord(m_user_mw_dict); + for (pos = m_user_dict.begin(); pos != m_user_mw_dict.end(); ++pos) { + OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--", + pos->second->GetHelp(), max_len); + } + result.AppendMessage(""); + } + result.AppendMessageWithFormat( "For more information on any command, type '%shelp <command-name>'.\n", GetCommandPrefix()); @@ -1931,6 +2098,10 @@ bool CommandInterpreter::HasAliases() const { return (!m_alias_dict.empty()); } bool CommandInterpreter::HasUserCommands() const { return (!m_user_dict.empty()); } +bool CommandInterpreter::HasUserMultiwordCommands() const { + return (!m_user_mw_dict.empty()); +} + bool CommandInterpreter::HasAliasOptions() const { return HasAliases(); } void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, @@ -2113,13 +2284,6 @@ static void GetCwdInitFile(llvm::SmallVectorImpl<char> &init_file) { FileSystem::Instance().Resolve(init_file); } -static LoadCWDlldbinitFile ShouldLoadCwdInitFile() { - lldb::TargetPropertiesSP properties = Target::GetGlobalProperties(); - if (!properties) - return eLoadCWDlldbinitFalse; - return properties->GetLoadCWDlldbinitFile(); -} - void CommandInterpreter::SourceInitFile(FileSpec file, CommandReturnObject &result) { assert(!m_skip_lldbinit_files); @@ -2155,7 +2319,8 @@ void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) { return; } - LoadCWDlldbinitFile should_load = ShouldLoadCwdInitFile(); + LoadCWDlldbinitFile should_load = + Target::GetGlobalProperties().GetLoadCWDlldbinitFile(); switch (should_load) { case eLoadCWDlldbinitFalse: @@ -2433,7 +2598,7 @@ void CommandInterpreter::HandleCommandsFromFile(FileSpec &cmd_file, std::string cmd_file_path = cmd_file.GetPath(); auto input_file_up = - FileSystem::Instance().Open(cmd_file, File::eOpenOptionRead); + FileSystem::Instance().Open(cmd_file, File::eOpenOptionReadOnly); if (!input_file_up) { std::string error = llvm::toString(input_file_up.takeError()); result.AppendErrorWithFormatv( @@ -2587,6 +2752,9 @@ void CommandInterpreter::OutputFormattedHelpText(Stream &strm, strm.IndentMore(prefix.size()); bool prefixed_yet = false; + // Even if we have no help text we still want to emit the command name. + if (help_text.empty()) + help_text = "No help text"; while (!help_text.empty()) { // Prefix the first line, indent subsequent lines to line up if (!prefixed_yet) { @@ -2706,7 +2874,8 @@ void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word, StringList &commands_help, bool search_builtin_commands, bool search_user_commands, - bool search_alias_commands) { + bool search_alias_commands, + bool search_user_mw_commands) { CommandObject::CommandMap::const_iterator pos; if (search_builtin_commands) @@ -2717,6 +2886,10 @@ void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word, FindCommandsForApropos(search_word, commands_found, commands_help, m_user_dict); + if (search_user_mw_commands) + FindCommandsForApropos(search_word, commands_found, commands_help, + m_user_mw_dict); + if (search_alias_commands) FindCommandsForApropos(search_word, commands_found, commands_help, m_alias_dict); @@ -2954,7 +3127,7 @@ bool CommandInterpreter::SaveTranscript( return false; }; - File::OpenOptions flags = File::eOpenOptionWrite | + File::OpenOptions flags = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | File::eOpenOptionTruncate; |