//===-- 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() != nullptr)
      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;
}
