//===-- 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;

namespace {
/// RAII scope that resets the result's status to eReturnStatusInvalid on entry
/// and asserts on exit that DoExecute changed it (directly via SetStatus, or
/// indirectly via AppendError/SetError, which call SetStatus internally).
class DoExecuteStatusCheck {
public:
  explicit DoExecuteStatusCheck(CommandReturnObject &result)
      : m_result(result) {
    m_result.SetStatus(eReturnStatusInvalid);
  }
  ~DoExecuteStatusCheck() {
    assert(m_result.GetStatus() != eReturnStatusInvalid &&
           "DoExecute did not set a status on the CommandReturnObject");
  }

private:
  CommandReturnObject &m_result;
};
} // namespace

// 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.
  //
  // The dummy target is allowed here because it is always alive, never causes
  // resource leaks, and can appear when a command (e.g. "command source") is
  // invoked re-entrantly before the outer Cleanup() has run.
  assert(!m_exe_ctx.GetTargetPtr() ||
         m_exe_ctx.GetTargetPtr()->IsDummyTarget());
  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. The dummy target is only adopted when the
  // command opts in via eCommandAllowsDummyTarget, so other commands won't
  // accidentally see it through m_exe_ctx.
  const uint32_t flags = GetFlags().Get();
  const bool adopt_dummy_target = flags & eCommandAllowsDummyTarget;
  m_exe_ctx = m_interpreter.GetExecutionContext(adopt_dummy_target);

  if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
               eCommandRequiresThread | eCommandRequiresFrame |
               eCommandTryTargetAPILock)) {

    Target *target = m_exe_ctx.GetTargetPtr();
    if ((flags & eCommandRequiresTarget) &&
        (!target || target->IsDummyTarget())) {
      result.AppendError(GetInvalidTargetDescription());
      return false;
    }

    if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
      if (!target || target->IsDummyTarget())
        result.AppendError(GetInvalidTargetDescription());
      else
        result.AppendError(GetInvalidProcessDescription());
      return false;
    }

    if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
      if (!target || target->IsDummyTarget())
        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 (!target || target->IsDummyTarget())
        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) {
      if (target && !target->IsDummyTarget())
        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, falling back
  // to the interpreter's execution context for paths like multi-line
  // expressions or breakpoint callbacks that run after DoExecute has
  // finished. Both honor eCommandAllowsDummyTarget when deciding whether to
  // substitute the dummy target, so no post-hoc filtering is needed.
  const uint32_t flags = GetFlags().Get();
  const bool adopt_dummy_target = flags & eCommandAllowsDummyTarget;
  Target *target = m_exe_ctx.GetTargetPtr();
  if (!target)
    target =
        m_interpreter.GetExecutionContext(adopt_dummy_target).GetTargetPtr();

  // CheckRequirements has already guaranteed a non-dummy target for any
  // command declaring a Requires* flag.
  assert(target || !(flags & (eCommandRequiresTarget | eCommandRequiresProcess |
                              eCommandRequiresThread | eCommandRequiresFrame)));
  return target;
}

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.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);
        DoExecuteStatusCheck check(result);
        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)) {
      DoExecuteStatusCheck check(result);
      DoExecute(args_string, result);
    }

    Cleanup();
  }
}
