summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp')
-rw-r--r--gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp b/gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp
new file mode 100644
index 00000000000..67225d3d6b8
--- /dev/null
+++ b/gnu/llvm/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -0,0 +1,385 @@
+//===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Options.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// CommandObjectMultiword
+
+CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags)
+ : CommandObject(interpreter, name, help, syntax, flags),
+ m_can_be_removed(false) {}
+
+CommandObjectMultiword::~CommandObjectMultiword() = default;
+
+CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
+ StringList *matches) {
+ CommandObjectSP return_cmd_sp;
+ CommandObject::CommandMap::iterator pos;
+
+ if (!m_subcommand_dict.empty()) {
+ pos = m_subcommand_dict.find(sub_cmd);
+ if (pos != m_subcommand_dict.end()) {
+ // An exact match; append the sub_cmd to the 'matches' string list.
+ if (matches)
+ matches->AppendString(sub_cmd);
+ return_cmd_sp = pos->second;
+ } else {
+ StringList local_matches;
+ if (matches == nullptr)
+ matches = &local_matches;
+ int num_matches =
+ AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
+
+ if (num_matches == 1) {
+ // Cleaner, but slightly less efficient would be to call back into this
+ // function, since I now know I have an exact match...
+
+ sub_cmd = matches->GetStringAtIndex(0);
+ pos = m_subcommand_dict.find(sub_cmd);
+ if (pos != m_subcommand_dict.end())
+ return_cmd_sp = pos->second;
+ }
+ }
+ }
+ return return_cmd_sp;
+}
+
+CommandObject *
+CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
+ StringList *matches) {
+ return GetSubcommandSP(sub_cmd, matches).get();
+}
+
+bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
+ const CommandObjectSP &cmd_obj) {
+ if (cmd_obj)
+ assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) &&
+ "tried to add a CommandObject from a different interpreter");
+
+ CommandMap::iterator pos;
+ bool success = true;
+
+ pos = m_subcommand_dict.find(name);
+ if (pos == m_subcommand_dict.end()) {
+ m_subcommand_dict[name] = cmd_obj;
+ } else
+ success = false;
+
+ return success;
+}
+
+bool CommandObjectMultiword::Execute(const char *args_string,
+ CommandReturnObject &result) {
+ Args args(args_string);
+ const size_t argc = args.GetArgumentCount();
+ if (argc == 0) {
+ this->CommandObject::GenerateHelpText(result);
+ return result.Succeeded();
+ }
+
+ auto sub_command = args[0].ref();
+ if (sub_command.empty()) {
+ result.AppendError("Need to specify a non-empty subcommand.");
+ return result.Succeeded();
+ }
+
+ if (sub_command.equals_lower("help")) {
+ this->CommandObject::GenerateHelpText(result);
+ return result.Succeeded();
+ }
+
+ if (m_subcommand_dict.empty()) {
+ result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
+ GetCommandName().str().c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ StringList matches;
+ CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
+ if (sub_cmd_obj != nullptr) {
+ // Now call CommandObject::Execute to process options in `rest_of_line`.
+ // From there the command-specific version of Execute will be called, with
+ // the processed arguments.
+
+ args.Shift();
+ sub_cmd_obj->Execute(args_string, result);
+ return result.Succeeded();
+ }
+
+ std::string error_msg;
+ const size_t num_subcmd_matches = matches.GetSize();
+ if (num_subcmd_matches > 0)
+ error_msg.assign("ambiguous command ");
+ else
+ error_msg.assign("invalid command ");
+
+ error_msg.append("'");
+ error_msg.append(GetCommandName());
+ error_msg.append(" ");
+ error_msg.append(sub_command);
+ error_msg.append("'.");
+
+ if (num_subcmd_matches > 0) {
+ error_msg.append(" Possible completions:");
+ for (const std::string &match : matches) {
+ error_msg.append("\n\t");
+ error_msg.append(match);
+ }
+ }
+ error_msg.append("\n");
+ result.AppendRawError(error_msg.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+}
+
+void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
+ // First time through here, generate the help text for the object and push it
+ // to the return result object as well
+
+ CommandObject::GenerateHelpText(output_stream);
+ output_stream.PutCString("\nThe following subcommands are supported:\n\n");
+
+ CommandMap::iterator pos;
+ uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
+
+ if (max_len)
+ max_len += 4; // Indent the output by 4 spaces.
+
+ for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
+ std::string indented_command(" ");
+ indented_command.append(pos->first);
+ if (pos->second->WantsRawCommandString()) {
+ std::string help_text(pos->second->GetHelp());
+ help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
+ m_interpreter.OutputFormattedHelpText(output_stream,
+ indented_command.c_str(), "--",
+ help_text.c_str(), max_len);
+ } else
+ m_interpreter.OutputFormattedHelpText(output_stream,
+ indented_command.c_str(), "--",
+ pos->second->GetHelp(), max_len);
+ }
+
+ output_stream.PutCString("\nFor more help on any particular subcommand, type "
+ "'help <command> <subcommand>'.\n");
+}
+
+void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
+ auto arg0 = request.GetParsedLine()[0].ref();
+ if (request.GetCursorIndex() == 0) {
+ StringList new_matches, descriptions;
+ AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
+ &descriptions);
+ request.AddCompletions(new_matches, descriptions);
+
+ if (new_matches.GetSize() == 1 &&
+ new_matches.GetStringAtIndex(0) != nullptr &&
+ (arg0 == new_matches.GetStringAtIndex(0))) {
+ StringList temp_matches;
+ CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
+ if (cmd_obj != nullptr) {
+ if (request.GetParsedLine().GetArgumentCount() != 1) {
+ request.GetParsedLine().Shift();
+ request.AppendEmptyArgument();
+ cmd_obj->HandleCompletion(request);
+ }
+ }
+ }
+ return;
+ }
+
+ StringList new_matches;
+ CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
+ if (sub_command_object == nullptr) {
+ request.AddCompletions(new_matches);
+ return;
+ }
+
+ // Remove the one match that we got from calling GetSubcommandObject.
+ new_matches.DeleteStringAtIndex(0);
+ request.AddCompletions(new_matches);
+ request.ShiftArguments();
+ sub_command_object->HandleCompletion(request);
+}
+
+const char *CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
+ uint32_t index) {
+ index++;
+ if (current_command_args.GetArgumentCount() <= index)
+ return nullptr;
+ CommandObject *sub_command_object =
+ GetSubcommandObject(current_command_args[index].ref());
+ if (sub_command_object == nullptr)
+ return nullptr;
+ return sub_command_object->GetRepeatCommand(current_command_args, index);
+}
+
+void CommandObjectMultiword::AproposAllSubCommands(llvm::StringRef prefix,
+ llvm::StringRef search_word,
+ StringList &commands_found,
+ StringList &commands_help) {
+ CommandObject::CommandMap::const_iterator pos;
+
+ for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
+ const char *command_name = pos->first.c_str();
+ CommandObject *sub_cmd_obj = pos->second.get();
+ StreamString complete_command_name;
+
+ complete_command_name << prefix << " " << command_name;
+
+ if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
+ commands_found.AppendString(complete_command_name.GetString());
+ commands_help.AppendString(sub_cmd_obj->GetHelp());
+ }
+
+ if (sub_cmd_obj->IsMultiwordObject())
+ sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetString(),
+ search_word, commands_found,
+ commands_help);
+ }
+}
+
+CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
+ const char *name, const char *help,
+ const char *syntax, uint32_t flags)
+ : CommandObject(interpreter, name, help, syntax, flags) {}
+
+CommandObjectProxy::~CommandObjectProxy() = default;
+
+llvm::StringRef CommandObjectProxy::GetHelpLong() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetHelpLong();
+ return llvm::StringRef();
+}
+
+bool CommandObjectProxy::IsRemovable() const {
+ const CommandObject *proxy_command =
+ const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->IsRemovable();
+ return false;
+}
+
+bool CommandObjectProxy::IsMultiwordObject() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->IsMultiwordObject();
+ return false;
+}
+
+CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetAsMultiwordCommand();
+ return nullptr;
+}
+
+void CommandObjectProxy::GenerateHelpText(Stream &result) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GenerateHelpText(result);
+}
+
+lldb::CommandObjectSP
+CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
+ StringList *matches) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetSubcommandSP(sub_cmd, matches);
+ return lldb::CommandObjectSP();
+}
+
+CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
+ StringList *matches) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetSubcommandObject(sub_cmd, matches);
+ return nullptr;
+}
+
+void CommandObjectProxy::AproposAllSubCommands(llvm::StringRef prefix,
+ llvm::StringRef search_word,
+ StringList &commands_found,
+ StringList &commands_help) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->AproposAllSubCommands(prefix, search_word,
+ commands_found, commands_help);
+}
+
+bool CommandObjectProxy::LoadSubCommand(
+ llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->LoadSubCommand(cmd_name, command_sp);
+ return false;
+}
+
+bool CommandObjectProxy::WantsRawCommandString() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->WantsRawCommandString();
+ return false;
+}
+
+bool CommandObjectProxy::WantsCompletion() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->WantsCompletion();
+ return false;
+}
+
+Options *CommandObjectProxy::GetOptions() {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetOptions();
+ return nullptr;
+}
+
+void CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ proxy_command->HandleCompletion(request);
+}
+
+void CommandObjectProxy::HandleArgumentCompletion(
+ CompletionRequest &request, OptionElementVector &opt_element_vector) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ proxy_command->HandleArgumentCompletion(request, opt_element_vector);
+}
+
+const char *CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
+ uint32_t index) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GetRepeatCommand(current_command_args, index);
+ return nullptr;
+}
+
+bool CommandObjectProxy::Execute(const char *args_string,
+ CommandReturnObject &result) {
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->Execute(args_string, result);
+ result.AppendError("command is not implemented");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+}