//===-- CommandObjectFrame.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 "CommandObjectFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/ValueObject/ValueObject.h"

#include <memory>
#include <optional>
#include <string>

using namespace lldb;
using namespace lldb_private;

#pragma mark CommandObjectFrameDiagnose

// CommandObjectFrameInfo

// CommandObjectFrameDiagnose

#define LLDB_OPTIONS_frame_diag
#include "CommandOptions.inc"

class CommandObjectFrameDiagnose : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r':
        reg = ConstString(option_arg);
        break;

      case 'a': {
        address.emplace();
        if (option_arg.getAsInteger(0, *address)) {
          address.reset();
          error = Status::FromErrorStringWithFormat(
              "invalid address argument '%s'", option_arg.str().c_str());
        }
      } break;

      case 'o': {
        offset.emplace();
        if (option_arg.getAsInteger(0, *offset)) {
          offset.reset();
          error = Status::FromErrorStringWithFormat(
              "invalid offset argument '%s'", option_arg.str().c_str());
        }
      } break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      address.reset();
      reg.reset();
      offset.reset();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_diag_options);
    }

    // Options.
    std::optional<lldb::addr_t> address;
    std::optional<ConstString> reg;
    std::optional<int64_t> offset;
  };

  CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame diagnose",
                            "Try to determine what path the current stop "
                            "location used to get to a register or address",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameDiagnose() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Thread *thread = m_exe_ctx.GetThreadPtr();
    StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);

    ValueObjectSP valobj_sp;

    if (m_options.address) {
      if (m_options.reg || m_options.offset) {
        result.AppendError(
            "`frame diagnose --address` is incompatible with other arguments.");
        return;
      }
      valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
    } else if (m_options.reg) {
      valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
          *m_options.reg, m_options.offset.value_or(0));
    } else {
      StopInfoSP stop_info_sp = thread->GetStopInfo();
      if (!stop_info_sp) {
        result.AppendError("No arguments provided, and no stop info.");
        return;
      }

      valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
    }

    if (!valobj_sp) {
      result.AppendError("No diagnosis available.");
      return;
    }

    DumpValueObjectOptions::DeclPrintingHelper helper =
        [&valobj_sp](ConstString type, ConstString var,
                     const DumpValueObjectOptions &opts,
                     Stream &stream) -> bool {
      const ValueObject::GetExpressionPathFormat format = ValueObject::
          GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
      valobj_sp->GetExpressionPath(stream, format);
      stream.PutCString(" =");
      return true;
    };

    DumpValueObjectOptions options;
    options.SetDeclPrintingHelper(helper);
    // We've already handled the case where the value object sp is null, so
    // this is just to make sure future changes don't skip that:
    assert(valobj_sp.get() && "Must have a valid ValueObject to print");
    ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
    if (llvm::Error error = printer.PrintValueObject())
      result.AppendError(toString(std::move(error)));
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectFrameInfo

// CommandObjectFrameInfo

class CommandObjectFrameInfo : public CommandObjectParsed {
public:
  CommandObjectFrameInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame info",
                            "List information about the current "
                            "stack frame in the current thread.",
                            "frame info",
                            eCommandRequiresFrame | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {}

  ~CommandObjectFrameInfo() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectFrameSelect

// CommandObjectFrameSelect

#define LLDB_OPTIONS_frame_select
#include "CommandOptions.inc"

class CommandObjectFrameSelect : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r': {
        int32_t offset = 0;
        if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
          error = Status::FromErrorStringWithFormat(
              "invalid frame offset argument '%s'", option_arg.str().c_str());
        } else
          relative_frame_offset = offset;
        break;
      }

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      relative_frame_offset.reset();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_select_options);
    }

    std::optional<int32_t> relative_frame_offset;
  };

  CommandObjectFrameSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame select",
                            "Select the current stack frame by "
                            "index from within the current thread "
                            "(see 'thread backtrace'.)",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameSelect() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "thread" for validity as eCommandRequiresThread ensures
    // it is valid
    Thread *thread = m_exe_ctx.GetThreadPtr();

    uint32_t frame_idx = UINT32_MAX;
    if (m_options.relative_frame_offset) {
      // The one and only argument is a signed relative frame index
      frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
      if (frame_idx == UINT32_MAX)
        frame_idx = 0;

      // If moving up/down by one, skip over hidden frames.
      if (*m_options.relative_frame_offset == 1 ||
          *m_options.relative_frame_offset == -1) {
        uint32_t candidate_idx = frame_idx;
        const unsigned max_depth = 12;
        for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
          if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
            candidate_idx = UINT32_MAX;
            break;
          }
          candidate_idx += *m_options.relative_frame_offset;
          if (auto candidate_sp = thread->GetStackFrameAtIndex(candidate_idx)) {
            if (candidate_sp->IsHidden())
              continue;
            // Now candidate_idx is the first non-hidden frame.
            break;
          }
          candidate_idx = UINT32_MAX;
          break;
        };
        if (candidate_idx != UINT32_MAX)
          m_options.relative_frame_offset = candidate_idx - frame_idx;
      }

      if (*m_options.relative_frame_offset < 0) {
        if (static_cast<int32_t>(frame_idx) >=
            -*m_options.relative_frame_offset)
          frame_idx += *m_options.relative_frame_offset;
        else {
          if (frame_idx == 0) {
            // If you are already at the bottom of the stack, then just warn
            // and don't reset the frame.
            result.AppendError("Already at the bottom of the stack.");
            return;
          } else
            frame_idx = 0;
        }
      } else if (*m_options.relative_frame_offset > 0) {
        // I don't want "up 20" where "20" takes you past the top of the stack
        // to produce an error, but rather to just go to the top.  OTOH, start
        // by seeing if the requested frame exists, in which case we can avoid 
        // counting the stack here...
        const uint32_t frame_requested = frame_idx 
            + *m_options.relative_frame_offset;
        StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
        if (frame_sp)
          frame_idx = frame_requested;
        else {
          // The request went past the stack, so handle that case:
          const uint32_t num_frames = thread->GetStackFrameCount();
          if (static_cast<int32_t>(num_frames - frame_idx) >
              *m_options.relative_frame_offset)
          frame_idx += *m_options.relative_frame_offset;
          else {
            if (frame_idx == num_frames - 1) {
              // If we are already at the top of the stack, just warn and don't
              // reset the frame.
              result.AppendError("Already at the top of the stack.");
              return;
            } else
              frame_idx = num_frames - 1;
          }
        }
      }
    } else {
      if (command.GetArgumentCount() > 1) {
        result.AppendErrorWithFormat(
            "too many arguments; expected frame-index, saw '%s'.\n",
            command[0].c_str());
        m_options.GenerateOptionUsage(
            result.GetErrorStream(), *this,
            GetCommandInterpreter().GetDebugger().GetTerminalWidth());
        return;
      }

      if (command.GetArgumentCount() == 1) {
        if (command[0].ref().getAsInteger(0, frame_idx)) {
          result.AppendErrorWithFormat("invalid frame index argument '%s'.",
                                       command[0].c_str());
          return;
        }
      } else if (command.GetArgumentCount() == 0) {
        frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
        if (frame_idx == UINT32_MAX) {
          frame_idx = 0;
        }
      }
    }

    bool success = thread->SetSelectedFrameByIndexNoisily(
        frame_idx, result.GetOutputStream());
    if (success) {
      m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
                                   frame_idx);
    }
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectFrameVariable
// List images with associated information
class CommandObjectFrameVariable : public CommandObjectParsed {
public:
  CommandObjectFrameVariable(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame variable",
            "Show variables for the current stack frame. Defaults to all "
            "arguments and local variables in scope. Names of argument, "
            "local, file static and file global variables can be specified.",
            nullptr,
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
                eCommandRequiresProcess),
        m_option_variable(
            true), // Include the frame specific options by passing "true"
        m_option_format(eFormatDefault) {
    SetHelpLong(R"(
Children of aggregate variables can be specified such as 'var->child.x'.  In
'frame variable', the operators -> and [] do not invoke operator overloads if
they exist, but directly access the specified element.  If you want to trigger
operator overloads use the expression command to print the variable instead.

It is worth noting that except for overloaded operators, when printing local
variables 'expr local_var' and 'frame var local_var' produce the same results.
However, 'frame variable' is more efficient, since it uses debug information and
memory reads directly, rather than parsing and evaluating an expression, which
may even involve JITing and running code in the target program.)");

    AddSimpleArgumentList(eArgTypeVarName, eArgRepeatStar);

    m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_format,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectFrameVariable() override = default;

  Options *GetOptions() override { return &m_option_group; }

protected:
  llvm::StringRef GetScopeString(VariableSP var_sp) {
    if (!var_sp)
      return llvm::StringRef();

    switch (var_sp->GetScope()) {
    case eValueTypeVariableGlobal:
      return "GLOBAL: ";
    case eValueTypeVariableStatic:
      return "STATIC: ";
    case eValueTypeVariableArgument:
      return "ARG: ";
    case eValueTypeVariableLocal:
      return "LOCAL: ";
    case eValueTypeVariableThreadLocal:
      return "THREAD: ";
    default:
      break;
    }

    return llvm::StringRef();
  }

  /// Returns true if `scope` matches any of the options in `m_option_variable`.
  bool ScopeRequested(lldb::ValueType scope) {
    switch (scope) {
    case eValueTypeVariableGlobal:
    case eValueTypeVariableStatic:
      return m_option_variable.show_globals;
    case eValueTypeVariableArgument:
      return m_option_variable.show_args;
    case eValueTypeVariableLocal:
      return m_option_variable.show_locals;
    case eValueTypeInvalid:
    case eValueTypeRegister:
    case eValueTypeRegisterSet:
    case eValueTypeConstResult:
    case eValueTypeVariableThreadLocal:
    case eValueTypeVTable:
    case eValueTypeVTableEntry:
      return false;
    }
    llvm_unreachable("Unexpected scope value");
  }

  /// Finds all the variables in `all_variables` whose name matches `regex`,
  /// inserting them into `matches`. Variables already contained in `matches`
  /// are not inserted again.
  /// Nullopt is returned in case of no matches.
  /// A sub-range of `matches` with all newly inserted variables is returned.
  /// This may be empty if all matches were already contained in `matches`.
  std::optional<llvm::ArrayRef<VariableSP>>
  findUniqueRegexMatches(RegularExpression &regex,
                         VariableList &matches,
                         const VariableList &all_variables) {
    bool any_matches = false;
    const size_t previous_num_vars = matches.GetSize();

    for (const VariableSP &var : all_variables) {
      if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
        continue;
      any_matches = true;
      matches.AddVariableIfUnique(var);
    }

    if (any_matches)
      return matches.toArrayRef().drop_front(previous_num_vars);
    return std::nullopt;
  }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "frame" for validity as eCommandRequiresFrame ensures
    // it is valid
    StackFrame *frame = m_exe_ctx.GetFramePtr();

    Stream &s = result.GetOutputStream();

    // Using a regex should behave like looking for an exact name match: it
    // also finds globals.
    m_option_variable.show_globals |= m_option_variable.use_regex;

    // Be careful about the stack frame, if any summary formatter runs code, it
    // might clear the StackFrameList for the thread.  So hold onto a shared
    // pointer to the frame so it stays alive.

    Status error;
    VariableList *variable_list =
        frame->GetVariableList(m_option_variable.show_globals, &error);

    if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
      result.AppendError(error.AsCString());

    }
    ValueObjectSP valobj_sp;

    TypeSummaryImplSP summary_format_sp;
    if (!m_option_variable.summary.IsCurrentValueEmpty())
      DataVisualization::NamedSummaryFormats::GetSummaryFormat(
          ConstString(m_option_variable.summary.GetCurrentValue()),
          summary_format_sp);
    else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
      summary_format_sp = std::make_shared<StringSummaryFormat>(
          TypeSummaryImpl::Flags(),
          m_option_variable.summary_string.GetCurrentValue());

    DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
        eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
        summary_format_sp));

    const SymbolContext &sym_ctx =
        frame->GetSymbolContext(eSymbolContextFunction);
    if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
      m_option_variable.show_globals = true;

    if (variable_list) {
      const Format format = m_option_format.GetFormat();
      options.SetFormat(format);

      if (!command.empty()) {
        VariableList regex_var_list;

        // If we have any args to the variable command, we will make variable
        // objects from them...
        for (auto &entry : command) {
          if (m_option_variable.use_regex) {
            llvm::StringRef name_str = entry.ref();
            RegularExpression regex(name_str);
            if (regex.IsValid()) {
              std::optional<llvm::ArrayRef<VariableSP>> results =
                  findUniqueRegexMatches(regex, regex_var_list, *variable_list);
              if (!results) {
                result.AppendErrorWithFormat(
                    "no variables matched the regular expression '%s'.",
                    entry.c_str());
                continue;
              }
              for (const VariableSP &var_sp : *results) {
                valobj_sp = frame->GetValueObjectForFrameVariable(
                    var_sp, m_varobj_options.use_dynamic);
                if (valobj_sp) {
                  std::string scope_string;
                  if (m_option_variable.show_scope)
                    scope_string = GetScopeString(var_sp).str();

                  if (!scope_string.empty())
                    s.PutCString(scope_string);

                  if (m_option_variable.show_decl &&
                      var_sp->GetDeclaration().GetFile()) {
                    bool show_fullpaths = false;
                    bool show_module = true;
                    if (var_sp->DumpDeclaration(&s, show_fullpaths,
                                                show_module))
                      s.PutCString(": ");
                  }
                  auto &strm = result.GetOutputStream();
                  if (llvm::Error error = valobj_sp->Dump(strm, options))
                    result.AppendError(toString(std::move(error)));
                }
              }
            } else {
              if (llvm::Error err = regex.GetError())
                result.AppendError(llvm::toString(std::move(err)));
              else
                result.AppendErrorWithFormat(
                    "unknown regex error when compiling '%s'", entry.c_str());
            }
          } else // No regex, either exact variable names or variable
                 // expressions.
          {
            Status error;
            uint32_t expr_path_options =
                StackFrame::eExpressionPathOptionCheckPtrVsMember |
                StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
                StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
            lldb::VariableSP var_sp;
            valobj_sp = frame->GetValueForVariableExpressionPath(
                entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
                var_sp, error);
            if (valobj_sp) {
              std::string scope_string;
              if (m_option_variable.show_scope)
                scope_string = GetScopeString(var_sp).str();

              if (!scope_string.empty())
                s.PutCString(scope_string);
              if (m_option_variable.show_decl && var_sp &&
                  var_sp->GetDeclaration().GetFile()) {
                var_sp->GetDeclaration().DumpStopContext(&s, false);
                s.PutCString(": ");
              }

              options.SetFormat(format);
              options.SetVariableFormatDisplayLanguage(
                  valobj_sp->GetPreferredDisplayLanguage());

              Stream &output_stream = result.GetOutputStream();
              options.SetRootValueObjectName(
                  valobj_sp->GetParent() ? entry.c_str() : nullptr);
              if (llvm::Error error = valobj_sp->Dump(output_stream, options))
                result.AppendError(toString(std::move(error)));
            } else {
              if (auto error_cstr = error.AsCString(nullptr))
                result.AppendError(error_cstr);
              else
                result.AppendErrorWithFormat(
                    "unable to find any variable expression path that matches "
                    "'%s'.",
                    entry.c_str());
            }
          }
        }
      } else // No command arg specified.  Use variable_list, instead.
      {
        const size_t num_variables = variable_list->GetSize();
        if (num_variables > 0) {
          for (size_t i = 0; i < num_variables; i++) {
            VariableSP var_sp = variable_list->GetVariableAtIndex(i);
            if (!ScopeRequested(var_sp->GetScope()))
                continue;
            std::string scope_string;
            if (m_option_variable.show_scope)
              scope_string = GetScopeString(var_sp).str();

            // Use the variable object code to make sure we are using the same
            // APIs as the public API will be using...
            valobj_sp = frame->GetValueObjectForFrameVariable(
                var_sp, m_varobj_options.use_dynamic);
            if (valobj_sp) {
              // When dumping all variables, don't print any variables that are
              // not in scope to avoid extra unneeded output
              if (valobj_sp->IsInScope()) {
                if (!valobj_sp->GetTargetSP()
                         ->GetDisplayRuntimeSupportValues() &&
                    valobj_sp->IsRuntimeSupportValue())
                  continue;

                if (!scope_string.empty())
                  s.PutCString(scope_string);

                if (m_option_variable.show_decl &&
                    var_sp->GetDeclaration().GetFile()) {
                  var_sp->GetDeclaration().DumpStopContext(&s, false);
                  s.PutCString(": ");
                }

                options.SetFormat(format);
                options.SetVariableFormatDisplayLanguage(
                    valobj_sp->GetPreferredDisplayLanguage());
                options.SetRootValueObjectName(
                    var_sp ? var_sp->GetName().AsCString() : nullptr);
                if (llvm::Error error =
                        valobj_sp->Dump(result.GetOutputStream(), options))
                  result.AppendError(toString(std::move(error)));
              }
            }
          }
        }
      }
      if (result.GetStatus() != eReturnStatusFailed)
        result.SetStatus(eReturnStatusSuccessFinishResult);
    }

    if (m_option_variable.show_recognized_args) {
      auto recognized_frame = frame->GetRecognizedFrame();
      if (recognized_frame) {
        ValueObjectListSP recognized_arg_list =
            recognized_frame->GetRecognizedArguments();
        if (recognized_arg_list) {
          for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
            options.SetFormat(m_option_format.GetFormat());
            options.SetVariableFormatDisplayLanguage(
                rec_value_sp->GetPreferredDisplayLanguage());
            options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
            if (llvm::Error error =
                    rec_value_sp->Dump(result.GetOutputStream(), options))
              result.AppendError(toString(std::move(error)));
          }
        }
      }
    }

    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
                                           m_cmd_name);

    // Increment statistics.
    TargetStats &target_stats = GetTarget().GetStatistics();
    if (result.Succeeded())
      target_stats.GetFrameVariableStats().NotifySuccess();
    else
      target_stats.GetFrameVariableStats().NotifyFailure();
  }

  OptionGroupOptions m_option_group;
  OptionGroupVariable m_option_variable;
  OptionGroupFormat m_option_format;
  OptionGroupValueObjectDisplay m_varobj_options;
};

#pragma mark CommandObjectFrameRecognizer

#define LLDB_OPTIONS_frame_recognizer_add
#include "CommandOptions.inc"

class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f': {
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, true, &success);
        if (success) {
          m_first_instruction_only = value;
        } else {
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value '%s' passed for -f option",
              option_arg.str().c_str());
        }
      } break;
      case 'l':
        m_class_name = std::string(option_arg);
        break;
      case 's':
        m_module = std::string(option_arg);
        break;
      case 'n':
        m_symbols.push_back(std::string(option_arg));
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_module = "";
      m_symbols.clear();
      m_class_name = "";
      m_regex = false;
      m_first_instruction_only = true;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_recognizer_add_options);
    }

    // Instance variables to hold the values for command options.
    std::string m_class_name;
    std::string m_module;
    std::vector<std::string> m_symbols;
    bool m_regex;
    bool m_first_instruction_only;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override;

public:
  CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer add",
                            "Add a new frame recognizer.", nullptr) {
    SetHelpLong(R"(
Frame recognizers allow for retrieving information about special frames based on
ABI, arguments or other special properties of that frame, even without source
code or debug info. Currently, one use case is to extract function arguments
that would otherwise be unaccesible, or augment existing arguments.

Adding a custom frame recognizer is possible by implementing a Python class
and using the 'frame recognizer add' command. The Python class should have a
'get_recognized_arguments' method and it will receive an argument of type
lldb.SBFrame representing the current frame that we are trying to recognize.
The method should return a (possibly empty) list of lldb.SBValue objects that
represent the recognized arguments.

An example of a recognizer that retrieves the file descriptor values from libc
functions 'read', 'write' and 'close' follows:

  class LibcFdRecognizer(object):
    def get_recognized_arguments(self, frame):
      if frame.name in ["read", "write", "close"]:
        fd = frame.EvaluateExpression("$arg1").unsigned
        target = frame.thread.process.target
        value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
        return [value]
      return []

The file containing this implementation can be imported via 'command script
import' and then we can register this recognizer with 'frame recognizer add'.
It's important to restrict the recognizer to the libc library (which is
libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
in other modules:

(lldb) command script import .../fd_recognizer.py
(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib

When the program is stopped at the beginning of the 'read' function in libc, we
can view the recognizer arguments in 'frame variable':

(lldb) b read
(lldb) r
Process 1234 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
    frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
(lldb) frame variable
(int) fd = 3

    )");
  }
  ~CommandObjectFrameRecognizerAdd() override = default;
};

void CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
                                                CommandReturnObject &result) {
#if LLDB_ENABLE_PYTHON
  if (m_options.m_class_name.empty()) {
    result.AppendErrorWithFormat(
        "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
    return;
  }

  if (m_options.m_module.empty()) {
    result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
                                 m_cmd_name.c_str());
    return;
  }

  if (m_options.m_symbols.empty()) {
    result.AppendErrorWithFormat(
        "%s needs at least one symbol name (-n argument).\n",
        m_cmd_name.c_str());
    return;
  }

  if (m_options.m_regex && m_options.m_symbols.size() > 1) {
    result.AppendErrorWithFormat(
        "%s needs only one symbol regular expression (-n argument).\n",
        m_cmd_name.c_str());
    return;
  }

  ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();

  if (interpreter &&
      !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
    result.AppendWarning("The provided class does not exist - please define it "
                         "before attempting to use this frame recognizer");
  }

  StackFrameRecognizerSP recognizer_sp =
      StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
          interpreter, m_options.m_class_name.c_str()));
  if (m_options.m_regex) {
    auto module =
        RegularExpressionSP(new RegularExpression(m_options.m_module));
    auto func =
        RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
    GetTarget().GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  } else {
    auto module = ConstString(m_options.m_module);
    std::vector<ConstString> symbols(m_options.m_symbols.begin(),
                                     m_options.m_symbols.end());
    GetTarget().GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, symbols,
        Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  }
#endif

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer clear",
                            "Delete all frame recognizers.", nullptr) {}

  ~CommandObjectFrameRecognizerClear() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    GetTarget().GetFrameRecognizerManager().RemoveAllRecognizers();
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

static void
PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
                       const std::string &module,
                       llvm::ArrayRef<lldb_private::ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
  if (!enabled)
    strm << "[disabled] ";

  strm << name << ", ";

  if (!module.empty())
    strm << "module " << module << ", ";

  switch (symbol_mangling) {
  case Mangled::NamePreference ::ePreferMangled:
    strm << "mangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangled:
    strm << "demangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
    strm << "demangled (no args) symbol ";
    break;
  }

  if (regexp)
    strm << "regex ";

  llvm::interleaveComma(symbols, strm);
}

// Base class for commands which accept a single frame recognizer as an argument
class CommandObjectWithFrameRecognizerArg : public CommandObjectParsed {
public:
  CommandObjectWithFrameRecognizerArg(CommandInterpreter &interpreter,
                                      const char *name,
                                      const char *help = nullptr,
                                      const char *syntax = nullptr,
                                      uint32_t flags = 0)
      : CommandObjectParsed(interpreter, name, help, syntax, flags) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex() != 0)
      return;

    GetTarget().GetFrameRecognizerManager().ForEach(
        [&request](uint32_t rid, bool enabled, std::string rname,
                   std::string module,
                   llvm::ArrayRef<lldb_private::ConstString> symbols,
                   Mangled::NamePreference symbol_mangling, bool regexp) {
          StreamString strm;
          if (rname.empty())
            rname = "(internal)";

          PrintRecognizerDetails(strm, rname, enabled, module, symbols,
                                 symbol_mangling, regexp);

          request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
        });
  }

  virtual void DoExecuteWithId(CommandReturnObject &result,
                               uint32_t recognizer_id) = 0;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    uint32_t recognizer_id;
    if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
      result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
                                   command.GetArgumentAtIndex(0));
      return;
    }

    DoExecuteWithId(result, recognizer_id);
  }
};

class CommandObjectFrameRecognizerEnable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerEnable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer enable",
            "Enable a frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerEnable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDisable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDisable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer disable",
            "Disable a frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDisable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDelete
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer delete",
            "Delete an existing frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDelete() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerList : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer list",
                            "Show a list of active frame recognizers.",
                            nullptr) {}

  ~CommandObjectFrameRecognizerList() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    bool any_printed = false;
    GetTarget().GetFrameRecognizerManager().ForEach(
        [&result,
         &any_printed](uint32_t recognizer_id, bool enabled, std::string name,
                       std::string module, llvm::ArrayRef<ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
          Stream &stream = result.GetOutputStream();

          if (name.empty())
            name = "(internal)";

          stream << std::to_string(recognizer_id) << ": ";
          PrintRecognizerDetails(stream, name, enabled, module, symbols,
                                 symbol_mangling, regexp);

          stream.EOL();
          stream.Flush();

          any_printed = true;
        });

    if (any_printed)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.GetOutputStream().PutCString("no matching results found.\n");
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
  }
};

class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame recognizer info",
            "Show which frame recognizer is applied a stack frame (if any).",
            nullptr) {
    AddSimpleArgumentList(eArgTypeFrameIndex);
  }

  ~CommandObjectFrameRecognizerInfo() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    const char *frame_index_str = command.GetArgumentAtIndex(0);
    uint32_t frame_index;
    if (!llvm::to_integer(frame_index_str, frame_index)) {
      result.AppendErrorWithFormat("'%s' is not a valid frame index.",
                                   frame_index_str);
      return;
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process");
      return;
    }
    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (thread == nullptr) {
      result.AppendError("no thread");
      return;
    }
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
      return;
    }

    StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
    if (!frame_sp) {
      result.AppendErrorWithFormat("no frame with index %u", frame_index);
      return;
    }

    auto recognizer =
        GetTarget().GetFrameRecognizerManager().GetRecognizerForFrame(frame_sp);

    Stream &output_stream = result.GetOutputStream();
    output_stream.Printf("frame %d ", frame_index);
    if (recognizer) {
      output_stream << "is recognized by ";
      output_stream << recognizer->GetName();
    } else {
      output_stream << "not recognized by any recognizer";
    }
    output_stream.EOL();
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizer : public CommandObjectMultiword {
public:
  CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "frame recognizer",
            "Commands for editing and viewing frame recognizers.",
            "frame recognizer [<sub-command-options>] ") {
    LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
                               interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
                               interpreter)));
    LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
                              interpreter)));
    LoadSubCommand(
        "enable",
        CommandObjectSP(new CommandObjectFrameRecognizerEnable(interpreter)));
    LoadSubCommand(
        "disable",
        CommandObjectSP(new CommandObjectFrameRecognizerDisable(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
    LoadSubCommand(
        "clear",
        CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
  }

  ~CommandObjectFrameRecognizer() override = default;
};

#pragma mark CommandObjectMultiwordFrame

// CommandObjectMultiwordFrame

CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "frame",
                             "Commands for selecting and "
                             "examining the current "
                             "thread's stack frames.",
                             "frame <subcommand> [<subcommand-options>]") {
  LoadSubCommand("diagnose",
                 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
  LoadSubCommand("info",
                 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
  LoadSubCommand("variable",
                 CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
#if LLDB_ENABLE_PYTHON
  LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
                                   interpreter)));
#endif
}

CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
