//===-- CommandObject.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Interpreter/CommandObject.h"

#include <map>
#include <sstream>
#include <string>

#include <cctype>
#include <cstdlib>

#include "lldb/Core/Address.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/ArchSpec.h"
#include "llvm/ADT/ScopeExit.h"

// These are for the Sourcename completers.
// FIXME: Make a separate file for the completers.
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/FileSpecList.h"

#include "lldb/Target/Language.h"

#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"

using namespace lldb;
using namespace lldb_private;

// CommandObject

CommandObject::CommandObject(CommandInterpreter &interpreter,
                             llvm::StringRef name, llvm::StringRef help,
                             llvm::StringRef syntax, uint32_t flags)
    : m_interpreter(interpreter), m_cmd_name(std::string(name)),
      m_flags(flags), m_deprecated_command_override_callback(nullptr),
      m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
  m_cmd_help_short = std::string(help);
  m_cmd_syntax = std::string(syntax);
}

Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }

llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }

llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }

llvm::StringRef CommandObject::GetSyntax() {
  if (!m_cmd_syntax.empty())
    return m_cmd_syntax;

  StreamString syntax_str;
  syntax_str.PutCString(GetCommandName());

  if (!IsDashDashCommand() && GetOptions() != nullptr)
    syntax_str.PutCString(" <cmd-options>");

  if (!m_arguments.empty()) {
    syntax_str.PutCString(" ");

    if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
        GetOptions()->NumCommandOptions())
      syntax_str.PutCString("-- ");
    GetFormattedCommandArguments(syntax_str);
  }
  m_cmd_syntax = std::string(syntax_str.GetString());

  return m_cmd_syntax;
}

llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }

void CommandObject::SetCommandName(llvm::StringRef name) {
  m_cmd_name = std::string(name);
}

void CommandObject::SetHelp(llvm::StringRef str) {
  m_cmd_help_short = std::string(str);
}

void CommandObject::SetHelpLong(llvm::StringRef str) {
  m_cmd_help_long = std::string(str);
}

void CommandObject::SetSyntax(llvm::StringRef str) {
  m_cmd_syntax = std::string(str);
}

Options *CommandObject::GetOptions() {
  // By default commands don't have options unless this virtual function is
  // overridden by base classes.
  return nullptr;
}

bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
  // See if the subclass has options?
  Options *options = GetOptions();
  if (options != nullptr) {
    Status error;

    auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
    options->NotifyOptionParsingStarting(&exe_ctx);

    const bool require_validation = true;
    llvm::Expected<Args> args_or = options->Parse(
        args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
        require_validation);

    if (args_or) {
      args = std::move(*args_or);
      error = options->NotifyOptionParsingFinished(&exe_ctx);
    } else {
      error = Status::FromError(args_or.takeError());
    }

    if (error.Fail()) {
      result.SetError(error.takeError());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (llvm::Error error = options->VerifyOptions()) {
      result.SetError(std::move(error));
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return true;
  }
  return true;
}

bool CommandObject::CheckRequirements(CommandReturnObject &result) {
  // Nothing should be stored in m_exe_ctx between running commands as
  // m_exe_ctx has shared pointers to the target, process, thread and frame and
  // we don't want any CommandObject instances to keep any of these objects
  // around longer than for a single command. Every command should call
  // CommandObject::Cleanup() after it has completed.
  assert(!m_exe_ctx.GetTargetPtr());
  assert(!m_exe_ctx.GetProcessPtr());
  assert(!m_exe_ctx.GetThreadPtr());
  assert(!m_exe_ctx.GetFramePtr());

  // Lock down the interpreter's execution context prior to running the command
  // so we guarantee the selected target, process, thread and frame can't go
  // away during the execution
  m_exe_ctx = m_interpreter.GetExecutionContext();

  const uint32_t flags = GetFlags().Get();
  if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
               eCommandRequiresThread | eCommandRequiresFrame |
               eCommandTryTargetAPILock)) {

    if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
      result.AppendError(GetInvalidTargetDescription());
      return false;
    }

    if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
      if (!m_exe_ctx.HasTargetScope())
        result.AppendError(GetInvalidTargetDescription());
      else
        result.AppendError(GetInvalidProcessDescription());
      return false;
    }

    if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
      if (!m_exe_ctx.HasTargetScope())
        result.AppendError(GetInvalidTargetDescription());
      else if (!m_exe_ctx.HasProcessScope())
        result.AppendError(GetInvalidProcessDescription());
      else
        result.AppendError(GetInvalidThreadDescription());
      return false;
    }

    if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
      if (!m_exe_ctx.HasTargetScope())
        result.AppendError(GetInvalidTargetDescription());
      else if (!m_exe_ctx.HasProcessScope())
        result.AppendError(GetInvalidProcessDescription());
      else if (!m_exe_ctx.HasThreadScope())
        result.AppendError(GetInvalidThreadDescription());
      else
        result.AppendError(GetInvalidFrameDescription());
      return false;
    }

    if ((flags & eCommandRequiresRegContext) &&
        (m_exe_ctx.GetRegisterContext() == nullptr)) {
      result.AppendError(GetInvalidRegContextDescription());
      return false;
    }

    if (flags & eCommandTryTargetAPILock) {
      Target *target = m_exe_ctx.GetTargetPtr();
      if (target)
        m_api_locker =
            std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
    }
  }

  if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
                        eCommandProcessMustBePaused)) {
    Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process == nullptr) {
      // A process that is not running is considered paused.
      if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
        result.AppendError("process must exist");
        return false;
      }
    } else {
      StateType state = process->GetState();
      switch (state) {
      case eStateInvalid:
      case eStateSuspended:
      case eStateCrashed:
      case eStateStopped:
        break;

      case eStateConnected:
      case eStateAttaching:
      case eStateLaunching:
      case eStateDetached:
      case eStateExited:
      case eStateUnloaded:
        if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
          result.AppendError("process must be launched");
          return false;
        }
        break;

      case eStateRunning:
      case eStateStepping:
        if (GetFlags().Test(eCommandProcessMustBePaused)) {
          result.AppendError("Process is running.  Use 'process interrupt' to "
                             "pause execution.");
          return false;
        }
      }
    }
  }

  if (GetFlags().Test(eCommandProcessMustBeTraced)) {
    Target *target = m_exe_ctx.GetTargetPtr();
    if (target && !target->GetTrace()) {
      result.AppendError("process is not being traced");
      return false;
    }
  }

  return true;
}

void CommandObject::Cleanup() {
  m_exe_ctx.Clear();
  if (m_api_locker.owns_lock())
    m_api_locker.unlock();
}

void CommandObject::HandleCompletion(CompletionRequest &request) {

  m_exe_ctx = m_interpreter.GetExecutionContext();
  llvm::scope_exit reset_ctx([this]() { Cleanup(); });

  // Default implementation of WantsCompletion() is !WantsRawCommandString().
  // Subclasses who want raw command string but desire, for example, argument
  // completion should override WantsCompletion() to return true, instead.
  if (WantsRawCommandString() && !WantsCompletion()) {
    // FIXME: Abstract telling the completion to insert the completion
    // character.
    return;
  } else {
    // Can we do anything generic with the options?
    Options *cur_options = GetOptions();
    OptionElementVector opt_element_vector;

    if (cur_options != nullptr) {
      opt_element_vector = cur_options->ParseForCompletion(
          request.GetParsedLine(), request.GetCursorIndex());

      bool handled_by_options = cur_options->HandleOptionCompletion(
          request, opt_element_vector, GetCommandInterpreter());
      if (handled_by_options)
        return;
    }

    // If we got here, the last word is not an option or an option argument.
    HandleArgumentCompletion(request, opt_element_vector);
  }
}

void CommandObject::HandleArgumentCompletion(
    CompletionRequest &request, OptionElementVector &opt_element_vector) {
  size_t num_arg_entries = GetNumArgumentEntries();
  if (num_arg_entries != 1)
    return;

  CommandArgumentEntry *entry_ptr = GetArgumentEntryAtIndex(0);
  if (!entry_ptr) {
    assert(entry_ptr && "We said there was one entry, but there wasn't.");
    return; // Not worth crashing if asserts are off...
  }
  
  CommandArgumentEntry &entry = *entry_ptr;
  // For now, we only handle the simple case of one homogenous argument type.
  if (entry.size() != 1)
    return;

  // Look up the completion type, and if it has one, invoke it:
  const CommandObject::ArgumentTableEntry *arg_entry =
      FindArgumentDataByType(entry[0].arg_type);
  const ArgumentRepetitionType repeat = entry[0].arg_repetition;

  if (arg_entry == nullptr || arg_entry->completion_type == lldb::eNoCompletion)
    return;

  // FIXME: This should be handled higher in the Command Parser.
  // Check the case where this command only takes one argument, and don't do
  // the completion if we aren't on the first entry:
  if (repeat == eArgRepeatPlain && request.GetCursorIndex() != 0)
    return;

  lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
      GetCommandInterpreter(), arg_entry->completion_type, request, nullptr);

}

bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
                                         bool search_short_help,
                                         bool search_long_help,
                                         bool search_syntax,
                                         bool search_options) {
  bool found_word = false;

  llvm::StringRef short_help = GetHelp();
  llvm::StringRef long_help = GetHelpLong();
  llvm::StringRef syntax_help = GetSyntax();

  if (search_short_help && short_help.contains_insensitive(search_word))
    found_word = true;
  else if (search_long_help && long_help.contains_insensitive(search_word))
    found_word = true;
  else if (search_syntax && syntax_help.contains_insensitive(search_word))
    found_word = true;

  if (!found_word && search_options && GetOptions() != nullptr) {
    StreamString usage_help;
    GetOptions()->GenerateOptionUsage(
        usage_help, *this,
        GetCommandInterpreter().GetDebugger().GetTerminalWidth(),
        GetCommandInterpreter().GetDebugger().GetUseColor());
    if (!usage_help.Empty()) {
      llvm::StringRef usage_text = usage_help.GetString();
      if (usage_text.contains_insensitive(search_word))
        found_word = true;
    }
  }

  return found_word;
}

bool CommandObject::ParseOptionsAndNotify(Args &args,
                                          CommandReturnObject &result,
                                          OptionGroupOptions &group_options,
                                          ExecutionContext &exe_ctx) {
  if (!ParseOptions(args, result))
    return false;

  Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
  if (error.Fail()) {
    result.AppendError(error.AsCString());
    return false;
  }
  return true;
}

void CommandObject::AddSimpleArgumentList(
    CommandArgumentType arg_type, ArgumentRepetitionType repetition_type) {

  CommandArgumentEntry arg_entry;
  CommandArgumentData simple_arg;

  // Define the first (and only) variant of this arg.
  simple_arg.arg_type = arg_type;
  simple_arg.arg_repetition = repetition_type;

  // There is only one variant this argument could be; put it into the argument
  // entry.
  arg_entry.push_back(simple_arg);

  // Push the data for the first argument into the m_arguments vector.
  m_arguments.push_back(arg_entry);
}

int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }

CommandObject::CommandArgumentEntry *
CommandObject::GetArgumentEntryAtIndex(int idx) {
  if (static_cast<size_t>(idx) < m_arguments.size())
    return &(m_arguments[idx]);

  return nullptr;
}

const CommandObject::ArgumentTableEntry *
CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
  for (int i = 0; i < eArgTypeLastArg; ++i)
    if (g_argument_table[i].arg_type == arg_type)
      return &(g_argument_table[i]);

  return nullptr;
}

void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
                                    CommandInterpreter &interpreter) {
  const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);

  // The table is *supposed* to be kept in arg_type order, but someone *could*
  // have messed it up...

  if (entry->arg_type != arg_type)
    entry = CommandObject::FindArgumentDataByType(arg_type);

  if (!entry)
    return;

  StreamString name_str;
  name_str.Printf("<%s>", entry->arg_name);

  if (entry->help_function) {
    llvm::StringRef help_text = entry->help_function();
    if (!entry->help_function.self_formatting) {
      interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
                                          help_text, name_str.GetSize());
    } else {
      interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
                                 name_str.GetSize());
    }
  } else {
    interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
                                        entry->help_text, name_str.GetSize());

    // Print enum values and their description if any.
    OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;
    if (!enum_values.empty()) {
      str.EOL();
      size_t longest = 0;
      for (const OptionEnumValueElement &element : enum_values)
        longest =
            std::max(longest, llvm::StringRef(element.string_value).size());
      str.IndentMore(5);
      for (const OptionEnumValueElement &element : enum_values) {
        str.Indent();
        interpreter.OutputHelpText(str, element.string_value, ":",
                                   element.usage, longest);
      }
      str.IndentLess(5);
      str.EOL();
    }
  }
}

const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
  const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);

  // The table is *supposed* to be kept in arg_type order, but someone *could*
  // have messed it up...

  if (entry->arg_type != arg_type)
    entry = CommandObject::FindArgumentDataByType(arg_type);

  if (entry)
    return entry->arg_name;

  return nullptr;
}

bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
  return (arg_repeat_type == eArgRepeatPairPlain) ||
         (arg_repeat_type == eArgRepeatPairOptional) ||
         (arg_repeat_type == eArgRepeatPairPlus) ||
         (arg_repeat_type == eArgRepeatPairStar) ||
         (arg_repeat_type == eArgRepeatPairRange) ||
         (arg_repeat_type == eArgRepeatPairRangeOptional);
}

std::optional<ArgumentRepetitionType> 
CommandObject::ArgRepetitionFromString(llvm::StringRef string) {
  return llvm::StringSwitch<ArgumentRepetitionType>(string)
  .Case("plain", eArgRepeatPlain)  
  .Case("optional", eArgRepeatOptional)
  .Case("plus", eArgRepeatPlus)
  .Case("star", eArgRepeatStar) 
  .Case("range", eArgRepeatRange)
  .Case("pair-plain", eArgRepeatPairPlain)
  .Case("pair-optional", eArgRepeatPairOptional)
  .Case("pair-plus", eArgRepeatPairPlus)
  .Case("pair-star", eArgRepeatPairStar)
  .Case("pair-range", eArgRepeatPairRange)
  .Case("pair-range-optional", eArgRepeatPairRangeOptional)
  .Default({});
}

static CommandObject::CommandArgumentEntry
OptSetFiltered(uint32_t opt_set_mask,
               CommandObject::CommandArgumentEntry &cmd_arg_entry) {
  CommandObject::CommandArgumentEntry ret_val;
  for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
    if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
      ret_val.push_back(cmd_arg_entry[i]);
  return ret_val;
}

// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
// take all the argument data into account.  On rare cases where some argument
// sticks with certain option sets, this function returns the option set
// filtered args.
void CommandObject::GetFormattedCommandArguments(Stream &str,
                                                 uint32_t opt_set_mask) {
  int num_args = m_arguments.size();
  for (int i = 0; i < num_args; ++i) {
    if (i > 0)
      str.Printf(" ");
    CommandArgumentEntry arg_entry =
        opt_set_mask == LLDB_OPT_SET_ALL
            ? m_arguments[i]
            : OptSetFiltered(opt_set_mask, m_arguments[i]);
    // This argument is not associated with the current option set, so skip it.
    if (arg_entry.empty())
      continue;
    int num_alternatives = arg_entry.size();

    if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
      const char *first_name = GetArgumentName(arg_entry[0].arg_type);
      const char *second_name = GetArgumentName(arg_entry[1].arg_type);
      switch (arg_entry[0].arg_repetition) {
      case eArgRepeatPairPlain:
        str.Printf("<%s> <%s>", first_name, second_name);
        break;
      case eArgRepeatPairOptional:
        str.Printf("[<%s> <%s>]", first_name, second_name);
        break;
      case eArgRepeatPairPlus:
        str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
                   first_name, second_name);
        break;
      case eArgRepeatPairStar:
        str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
                   first_name, second_name);
        break;
      case eArgRepeatPairRange:
        str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
                   first_name, second_name);
        break;
      case eArgRepeatPairRangeOptional:
        str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
                   first_name, second_name);
        break;
      // Explicitly test for all the rest of the cases, so if new types get
      // added we will notice the missing case statement(s).
      case eArgRepeatPlain:
      case eArgRepeatOptional:
      case eArgRepeatPlus:
      case eArgRepeatStar:
      case eArgRepeatRange:
        // These should not be reached, as they should fail the IsPairType test
        // above.
        break;
      }
    } else {
      StreamString names;
      for (int j = 0; j < num_alternatives; ++j) {
        if (j > 0)
          names.Printf(" | ");
        names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
      }

      std::string name_str = std::string(names.GetString());
      switch (arg_entry[0].arg_repetition) {
      case eArgRepeatPlain:
        str.Printf("<%s>", name_str.c_str());
        break;
      case eArgRepeatPlus:
        str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
        break;
      case eArgRepeatStar:
        str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
        break;
      case eArgRepeatOptional:
        str.Printf("[<%s>]", name_str.c_str());
        break;
      case eArgRepeatRange:
        str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
        break;
      // Explicitly test for all the rest of the cases, so if new types get
      // added we will notice the missing case statement(s).
      case eArgRepeatPairPlain:
      case eArgRepeatPairOptional:
      case eArgRepeatPairPlus:
      case eArgRepeatPairStar:
      case eArgRepeatPairRange:
      case eArgRepeatPairRangeOptional:
        // These should not be hit, as they should pass the IsPairType test
        // above, and control should have gone into the other branch of the if
        // statement.
        break;
      }
    }
  }
}

CommandArgumentType
CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
  CommandArgumentType return_type = eArgTypeLastArg;

  arg_name = arg_name.ltrim('<').rtrim('>');

  for (int i = 0; i < eArgTypeLastArg; ++i)
    if (arg_name == g_argument_table[i].arg_name)
      return_type = g_argument_table[i].arg_type;

  return return_type;
}

void CommandObject::FormatLongHelpText(Stream &output_strm,
                                       llvm::StringRef long_help) {
  CommandInterpreter &interpreter = GetCommandInterpreter();
  std::stringstream lineStream{std::string(long_help)};
  std::string line;
  while (std::getline(lineStream, line)) {
    if (line.empty()) {
      output_strm << "\n";
      continue;
    }
    size_t result = line.find_first_not_of(" \t");
    if (result == std::string::npos) {
      result = 0;
    }
    std::string whitespace_prefix = line.substr(0, result);
    std::string remainder = line.substr(result);
    interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,
                                        remainder);
  }
}

void CommandObject::GenerateHelpText(CommandReturnObject &result) {
  GenerateHelpText(result.GetOutputStream());

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

void CommandObject::GenerateHelpText(Stream &output_strm) {
  CommandInterpreter &interpreter = GetCommandInterpreter();
  std::string help_text(GetHelp());
  if (WantsRawCommandString()) {
    help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
  }
  interpreter.OutputFormattedHelpText(output_strm, "", help_text);
  output_strm << "\nSyntax: " << GetSyntax() << "\n";
  Options *options = GetOptions();
  if (options != nullptr) {
    options->GenerateOptionUsage(
        output_strm, *this,
        GetCommandInterpreter().GetDebugger().GetTerminalWidth(),
        GetCommandInterpreter().GetDebugger().GetUseColor());
  }
  llvm::StringRef long_help = GetHelpLong();
  if (!long_help.empty()) {
    FormatLongHelpText(output_strm, long_help);
  }
  if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
    if (WantsRawCommandString() && !WantsCompletion()) {
      // Emit the message about using ' -- ' between the end of the command
      // options and the raw input conditionally, i.e., only if the command
      // object does not want completion.
      interpreter.OutputFormattedHelpText(
          output_strm, "", "",
          "\nImportant Note: Because this command takes 'raw' input, if you "
          "use any command options"
          " you must use ' -- ' between the end of the command options and the "
          "beginning of the raw input.",
          1);
    } else if (GetNumArgumentEntries() > 0) {
      // Also emit a warning about using "--" in case you are using a command
      // that takes options and arguments.
      interpreter.OutputFormattedHelpText(
          output_strm, "", "",
          "\nThis command takes options and free-form arguments.  If your "
          "arguments resemble"
          " option specifiers (i.e., they start with a - or --), you must use "
          "' -- ' between"
          " the end of the command options and the beginning of the arguments.",
          1);
    }
  }
}

void CommandObject::AddIDsArgumentData(CommandObject::IDType type) {
  CommandArgumentEntry arg;
  CommandArgumentData id_arg;
  CommandArgumentData id_range_arg;

  // Create the first variant for the first (and only) argument for this
  // command.
  switch (type) {
  case eBreakpointArgs:
    id_arg.arg_type = eArgTypeBreakpointID;
    id_range_arg.arg_type = eArgTypeBreakpointIDRange;
    break;
  case eWatchpointArgs:
    id_arg.arg_type = eArgTypeWatchpointID;
    id_range_arg.arg_type = eArgTypeWatchpointIDRange;
    break;
  }
  id_arg.arg_repetition = eArgRepeatOptional;
  id_range_arg.arg_repetition = eArgRepeatOptional;

  // The first (and only) argument for this command could be either an id or an
  // id_range. Push both variants into the entry for the first argument for
  // this command.
  arg.push_back(id_arg);
  arg.push_back(id_range_arg);
  m_arguments.push_back(arg);
}

const char *CommandObject::GetArgumentTypeAsCString(
    const lldb::CommandArgumentType arg_type) {
  assert(arg_type < eArgTypeLastArg &&
         "Invalid argument type passed to GetArgumentTypeAsCString");
  return g_argument_table[arg_type].arg_name;
}

const char *CommandObject::GetArgumentDescriptionAsCString(
    const lldb::CommandArgumentType arg_type) {
  assert(arg_type < eArgTypeLastArg &&
         "Invalid argument type passed to GetArgumentDescriptionAsCString");
  return g_argument_table[arg_type].help_text;
}

Target &CommandObject::GetDummyTarget() {
  return m_interpreter.GetDebugger().GetDummyTarget();
}

Target &CommandObject::GetTarget() {
  // Prefer the frozen execution context in the command object.
  if (Target *target = m_exe_ctx.GetTargetPtr())
    return *target;

  // Fallback to the command interpreter's execution context in case we get
  // called after DoExecute has finished. For example, when doing multi-line
  // expression that uses an input reader or breakpoint callbacks.
  if (Target *target = m_interpreter.GetExecutionContext().GetTargetPtr())
    return *target;

  // Finally, if we have no other target, get the selected target.
  if (TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget())
    return *target_sp;

  // We only have the dummy target.
  return GetDummyTarget();
}

Thread *CommandObject::GetDefaultThread() {
  Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
  if (thread_to_use)
    return thread_to_use;

  Process *process = m_exe_ctx.GetProcessPtr();
  if (!process) {
    Target *target = m_exe_ctx.GetTargetPtr();
    if (!target) {
      target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    }
    if (target)
      process = target->GetProcessSP().get();
  }

  if (process)
    return process->GetThreadList().GetSelectedThread().get();
  else
    return nullptr;
}

void CommandObjectParsed::Execute(const char *args_string,
                                  CommandReturnObject &result) {
  bool handled = false;
  Args cmd_args(args_string);
  if (HasOverrideCallback()) {
    Args full_args(GetCommandName());
    full_args.AppendArguments(cmd_args);
    handled =
        InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
  }
  if (!handled) {
    for (auto entry : llvm::enumerate(cmd_args.entries())) {
      const Args::ArgEntry &value = entry.value();
      if (!value.ref().empty() && value.GetQuoteChar() == '`') {
        // We have to put the backtick back in place for PreprocessCommand.
        std::string opt_string = value.c_str();
        Status error;
        error = m_interpreter.PreprocessToken(opt_string);
        if (error.Success())
          cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);
      }
    }

    if (CheckRequirements(result)) {
      if (ParseOptions(cmd_args, result)) {
        // Call the command-specific version of 'Execute', passing it the
        // already processed arguments.
        if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
          result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
                                        GetCommandName());
          Cleanup();
          return;
        }
        m_interpreter.IncreaseCommandUsage(*this);
        DoExecute(cmd_args, result);
      }
    }

    Cleanup();
  }
}

void CommandObjectRaw::Execute(const char *args_string,
                               CommandReturnObject &result) {
  bool handled = false;
  if (HasOverrideCallback()) {
    std::string full_command(GetCommandName());
    full_command += ' ';
    full_command += args_string;
    const char *argv[2] = {nullptr, nullptr};
    argv[0] = full_command.c_str();
    handled = InvokeOverrideCallback(argv, result);
  }
  if (!handled) {
    if (CheckRequirements(result))
      DoExecute(args_string, result);

    Cleanup();
  }
}
