summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Interpreter/Args.h3
-rw-r--r--lldb/include/lldb/Interpreter/CommandInterpreter.h10
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp133
-rw-r--r--lldb/source/Interpreter/Args.cpp22
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp478
5 files changed, 486 insertions, 160 deletions
diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h
index 4cde95f3dc9..3a62fdee42f 100644
--- a/lldb/include/lldb/Interpreter/Args.h
+++ b/lldb/include/lldb/Interpreter/Args.h
@@ -313,7 +313,8 @@ public:
// and it builds up the option_arg_vector as it parses the options.
void
- ParseAliasOptions (Options &options, CommandReturnObject &result, OptionArgVector *option_arg_vector);
+ ParseAliasOptions (Options &options, CommandReturnObject &result, OptionArgVector *option_arg_vector,
+ std::string &raw_input_line);
void
ParseArgsForCompletion (Options &options, OptionElementVector &option_element_vector, uint32_t cursor_index);
diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h
index ada49c32a1d..865761ffaa8 100644
--- a/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -85,11 +85,21 @@ public:
AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp);
bool
+ StripFirstWord (std::string &command_string, std::string &next_word);
+
+ void
+ BuildAliasResult (const char *alias_name, std::string &raw_input_string, std::string &alias_result,
+ CommandObject *&alias_cmd_obj, CommandReturnObject &result);
+
+ bool
HandleCommand (const char *command_line,
bool add_to_history,
CommandReturnObject &result,
ExecutionContext *override_context = NULL);
+ CommandObject *
+ GetCommandObjectForCommand (std::string &command_line);
+
// This handles command line completion. You are given a pointer to the command string buffer, to the current cursor,
// and to the end of the string (in case it is not NULL terminated).
// You also passed in an Args object to fill with the returns.
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 0ca50b0ff65..0d2c55c9567 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -239,6 +239,133 @@ public:
{
}
+ bool
+ WantsRawCommandString ()
+ {
+ return true;
+ }
+
+ bool
+ ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
+ {
+ Args args (raw_command_line);
+ std::string raw_command_string (raw_command_line);
+
+ size_t argc = args.GetArgumentCount();
+
+ if (argc < 2)
+ {
+ result.AppendError ("'alias' requires at least two arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // Get the alias command.
+
+ const std::string alias_command = args.GetArgumentAtIndex (0);
+
+ // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
+ // does the stripping itself.
+ size_t pos = raw_command_string.find (alias_command);
+ if (pos == 0)
+ {
+ raw_command_string = raw_command_string.substr (alias_command.size());
+ pos = raw_command_string.find_first_not_of (' ');
+ if ((pos != std::string::npos) && (pos > 0))
+ raw_command_string = raw_command_string.substr (pos);
+ }
+ else
+ {
+ result.AppendError ("Error parsing command string. No alias created.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+
+ // Verify that the command is alias-able.
+ if (m_interpreter.CommandExists (alias_command.c_str()))
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
+ alias_command.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
+ // raw_command_string is returned with the name of the command object stripped off the front.
+ CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
+
+ if (!cmd_obj)
+ {
+ result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
+ " No alias created.", raw_command_string.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else if (!cmd_obj->WantsRawCommandString ())
+ {
+ // Note that args was initialized with the original command, and has not been updated to this point.
+ // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
+ return Execute (args, result);
+ }
+ else
+ {
+ // Verify & handle any options/arguments passed to the alias command
+
+ OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ // Check to see if there's anything left in the input command string.
+ if (raw_command_string.size() > 0)
+ {
+
+ // Check to see if the command being aliased can take any command options.
+ Options *options = cmd_obj->GetOptions();
+ if (options)
+ {
+ // See if any options were specified as part of the alias; if so, handle them appropriately
+ options->ResetOptionValues ();
+ Args tmp_args (raw_command_string.c_str());
+ args.Unshift ("dummy_arg");
+ args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
+ args.Shift ();
+ if (result.Succeeded())
+ options->VerifyPartialOptions (result);
+ if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
+ {
+ result.AppendError ("Unable to create requested alias.\n");
+ return false;
+ }
+ }
+ // Anything remaining must be plain raw input. Push it in as a single raw input argument.
+ if (raw_command_string.size() > 0)
+ option_arg_vector->push_back (OptionArgPair ("<argument>",
+ OptionArgValue (-1,
+ raw_command_string)));
+ }
+
+ // Create the alias
+ if (m_interpreter.AliasExists (alias_command.c_str())
+ || m_interpreter.UserCommandExists (alias_command.c_str()))
+ {
+ OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
+ if (temp_option_arg_sp.get())
+ {
+ if (option_arg_vector->size() == 0)
+ m_interpreter.RemoveAliasOptions (alias_command.c_str());
+ }
+ result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
+ alias_command.c_str());
+ }
+
+ CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
+ m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
+ if (option_arg_vector->size() > 0)
+ m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ return result.Succeeded();
+ }
bool
Execute
@@ -282,7 +409,7 @@ public:
OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
- if (cmd_obj->IsMultiwordObject())
+ while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
{
if (argc >= 3)
{
@@ -295,6 +422,7 @@ public:
sub_cmd_obj = subcommand_obj_sp.get();
use_subcommand = true;
args.Shift(); // Shift the sub_command word off the argument vector.
+ cmd_obj = sub_cmd_obj;
}
else
{
@@ -320,8 +448,9 @@ public:
else
options = cmd_obj->GetOptions();
options->ResetOptionValues ();
+ std::string empty_string;
args.Unshift ("dummy_arg");
- args.ParseAliasOptions (*options, result, option_arg_vector);
+ args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
args.Shift ();
if (result.Succeeded())
options->VerifyPartialOptions (result);
diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp
index 8bc7d97b582..b0e448ee9bd 100644
--- a/lldb/source/Interpreter/Args.cpp
+++ b/lldb/source/Interpreter/Args.cpp
@@ -849,7 +849,8 @@ Args::IsPositionalArgument (const char *arg)
void
Args::ParseAliasOptions (Options &options,
CommandReturnObject &result,
- OptionArgVector *option_arg_vector)
+ OptionArgVector *option_arg_vector,
+ std::string &raw_input_string)
{
StreamString sstr;
int i;
@@ -985,16 +986,33 @@ Args::ParseAliasOptions (Options &options,
if (long_options_index >= 0)
{
// Find option in the argument list; also see if it was supposed to take an argument and if one was
- // supplied. Remove option (and argument, if given) from the argument list.
+ // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
+ // the raw_input_string, if one was passed in.
size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
if (idx < GetArgumentCount())
{
+ if (raw_input_string.size() > 0)
+ {
+ const char *tmp_arg = GetArgumentAtIndex (idx);
+ size_t pos = raw_input_string.find (tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase (pos, strlen (tmp_arg));
+ }
ReplaceArgumentAtIndex (idx, "");
if ((long_options[long_options_index].has_arg != no_argument)
&& (optarg != NULL)
&& (idx+1 < GetArgumentCount())
&& (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
+ {
+ if (raw_input_string.size() > 0)
+ {
+ const char *tmp_arg = GetArgumentAtIndex (idx+1);
+ size_t pos = raw_input_string.find (tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase (pos, strlen (tmp_arg));
+ }
ReplaceArgumentAtIndex (idx+1, "");
+ }
}
}
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index feb496332c1..4651ad93a47 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -494,30 +494,184 @@ CommandInterpreter::GetHelp (CommandReturnObject &result)
result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
}
+CommandObject *
+CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
+{
+ // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
+ // eventually be invoked by the given command line.
+
+ CommandObject *cmd_obj = NULL;
+ std::string white_space (" \t\v");
+ size_t start = command_string.find_first_not_of (white_space);
+ size_t end = 0;
+ bool done = false;
+ while (!done)
+ {
+ if (start != std::string::npos)
+ {
+ // Get the next word from command_string.
+ end = command_string.find_first_of (white_space, start);
+ if (end == std::string::npos)
+ end = command_string.size();
+ std::string cmd_word = command_string.substr (start, end - start);
+
+ if (cmd_obj == NULL)
+ // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
+ // command or alias.
+ cmd_obj = GetCommandObject (cmd_word.c_str());
+ else if (cmd_obj->IsMultiwordObject ())
+ {
+ // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
+ CommandObject *sub_cmd_obj =
+ ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (cmd_word.c_str());
+ if (sub_cmd_obj)
+ cmd_obj = sub_cmd_obj;
+ else // cmd_word was not a valid sub-command word, so we are donee
+ done = true;
+ }
+ else
+ // We have a cmd_obj and it is not a multi-word object, so we are done.
+ done = true;
+
+ // If we didn't find a valid command object, or our command object is not a multi-word object, or
+ // we are at the end of the command_string, then we are done. Otherwise, find the start of the
+ // next word.
+
+ if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
+ done = true;
+ else
+ start = command_string.find_first_not_of (white_space, end);
+ }
+ else
+ // Unable to find any more words.
+ done = true;
+ }
+
+ if (end == command_string.size())
+ command_string.clear();
+ else
+ command_string = command_string.substr(end);
+
+ return cmd_obj;
+}
+
bool
-CommandInterpreter::HandleCommand
-(
- const char *command_line,
- bool add_to_history,
- CommandReturnObject &result,
- ExecutionContext *override_context
-)
+CommandInterpreter::StripFirstWord (std::string &command_string, std::string &word)
{
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
- // FIXME: there should probably be a mutex to make sure only one thread can
- // run the interpreter at a time.
+ std::string white_space (" \t\v");
+ size_t start;
+ size_t end;
+
+ start = command_string.find_first_not_of (white_space);
+ if (start != std::string::npos)
+ {
+ end = command_string.find_first_of (white_space, start);
+ if (end != std::string::npos)
+ {
+ word = command_string.substr (start, end - start);
+ command_string = command_string.substr (end);
+ size_t pos = command_string.find_first_not_of (white_space);
+ if ((pos != 0) && (pos != std::string::npos))
+ command_string = command_string.substr (pos);
+ }
+ else
+ {
+ word = command_string.substr (start);
+ command_string.erase();
+ }
+
+ }
+ return true;
+}
+
+void
+CommandInterpreter::BuildAliasResult (const char *alias_name, std::string &raw_input_string, std::string &alias_result,
+ CommandObject *&alias_cmd_obj, CommandReturnObject &result)
+{
+ Args cmd_args (raw_input_string.c_str());
+ alias_cmd_obj = GetCommandObject (alias_name);
+ StreamString result_str;
+
+ if (alias_cmd_obj)
+ {
+ std::string alias_name_str = alias_name;
+ if ((cmd_args.GetArgumentCount() == 0)
+ || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
+ cmd_args.Unshift (alias_name);
+
+ result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
+ OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+ if (option_arg_vector_sp.get())
+ {
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ for (int i = 0; i < option_arg_vector->size(); ++i)
+ {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ OptionArgValue value_pair = option_pair.second;
+ int value_type = value_pair.first;
+ std::string option = option_pair.first;
+ std::string value = value_pair.second;
+ if (option.compare ("<argument>") == 0)
+ result_str.Printf (" %s", value.c_str());
+ else
+ {
+ result_str.Printf (" %s", option.c_str());
+ if (value_type != optional_argument)
+ result_str.Printf (" ");
+ if (value.compare ("<no_argument>") != 0)
+ {
+ int index = GetOptionArgumentPosition (value.c_str());
+ if (index == 0)
+ result_str.Printf ("%s", value.c_str());
+ else if (index >= cmd_args.GetArgumentCount())
+ {
+
+ result.AppendErrorWithFormat
+ ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
+ index);
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ else
+ {
+ size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
+ if (strpos != std::string::npos)
+ raw_input_string = raw_input_string.erase (strpos,
+ strlen (cmd_args.GetArgumentAtIndex (index)));
+ result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
+ }
+ }
+ }
+ }
+ }
+
+ alias_result = result_str.GetData();
+ }
+}
+
+bool
+CommandInterpreter::HandleCommand (const char *command_line,
+ bool add_to_history,
+ CommandReturnObject &result,
+ ExecutionContext *override_context)
+{
+ bool done = false;
+ CommandObject *cmd_obj = NULL;
+ std::string next_word;
+ bool wants_raw_input = false;
+ std::string command_string (command_line);
+
+ LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
// Make a scoped cleanup object that will clear the crash description string
// on exit of this function.
lldb_utility::CleanUp <const char *, void> crash_description_cleanup(NULL, Host::SetCrashDescription);
- // TODO: this should be a logging channel in lldb.
-// if (DebugSelf())
-// {
-// result.AppendMessageWithFormat ("Processing command: %s\n", command_line);
-// }
+ if (log)
+ log->Printf ("Processing command: %s", command_line);
Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
@@ -534,6 +688,7 @@ CommandInterpreter::HandleCommand
else
{
command_line = m_repeat_command.c_str();
+ command_string = command_line;
if (m_repeat_command.empty())
{
result.AppendErrorWithFormat("No auto repeat.\n");
@@ -544,158 +699,171 @@ CommandInterpreter::HandleCommand
add_to_history = false;
}
- if (log)
- log->Printf ("CommandInterpreter::HandleCommand, command_line = '%s'", command_line);
-
- Args command_args(command_line);
-
- if (command_args.GetArgumentCount() > 0)
+ // Phase 1.
+
+ // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
+ // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
+ // the user could have specified an alias, and in translating the alias there may also be command options and/or
+ // even data (including raw text strings) that need to be found and inserted into the command line as part of
+ // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
+ // object whose Execute method will actually be called; 2). a revised command string, with all substituitions &
+ // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
+
+ StreamString revised_command_line;
+ while (!done)
{
- std::string raw_command_string (command_line); // For commands that take raw input but may be aliased or
- // have command options.
-
- const char *command_cstr = command_args.GetArgumentAtIndex(0);
- if (command_cstr)
+ StripFirstWord (command_string, next_word);
+ if (!cmd_obj && AliasExists (next_word.c_str()))
{
-
- // 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);
-
- if (command_obj != NULL)
+ std::string alias_result;
+ BuildAliasResult (next_word.c_str(), command_string, alias_result, cmd_obj, result);
+ revised_command_line.Printf ("%s", alias_result.c_str());
+ if (cmd_obj)
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ }
+ else if (!cmd_obj)
+ {
+ cmd_obj = GetCommandObject (next_word.c_str());
+ if (cmd_obj)
{
- // Strip command name from the raw_command_string.
- if (raw_command_string.find (command_cstr) == 0)
- {
- // The command name is at the front of the string (where it should be) so strip it off.
- raw_command_string = raw_command_string.substr (strlen (command_cstr));
- }
-
+ revised_command_line.Printf ("%s", next_word.c_str());
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ }
+ else
+ {
+ revised_command_line.Printf ("%s", next_word.c_str());
+ }
+ }
+ else if (cmd_obj->IsMultiwordObject ())
+ {
+ CommandObject *sub_cmd_obj = ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (next_word.c_str());
+ if (sub_cmd_obj)
+ {
+ revised_command_line.Printf (" %s", next_word.c_str());
+ cmd_obj = sub_cmd_obj;
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ }
+ else
+ {
+ revised_command_line.Printf (" %s", next_word.c_str());
+ done = true;
+ }
+ }
+ else
+ {
+ revised_command_line.Printf (" %s", next_word.c_str());
+ done = true;
+ }
+
+ if (cmd_obj == NULL)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ next_word.erase ();
+ if (command_string.length() == 0)
+ done = true;
- std::string aliased_cmd_str;
- if (command_obj->IsAlias())
- {
- if (log)
- log->Printf ("Command '%s' is an alias. Building alias command args.", command_cstr);
- BuildAliasCommandArgs (command_obj, command_cstr, command_args, raw_command_string, result);
- if (!result.Succeeded())
- {
- if (log)
- log->Printf ("Building alias command args failed.");
- return false;
- }
- else
- {
- // We need to transfer the newly constructed args back into the command_line, in case
- // this happens to be an alias for a command that takes raw input.
- if (command_args.GetCommandString (aliased_cmd_str))
- {
- if (log)
- log->Printf ("Result string from BuildAliasCommandArgs is '%s'", aliased_cmd_str.c_str());
- if (command_obj->WantsRawCommandString())
- {
- if (log)
- {
- log->Printf ("This command takes raw input.");
- }
- aliased_cmd_str.append (" ");
- aliased_cmd_str.append (raw_command_string);
- }
- else
- {
- if (log)
- log->Printf ("This command does NOT take raw input.");
- }
- command_line = aliased_cmd_str.c_str();
- command_cstr = command_args.GetArgumentAtIndex (0);
- if (log)
- {
- log->Printf ("Final command line, after resolving aliases is '%s'", command_line);
- }
- }
- }
- }
+ }
- if (add_to_history)
- {
- const char *repeat_command = command_obj->GetRepeatCommand(command_args, 0);
- if (repeat_command != NULL)
- m_repeat_command.assign(repeat_command);
- else
- m_repeat_command.assign(command_line);
-
- m_command_history.push_back (command_line);
- }
+ if (command_string.size() > 0)
+ revised_command_line.Printf (" %s", command_string.c_str());
+ // End of Phase 1.
+ // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
+ // specified was valid; revised_command_line contains the complete command line (including command name(s)),
+ // fully translated with all substitutions & translations taken care of (still in raw text format); and
+ // wants_raw_input specifies whether the Execute method expects raw input or not.
- if (command_obj->WantsRawCommandString())
- {
- const char *stripped_command = ::strstr (command_line, command_cstr);
- if (stripped_command)
- {
- stripped_command += strlen(command_cstr);
- while (isspace(*stripped_command))
- ++stripped_command;
- if (log)
- log->Printf ("Input string being passed to ExecuteRawCommandString for '%s' command is '%s'",
- command_obj->GetCommandName(), stripped_command);
- command_obj->ExecuteRawCommandString (stripped_command, result);
- }
- }
- else
- {
- // Remove the command from the args.
- command_args.Shift();
- if (log)
- {
- size_t count = command_args.GetArgumentCount();
- log->Printf ("ExecuteWithOptions for '%s' command is being called with %d args:",
- command_obj->GetCommandName(), count);
- for (size_t k = 0; k < count; ++k)
- log->Printf (" arg[%d]='%s'", k, command_args.GetArgumentAtIndex (k));
- }
- command_obj->ExecuteWithOptions (command_args, result);
- }
- }
- else
- {
- // We didn't find the first command object, so complete the first argument.
- StringList matches;
- int num_matches;
- int cursor_index = 0;
- int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
- bool word_complete;
- num_matches = HandleCompletionMatches (command_args,
- cursor_index,
- cursor_char_position,
- 0,
- -1,
- word_complete,
- matches);
-
- if (num_matches > 0)
- {
- std::string error_msg;
- error_msg.assign ("ambiguous command '");
- error_msg.append(command_cstr);
- error_msg.append ("'.");
+
+ if (log)
+ {
+ log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
+ log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
+ log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
+ }
- error_msg.append (" Possible completions:");
- for (int i = 0; i < num_matches; i++)
- {
- error_msg.append ("\n\t");
- error_msg.append (matches.GetStringAtIndex (i));
- }
- error_msg.append ("\n");
- result.AppendRawError (error_msg.c_str(), error_msg.size());
- }
- else
- result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr);
+ // Phase 2.
+ // Take care of things like setting up the history command & calling the appropriate Execute method on the
+ // CommandObject, with the appropriate arguments.
+
+ if (cmd_obj != NULL)
+ {
+ if (add_to_history)
+ {
+ Args command_args (revised_command_line.GetData());
+ const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
+ if (repeat_command != NULL)
+ m_repeat_command.assign(repeat_command);
+ else
+ m_repeat_command.assign(command_line);
+
+ m_command_history.push_back (command_line);
+ }
+
+ command_string = revised_command_line.GetData();
+ std::string command_name (cmd_obj->GetCommandName());
+ std::string remainder (command_string.substr (command_name.size()));
+
+ // Remove any initial spaces
+ std::string white_space (" \t\v");
+ size_t pos = remainder.find_first_not_of (white_space);
+ if (pos != 0 && pos != std::string::npos)
+ remainder = remainder.substr (pos);
+
+ if (log)
+ log->Printf ("HandleCommand, command line after removing command name(s): '%s'\n", remainder.c_str());
+
- result.SetStatus (eReturnStatusFailed);
+ if (wants_raw_input)
+ cmd_obj->ExecuteRawCommandString (remainder.c_str(), result);
+ else
+ {
+ Args cmd_args (remainder.c_str());
+ cmd_obj->ExecuteWithOptions (cmd_args, result);
+ }
+ }
+ else
+ {
+ // We didn't find the first command object, so complete the first argument.
+ Args command_args (revised_command_line.GetData());
+ StringList matches;
+ int num_matches;
+ int cursor_index = 0;
+ int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
+ bool word_complete;
+ num_matches = HandleCompletionMatches (command_args,
+ cursor_index,
+ cursor_char_position,
+ 0,
+ -1,
+ word_complete,
+ matches);
+
+ if (num_matches > 0)
+ {
+ std::string error_msg;
+ error_msg.assign ("ambiguous command '");
+ error_msg.append(command_args.GetArgumentAtIndex(0));
+ error_msg.append ("'.");
+
+ error_msg.append (" Possible completions:");
+ for (int i = 0; i < num_matches; i++)
+ {
+ error_msg.append ("\n\t");
+ error_msg.append (matches.GetStringAtIndex (i));
}
+ error_msg.append ("\n");
+ result.AppendRawError (error_msg.c_str(), error_msg.size());
}
+ else
+ result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
+
+ result.SetStatus (eReturnStatusFailed);
}
+
return result.Succeeded();
}
OpenPOWER on IntegriCloud