From 279a6c26698c4a09784cce11e69ea9da86681406 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Tue, 6 Jul 2010 22:46:59 +0000 Subject: [PATCH] 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 --- .../lldb/Interpreter/CommandInterpreter.h | 10 +- lldb/include/lldb/Interpreter/CommandObject.h | 7 + lldb/source/Commands/CommandObjectAlias.cpp | 2 +- lldb/source/Commands/CommandObjectHelp.cpp | 19 ++- .../source/Interpreter/CommandInterpreter.cpp | 123 +++++++++++------- lldb/source/Interpreter/CommandObject.cpp | 1 + 6 files changed, 104 insertions(+), 58 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 7443c5e6856c..4cc969394b10 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -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 diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h index 6cb996fc2c99..6bb889bec2ff 100644 --- a/lldb/include/lldb/Interpreter/CommandObject.h +++ b/lldb/include/lldb/Interpreter/CommandObject.h @@ -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; }; diff --git a/lldb/source/Commands/CommandObjectAlias.cpp b/lldb/source/Commands/CommandObjectAlias.cpp index 62ffbf4915e1..5c09a2aec0b0 100644 --- a/lldb/source/Commands/CommandObjectAlias.cpp +++ b/lldb/source/Commands/CommandObjectAlias.cpp @@ -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()) diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp index 363bbc4675ab..37802a85b2a9 100644 --- a/lldb/source/Commands/CommandObjectHelp.cpp +++ b/lldb/source/Commands/CommandObjectHelp.cpp @@ -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, diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index f37e985e4a29..6516cf7735ac 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -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) { diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 7ee9137b0e1d..88841c4bae7e 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -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])