forked from OSchip/llvm-project
526 lines
18 KiB
C++
526 lines
18 KiB
C++
//===-- CommandObjectMultiword.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/lldb-python.h"
|
|
|
|
#include "lldb/Interpreter/CommandObjectMultiword.h"
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Core/Debugger.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Interpreter/Options.h"
|
|
#include "lldb/Interpreter/CommandReturnObject.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 ()
|
|
{
|
|
}
|
|
|
|
CommandObjectSP
|
|
CommandObjectMultiword::GetSubcommandSP (const char *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 == NULL)
|
|
matches = &local_matches;
|
|
int num_matches = CommandObject::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 (const char *sub_cmd, StringList *matches)
|
|
{
|
|
return GetSubcommandSP(sub_cmd, matches).get();
|
|
}
|
|
|
|
bool
|
|
CommandObjectMultiword::LoadSubCommand
|
|
(
|
|
const char *name,
|
|
const CommandObjectSP& cmd_obj
|
|
)
|
|
{
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
const char *sub_command = args.GetArgumentAtIndex (0);
|
|
|
|
if (sub_command)
|
|
{
|
|
if (::strcasecmp (sub_command, "help") == 0)
|
|
{
|
|
this->CommandObject::GenerateHelpText (result);
|
|
}
|
|
else if (!m_subcommand_dict.empty())
|
|
{
|
|
StringList matches;
|
|
CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
|
|
if (sub_cmd_obj != NULL)
|
|
{
|
|
// Now call CommandObject::Execute to process and 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);
|
|
}
|
|
else
|
|
{
|
|
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 (size_t i = 0; i < num_subcmd_matches; i++)
|
|
{
|
|
error_msg.append ("\n\t");
|
|
error_msg.append (matches.GetStringAtIndex (i));
|
|
}
|
|
}
|
|
error_msg.append ("\n");
|
|
result.AppendRawError (error_msg.c_str());
|
|
result.SetStatus (eReturnStatusFailed);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
|
|
result.SetStatus (eReturnStatusFailed);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
|
|
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
|
|
|
|
output_stream.PutCString ("The following subcommands are supported:\n\n");
|
|
|
|
CommandMap::iterator pos;
|
|
uint32_t max_len = m_interpreter.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 (" This command takes 'raw' input (no need to quote stuff).");
|
|
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");
|
|
}
|
|
|
|
int
|
|
CommandObjectMultiword::HandleCompletion
|
|
(
|
|
Args &input,
|
|
int &cursor_index,
|
|
int &cursor_char_position,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches
|
|
)
|
|
{
|
|
// Any of the command matches will provide a complete word, otherwise the individual
|
|
// completers will override this.
|
|
word_complete = true;
|
|
|
|
const char *arg0 = input.GetArgumentAtIndex(0);
|
|
if (cursor_index == 0)
|
|
{
|
|
CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
|
|
arg0,
|
|
matches);
|
|
|
|
if (matches.GetSize() == 1
|
|
&& matches.GetStringAtIndex(0) != NULL
|
|
&& strcmp (arg0, matches.GetStringAtIndex(0)) == 0)
|
|
{
|
|
StringList temp_matches;
|
|
CommandObject *cmd_obj = GetSubcommandObject (arg0,
|
|
&temp_matches);
|
|
if (cmd_obj != NULL)
|
|
{
|
|
if (input.GetArgumentCount() == 1)
|
|
{
|
|
word_complete = true;
|
|
}
|
|
else
|
|
{
|
|
matches.DeleteStringAtIndex (0);
|
|
input.Shift();
|
|
cursor_char_position = 0;
|
|
input.AppendArgument ("");
|
|
return cmd_obj->HandleCompletion (input,
|
|
cursor_index,
|
|
cursor_char_position,
|
|
match_start_point,
|
|
max_return_elements,
|
|
word_complete,
|
|
matches);
|
|
}
|
|
}
|
|
}
|
|
return matches.GetSize();
|
|
}
|
|
else
|
|
{
|
|
CommandObject *sub_command_object = GetSubcommandObject (arg0,
|
|
&matches);
|
|
if (sub_command_object == NULL)
|
|
{
|
|
return matches.GetSize();
|
|
}
|
|
else
|
|
{
|
|
// Remove the one match that we got from calling GetSubcommandObject.
|
|
matches.DeleteStringAtIndex(0);
|
|
input.Shift();
|
|
cursor_index--;
|
|
return sub_command_object->HandleCompletion (input,
|
|
cursor_index,
|
|
cursor_char_position,
|
|
match_start_point,
|
|
max_return_elements,
|
|
word_complete,
|
|
matches);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
const char *
|
|
CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index)
|
|
{
|
|
index++;
|
|
if (current_command_args.GetArgumentCount() <= index)
|
|
return NULL;
|
|
CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
|
|
if (sub_command_object == NULL)
|
|
return NULL;
|
|
return sub_command_object->GetRepeatCommand(current_command_args, index);
|
|
}
|
|
|
|
|
|
void
|
|
CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
|
|
const char *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.Printf ("%s %s", prefix, command_name);
|
|
|
|
if (sub_cmd_obj->HelpTextContainsWord (search_word))
|
|
{
|
|
commands_found.AppendString (complete_command_name.GetData());
|
|
commands_help.AppendString (sub_cmd_obj->GetHelp());
|
|
}
|
|
|
|
if (sub_cmd_obj->IsMultiwordObject())
|
|
sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
|
|
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 ()
|
|
{
|
|
}
|
|
|
|
const char *
|
|
CommandObjectProxy::GetHelpLong ()
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->GetHelpLong();
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
lldb::CommandObjectSP
|
|
CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->GetSubcommandSP(sub_cmd, matches);
|
|
return lldb::CommandObjectSP();
|
|
}
|
|
|
|
CommandObject *
|
|
CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->GetSubcommandObject(sub_cmd, matches);
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
CommandObjectProxy::AproposAllSubCommands (const char *prefix,
|
|
const char *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 (const char *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 NULL;
|
|
}
|
|
|
|
|
|
int
|
|
CommandObjectProxy::HandleCompletion (Args &input,
|
|
int &cursor_index,
|
|
int &cursor_char_position,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches)
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->HandleCompletion (input,
|
|
cursor_index,
|
|
cursor_char_position,
|
|
match_start_point,
|
|
max_return_elements,
|
|
word_complete,
|
|
matches);
|
|
matches.Clear();
|
|
return 0;
|
|
}
|
|
int
|
|
CommandObjectProxy::HandleArgumentCompletion (Args &input,
|
|
int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches)
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->HandleArgumentCompletion (input,
|
|
cursor_index,
|
|
cursor_char_position,
|
|
opt_element_vector,
|
|
match_start_point,
|
|
max_return_elements,
|
|
word_complete,
|
|
matches);
|
|
matches.Clear();
|
|
return 0;
|
|
}
|
|
|
|
const char *
|
|
CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args,
|
|
uint32_t index)
|
|
{
|
|
CommandObject *proxy_command = GetProxyCommandObject();
|
|
if (proxy_command)
|
|
return proxy_command->GetRepeatCommand (current_command_args, index);
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|