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 != nullptr) {
          // 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();
}
Example #2
0
bool
CommandInterpreter::HandleCommand 
(
    const char *command_line, 
    bool add_to_history,
    CommandReturnObject &result,
    ExecutionContext *override_context
)
{
    // FIXME: there should probably be a mutex to make sure only one thread can
    // run the interpreter at a time.

    // TODO: this should be a logging channel in lldb.
//    if (DebugSelf())
//    {
//        result.AppendMessageWithFormat ("Processing command: %s\n", command_line);
//    }

    m_debugger.UpdateExecutionContext (override_context);

    if (command_line == NULL || command_line[0] == '\0')
    {
        if (m_command_history.empty())
        {
            result.AppendError ("empty command");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        else
        {
            command_line = m_repeat_command.c_str();
            if (m_repeat_command.empty())
            {
                result.AppendErrorWithFormat("No auto repeat.\n");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        add_to_history = false;
    }

    Args command_args(command_line);

    if (command_args.GetArgumentCount() > 0)
    {
        const char *command_cstr = command_args.GetArgumentAtIndex(0);
        if (command_cstr)
        {

            // 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)
            {
                if (command_obj->IsAlias())
                {
                    BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
                    if (!result.Succeeded())
                        return false;
                }

                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_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;
                        command_obj->ExecuteRawCommandString (*this, stripped_command, result);
                    }
                }
                else
                {
                    // Remove the command from the args.
                    command_args.Shift();
                    command_obj->ExecuteWithOptions (*this, 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 ("'.");

                    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);

                result.SetStatus (eReturnStatusFailed);
            }
        }
    }
    return result.Succeeded();
}