//===-- CommandObjectRegexCommand.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/Interpreter/CommandObjectRegexCommand.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// CommandObjectRegexCommand constructor
//----------------------------------------------------------------------
CommandObjectRegexCommand::CommandObjectRegexCommand(
    CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help,
  llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask,
    bool is_removable)
    : CommandObjectRaw(interpreter, name, help, syntax),
      m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
      m_entries(), m_is_removable(is_removable) {}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
CommandObjectRegexCommand::~CommandObjectRegexCommand() {}

bool CommandObjectRegexCommand::DoExecute(const char *command,
                                          CommandReturnObject &result) {
  if (command) {
    EntryCollection::const_iterator pos, end = m_entries.end();
    for (pos = m_entries.begin(); pos != end; ++pos) {
      RegularExpression::Match regex_match(m_max_matches);

      if (pos->regex.Execute(command, &regex_match)) {
        std::string new_command(pos->command);
        std::string match_str;
        char percent_var[8];
        size_t idx, percent_var_idx;
        for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
          if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
            const int percent_var_len =
                ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
            for (idx = 0; (percent_var_idx = new_command.find(
                               percent_var, idx)) != std::string::npos;) {
              new_command.erase(percent_var_idx, percent_var_len);
              new_command.insert(percent_var_idx, match_str);
              idx += percent_var_idx + match_str.size();
            }
          }
        }
        // Interpret the new command and return this as the result!
        if (m_interpreter.GetExpandRegexAliases())
          result.GetOutputStream().Printf("%s\n", new_command.c_str());
        // Pass in true for "no context switching".  The command that called us
        // should have set up the context appropriately, we shouldn't have to
        // redo that.
        return m_interpreter.HandleCommand(new_command.c_str(),
                                           eLazyBoolCalculate, result, nullptr,
                                           true, true);
      }
    }
    result.SetStatus(eReturnStatusFailed);
    if (!GetSyntax().empty())
      result.AppendError(GetSyntax());
    else
      result.AppendErrorWithFormat("Command contents '%s' failed to match any "
                                   "regular expression in the '%s' regex "
                                   "command.\n",
                                   command, m_cmd_name.c_str());
    return false;
  }
  result.AppendError("empty command passed to regular expression command");
  result.SetStatus(eReturnStatusFailed);
  return false;
}

bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
                                                const char *command_cstr) {
  m_entries.resize(m_entries.size() + 1);
  // Only add the regular expression if it compiles
  if (m_entries.back().regex.Compile(
          llvm::StringRef::withNullAsEmpty(re_cstr))) {
    m_entries.back().command.assign(command_cstr);
    return true;
  }
  // The regex didn't compile...
  m_entries.pop_back();
  return false;
}

int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
                                                int &cursor_char_position,
                                                int match_start_point,
                                                int max_return_elements,
                                                bool &word_complete,
                                                StringList &matches) {
  if (m_completion_type_mask) {
    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
                               cursor_char_position);
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
        match_start_point, max_return_elements, nullptr, word_complete,
        matches);
    return matches.GetSize();
  } else {
    matches.Clear();
    word_complete = false;
  }
  return 0;
}
