aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp253
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;