Hide the logic for command resolution for commands, aliases & user commands behind a single

interface so everybody does it the same way.  Add an "exact" lookup for internal uses.

Fix up a few little cases where we weren't reporting command lookup errors correctly.

Added "b" as an alias for "breakpoint" so it doesn't collide with "bt".

llvm-svn: 107718
This commit is contained in:
Jim Ingham 2010-07-06 22:46:59 +00:00
parent 13f0260e76
commit 279a6c2669
6 changed files with 104 additions and 58 deletions

View File

@ -51,10 +51,13 @@ public:
~CommandInterpreter ();
lldb::CommandObjectSP
GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
GetCommandSPExact (const char *cmd, bool include_aliases);
CommandObject *
GetCommandObject (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
GetCommandObjectExact (const char *cmd_cstr, bool include_aliases);
CommandObject *
GetCommandObject (const char *cmd, StringList *matches = NULL);
StateVariable *
GetStateVariable(const char *name);
@ -243,6 +246,9 @@ protected:
void
SetSynchronous (bool value);
lldb::CommandObjectSP
GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
private:
Debugger &m_debugger; // The debugger session that this interpreter is associated with

View File

@ -65,6 +65,12 @@ public:
virtual bool
IsCrossRefObject () { return false; }
bool
IsAlias () { return m_is_alias; }
void
SetIsAlias (bool value) { m_is_alias = value; }
virtual bool
IsMultiwordObject () { return false; }
@ -252,6 +258,7 @@ protected:
std::string m_cmd_help_short;
std::string m_cmd_help_long;
std::string m_cmd_syntax;
bool m_is_alias;
Flags m_flags;
};

View File

@ -121,7 +121,7 @@ CommandObjectAlias::Execute
}
else
{
CommandObjectSP command_obj_sp(interpreter.GetCommandSP (actual_command.c_str()));
CommandObjectSP command_obj_sp(interpreter.GetCommandSPExact (actual_command.c_str(), true));
CommandObjectSP subcommand_obj_sp;
bool use_subcommand = false;
if (command_obj_sp.get())

View File

@ -54,12 +54,8 @@ CommandObjectHelp::Execute (CommandInterpreter &interpreter, Args& command, Comm
else
{
// Get command object for the first command argument. Only search built-in command dictionary.
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), false, false);
if (cmd_obj == NULL)
{
// That failed, so now search in the aliases dictionary, too.
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), true, false);
}
StringList matches;
cmd_obj = interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches);
if (cmd_obj != NULL)
{
@ -123,6 +119,15 @@ CommandObjectHelp::Execute (CommandInterpreter &interpreter, Args& command, Comm
}
}
}
else if (matches.GetSize() > 0)
{
Stream &output_strm = result.GetOutputStream();
output_strm.Printf("Help requested with ambiguous command name, possible completions:\n");
for (int i = 0; i < matches.GetSize(); i++)
{
output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));
}
}
else
{
result.AppendErrorWithFormat
@ -156,7 +161,7 @@ CommandObjectHelp::HandleCompletion
}
else
{
CommandObject *cmd_obj = interpreter.GetCommandObject (input.GetArgumentAtIndex(0), true, false);
CommandObject *cmd_obj = interpreter.GetCommandObject (input.GetArgumentAtIndex(0));
input.Shift();
cursor_index--;
return cmd_obj->HandleCompletion (interpreter, input, cursor_index, cursor_char_position, match_start_point,

View File

@ -91,6 +91,7 @@ CommandInterpreter::Initialize ()
result.Clear(); HandleCommand ("alias continue process continue", false, result);
result.Clear(); HandleCommand ("alias expr expression", false, result);
result.Clear(); HandleCommand ("alias exit quit", false, result);
result.Clear(); HandleCommand ("alias b breakpoint", false, result);
result.Clear(); HandleCommand ("alias bt thread backtrace", false, result);
result.Clear(); HandleCommand ("alias si thread step-inst", false, result);
result.Clear(); HandleCommand ("alias step thread step-in", false, result);
@ -296,13 +297,21 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
if (!exact && ret_val == NULL)
{
// We will only get into here if we didn't find any exact matches.
CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
StringList local_matches;
if (matches == NULL)
matches = &local_matches;
int num_cmd_matches = 0;
int num_alias_matches = 0;
int num_user_matches = 0;
unsigned int num_cmd_matches = 0;
unsigned int num_alias_matches = 0;
unsigned int num_user_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 empty CommandObjectSP and the list of matches.
if (HasCommands())
{
num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
@ -313,7 +322,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
cmd.assign(matches->GetStringAtIndex(0));
pos = m_command_dict.find(cmd);
if (pos != m_command_dict.end())
ret_val = pos->second;
real_match_sp = pos->second;
}
if (include_aliases && HasAliases())
@ -322,17 +331,12 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
}
if (num_alias_matches == 1 && num_cmd_matches == 0)
if (num_alias_matches == 1)
{
cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
pos = m_alias_dict.find(cmd);
if (pos != m_alias_dict.end())
{
matches->Clear();
matches->AppendString (cmd.c_str());
ret_val = pos->second;
}
alias_match_sp = pos->second;
}
if (HasUserCommands())
@ -340,33 +344,68 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
}
if (num_user_matches == 1 && num_alias_matches == 0 && num_cmd_matches == 0)
if (num_user_matches == 1)
{
cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
pos = m_user_dict.find (cmd);
if (pos != m_user_dict.end())
{
matches->Clear();
matches->AppendString (cmd.c_str());
ret_val = pos->second;
}
user_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_cmd_matches)
return real_match_sp;
else if (num_alias_matches)
return alias_match_sp;
else
return user_match_sp;
}
}
else {
if (matches)
matches->AppendString (cmd_cstr);
else if (matches && ret_val != NULL)
{
matches->AppendString (cmd_cstr);
}
return ret_val;
}
CommandObject *
CommandInterpreter::GetCommandObject (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
CommandObjectSP
CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
{
return GetCommandSP (cmd_cstr, include_aliases, exact, matches).get();
return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
}
CommandObject *
CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
{
return GetCommandSPExact (cmd_cstr, include_aliases).get();
}
CommandObject *
CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
{
CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
// If we didn't find an exact match to the command string in the commands, look in
// the aliases.
if (command_obj == NULL)
{
command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
}
// Finally, if there wasn't an exact match among the aliases, look for an inexact match
// in both the commands and the aliases.
if (command_obj == NULL)
command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
return command_obj;
}
bool
@ -390,6 +429,7 @@ CommandInterpreter::UserCommandExists (const char *cmd)
void
CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
{
command_obj_sp->SetIsAlias (true);
m_alias_dict[alias_name] = command_obj_sp;
}
@ -602,30 +642,17 @@ CommandInterpreter::HandleCommand
// We're looking up the command object here. So first find an exact match to the
// command in the commands.
CommandObject *command_obj = GetCommandObject (command_cstr, false, true);
// If we didn't find an exact match to the command string in the commands, look in
// the aliases.
if (command_obj == NULL)
CommandObject *command_obj = GetCommandObject(command_cstr);
if (command_obj != NULL)
{
command_obj = GetCommandObject (command_cstr, true, true);
if (command_obj != NULL)
if (command_obj->IsAlias())
{
BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
if (!result.Succeeded())
return false;
}
}
// Finally, if there wasn't an exact match among the aliases, look for an inexact match.
if (command_obj == NULL)
command_obj = GetCommandObject(command_cstr, false, false);
if (command_obj)
{
if (command_obj->WantsRawCommandString())
{
const char *stripped_command = ::strstr (command_line, command_cstr);
@ -649,10 +676,11 @@ CommandInterpreter::HandleCommand
}
else
{
// We didn't find the first command object, so complete the first argument.
StringList matches;
int num_matches;
int cursor_index = command_args.GetArgumentCount() - 1;
int cursor_char_position = strlen (command_args.GetArgumentAtIndex(command_args.GetArgumentCount() - 1));
int cursor_index = 0;
int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
bool word_complete;
num_matches = HandleCompletionMatches (command_args,
cursor_index,
@ -698,7 +726,6 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
StringList &matches)
{
int num_command_matches = 0;
bool include_aliases = true;
bool look_for_subcommand = false;
// For any of the command completions a unique match will be a complete word.
@ -707,13 +734,13 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
if (cursor_index == -1)
{
// We got nothing on the command line, so return the list of commands
bool include_aliases = true;
num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
}
else if (cursor_index == 0)
{
// The cursor is in the first argument, so just do a lookup in the dictionary.
CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false,
&matches);
CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
num_command_matches = matches.GetSize();
if (num_command_matches == 1
@ -735,7 +762,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
// We are completing further on into a commands arguments, so find the command and tell it
// to complete the command.
// First see if there is a matching initial command:
CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false);
CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
if (command_object == NULL)
{
return 0;
@ -910,7 +937,7 @@ CommandInterpreter::SetPrompt (const char *new_prompt)
void
CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
{
CommandObjectSP cmd_obj_sp = GetCommandSP (dest_cmd);
CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
if (cmd_obj_sp != NULL)
{

View File

@ -43,6 +43,7 @@ CommandObject::CommandObject (const char *name, const char *help, const char *sy
m_cmd_help_short (),
m_cmd_help_long (),
m_cmd_syntax (),
m_is_alias (false),
m_flags (flags)
{
if (help && help[0])