//===-- BreakpointOptions.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/Breakpoint/BreakpointOptions.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Value.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"

#include "llvm/ADT/STLExtras.h"

using namespace lldb;
using namespace lldb_private;

const char
    *BreakpointOptions::CommandData::g_option_names[static_cast<uint32_t>(
        BreakpointOptions::CommandData::OptionNames::LastOptionName)]{
        "UserSource", "ScriptSource", "StopOnError"};

StructuredData::ObjectSP
BreakpointOptions::CommandData::SerializeToStructuredData() {
  size_t num_strings = user_source.GetSize();
  if (num_strings == 0 && script_source.empty()) {
    // We shouldn't serialize commands if there aren't any, return an empty sp
    // to indicate this.
    return StructuredData::ObjectSP();
  }

  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());
  options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
                                  stop_on_error);

  StructuredData::ArraySP user_source_sp(new StructuredData::Array());
  for (size_t i = 0; i < num_strings; i++) {
    StructuredData::StringSP item_sp(
        new StructuredData::String(user_source[i]));
    user_source_sp->AddItem(item_sp);
    options_dict_sp->AddItem(GetKey(OptionNames::UserSource), user_source_sp);
  }

  options_dict_sp->AddStringItem(
      GetKey(OptionNames::Interpreter),
      ScriptInterpreter::LanguageToString(interpreter));
  return options_dict_sp;
}

std::unique_ptr<BreakpointOptions::CommandData>
BreakpointOptions::CommandData::CreateFromStructuredData(
    const StructuredData::Dictionary &options_dict, Status &error) {
  std::unique_ptr<CommandData> data_up(new CommandData());
  bool found_something = false;

  bool success = options_dict.GetValueForKeyAsBoolean(
      GetKey(OptionNames::StopOnError), data_up->stop_on_error);

  if (success)
    found_something = true;

  llvm::StringRef interpreter_str;
  ScriptLanguage interp_language;
  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::Interpreter), interpreter_str);

  if (!success) {
    error.SetErrorString("Missing command language value.");
    return data_up;
  }

  found_something = true;
  interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
  if (interp_language == eScriptLanguageUnknown) {
    error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
                                    interpreter_str);
    return data_up;
  }
  data_up->interpreter = interp_language;

  StructuredData::Array *user_source;
  success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
                                               user_source);
  if (success) {
    found_something = true;
    size_t num_elems = user_source->GetSize();
    for (size_t i = 0; i < num_elems; i++) {
      llvm::StringRef elem_string;
      success = user_source->GetItemAtIndexAsString(i, elem_string);
      if (success)
        data_up->user_source.AppendString(elem_string);
    }
  }

  if (found_something)
    return data_up;
  else
    return std::unique_ptr<BreakpointOptions::CommandData>();
}

const char *BreakpointOptions::g_option_names[(
    size_t)BreakpointOptions::OptionNames::LastOptionName]{
    "ConditionText", "IgnoreCount", 
    "EnabledState", "OneShotState", "AutoContinue"};

bool BreakpointOptions::NullCallback(void *baton,
                                     StoppointCallbackContext *context,
                                     lldb::user_id_t break_id,
                                     lldb::user_id_t break_loc_id) {
  return true;
}

// BreakpointOptions constructor
BreakpointOptions::BreakpointOptions(bool all_flags_set)
    : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
      m_baton_is_command_baton(false), m_callback_is_synchronous(false),
      m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_up(),
      m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
      m_set_flags(0) {
  if (all_flags_set)
    m_set_flags.Set(~((Flags::ValueType)0));
}

BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
                                     int32_t ignore, bool one_shot, 
                                     bool auto_continue)
    : m_callback(nullptr), m_baton_is_command_baton(false),
      m_callback_is_synchronous(false), m_enabled(enabled),
      m_one_shot(one_shot), m_ignore_count(ignore),
      m_condition_text_hash(0), m_auto_continue(auto_continue)
{
    m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot 
                   | eAutoContinue);
    if (condition && *condition != '\0') {
      SetCondition(condition);
    }
}

// BreakpointOptions copy constructor
BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
    : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
      m_baton_is_command_baton(rhs.m_baton_is_command_baton),
      m_callback_is_synchronous(rhs.m_callback_is_synchronous),
      m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
      m_ignore_count(rhs.m_ignore_count), m_thread_spec_up(),
      m_auto_continue(rhs.m_auto_continue), m_set_flags(rhs.m_set_flags) {
  if (rhs.m_thread_spec_up != nullptr)
    m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
  m_condition_text = rhs.m_condition_text;
  m_condition_text_hash = rhs.m_condition_text_hash;
}

// BreakpointOptions assignment operator
const BreakpointOptions &BreakpointOptions::
operator=(const BreakpointOptions &rhs) {
  m_callback = rhs.m_callback;
  m_callback_baton_sp = rhs.m_callback_baton_sp;
  m_baton_is_command_baton = rhs.m_baton_is_command_baton;
  m_callback_is_synchronous = rhs.m_callback_is_synchronous;
  m_enabled = rhs.m_enabled;
  m_one_shot = rhs.m_one_shot;
  m_ignore_count = rhs.m_ignore_count;
  if (rhs.m_thread_spec_up != nullptr)
    m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
  m_condition_text = rhs.m_condition_text;
  m_condition_text_hash = rhs.m_condition_text_hash;
  m_auto_continue = rhs.m_auto_continue;
  m_set_flags = rhs.m_set_flags;
  return *this;
}

void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
{
  if (incoming.m_set_flags.Test(eEnabled))
  {
    m_enabled = incoming.m_enabled;
    m_set_flags.Set(eEnabled);
  }
  if (incoming.m_set_flags.Test(eOneShot))
  {
    m_one_shot = incoming.m_one_shot;
    m_set_flags.Set(eOneShot);
  }
  if (incoming.m_set_flags.Test(eCallback))
  {
    m_callback = incoming.m_callback;
    m_callback_baton_sp = incoming.m_callback_baton_sp;
    m_callback_is_synchronous = incoming.m_callback_is_synchronous;
    m_baton_is_command_baton = incoming.m_baton_is_command_baton;
    m_set_flags.Set(eCallback);
  }
  if (incoming.m_set_flags.Test(eIgnoreCount))
  {
    m_ignore_count = incoming.m_ignore_count;
    m_set_flags.Set(eIgnoreCount);
  }
  if (incoming.m_set_flags.Test(eCondition))
  {
    // If we're copying over an empty condition, mark it as unset.
    if (incoming.m_condition_text.empty()) {
      m_condition_text.clear();
      m_condition_text_hash = 0;
      m_set_flags.Clear(eCondition);
    } else {
      m_condition_text = incoming.m_condition_text;
      m_condition_text_hash = incoming.m_condition_text_hash;
      m_set_flags.Set(eCondition);
    }
  }
  if (incoming.m_set_flags.Test(eAutoContinue))
  {
    m_auto_continue = incoming.m_auto_continue;
    m_set_flags.Set(eAutoContinue);
  }
  if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_up) {
    if (!m_thread_spec_up)
      m_thread_spec_up =
          std::make_unique<ThreadSpec>(*incoming.m_thread_spec_up);
    else
      *m_thread_spec_up = *incoming.m_thread_spec_up;
    m_set_flags.Set(eThreadSpec);
  }
}

// Destructor
BreakpointOptions::~BreakpointOptions() = default;

std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &options_dict,
    Status &error) {
  bool enabled = true;
  bool one_shot = false;
  bool auto_continue = false;
  int32_t ignore_count = 0;
  llvm::StringRef condition_ref("");
  Flags set_options;

  const char *key = GetKey(OptionNames::EnabledState);
  bool success;
  if (key && options_dict.HasKey(key)) {
    success = options_dict.GetValueForKeyAsBoolean(key, enabled);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.", key);
      return nullptr;
    }
    set_options.Set(eEnabled);
  }

  key = GetKey(OptionNames::OneShotState);
  if (key && options_dict.HasKey(key)) {
    success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.", key);
      return nullptr;
      }
      set_options.Set(eOneShot);
  }
  
  key = GetKey(OptionNames::AutoContinue);
  if (key && options_dict.HasKey(key)) {
    success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.", key);
      return nullptr;
      }
      set_options.Set(eAutoContinue);
  }
  
  key = GetKey(OptionNames::IgnoreCount);
  if (key && options_dict.HasKey(key)) {
    success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not an integer.", key);
      return nullptr;
    }
    set_options.Set(eIgnoreCount);
  }

  key = GetKey(OptionNames::ConditionText);
  if (key && options_dict.HasKey(key)) {
    success = options_dict.GetValueForKeyAsString(key, condition_ref);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not an string.", key);
      return nullptr;
    }
    set_options.Set(eCondition);
  }

  std::unique_ptr<CommandData> cmd_data_up;
  StructuredData::Dictionary *cmds_dict;
  success = options_dict.GetValueForKeyAsDictionary(
      CommandData::GetSerializationKey(), cmds_dict);
  if (success && cmds_dict) {
    Status cmds_error;
    cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
    if (cmds_error.Fail()) {
      error.SetErrorStringWithFormat(
          "Failed to deserialize breakpoint command options: %s.",
          cmds_error.AsCString());
      return nullptr;
    }
  }

  auto bp_options = std::make_unique<BreakpointOptions>(
      condition_ref.str().c_str(), enabled, 
      ignore_count, one_shot, auto_continue);
  if (cmd_data_up) {
    if (cmd_data_up->interpreter == eScriptLanguageNone)
      bp_options->SetCommandDataCallback(cmd_data_up);
    else {
      ScriptInterpreter *interp = target.GetDebugger().GetScriptInterpreter();
      if (!interp) {
        error.SetErrorString(
            "Can't set script commands - no script interpreter");
        return nullptr;
      }
      if (interp->GetLanguage() != cmd_data_up->interpreter) {
        error.SetErrorStringWithFormat(
            "Current script language doesn't match breakpoint's language: %s",
            ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
                .c_str());
        return nullptr;
      }
      Status script_error;
      script_error =
          interp->SetBreakpointCommandCallback(bp_options.get(), cmd_data_up);
      if (script_error.Fail()) {
        error.SetErrorStringWithFormat("Error generating script callback: %s.",
                                       error.AsCString());
        return nullptr;
      }
    }
  }

  StructuredData::Dictionary *thread_spec_dict;
  success = options_dict.GetValueForKeyAsDictionary(
      ThreadSpec::GetSerializationKey(), thread_spec_dict);
  if (success) {
    Status thread_spec_error;
    std::unique_ptr<ThreadSpec> thread_spec_up =
        ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
                                             thread_spec_error);
    if (thread_spec_error.Fail()) {
      error.SetErrorStringWithFormat(
          "Failed to deserialize breakpoint thread spec options: %s.",
          thread_spec_error.AsCString());
      return nullptr;
    }
    bp_options->SetThreadSpec(thread_spec_up);
  }
  return bp_options;
}

StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());
  if (m_set_flags.Test(eEnabled))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
                                    m_enabled);
  if (m_set_flags.Test(eOneShot))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
                               m_one_shot);
  if (m_set_flags.Test(eAutoContinue))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
                               m_auto_continue);
  if (m_set_flags.Test(eIgnoreCount))
    options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
                                    m_ignore_count);
  if (m_set_flags.Test(eCondition))
    options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
                                   m_condition_text);
         
  if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
    auto cmd_baton =
        std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
    StructuredData::ObjectSP commands_sp =
        cmd_baton->getItem()->SerializeToStructuredData();
    if (commands_sp) {
      options_dict_sp->AddItem(
          BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
    }
  }
  if (m_set_flags.Test(eThreadSpec) && m_thread_spec_up) {
    StructuredData::ObjectSP thread_spec_sp =
        m_thread_spec_up->SerializeToStructuredData();
    options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
  }

  return options_dict_sp;
}

// Callbacks
void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
                                    const lldb::BatonSP &callback_baton_sp,
                                    bool callback_is_synchronous) {
  // FIXME: This seems unsafe.  If BatonSP actually *is* a CommandBaton, but
  // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
  // set m_baton_is_command_baton to false, which is incorrect. One possible
  // solution is to make the base Baton class provide a method such as:
  //     virtual StringRef getBatonId() const { return ""; }
  // and have CommandBaton override this to return something unique, and then
  // check for it here.  Another option might be to make Baton using the llvm
  // casting infrastructure, so that we could write something like:
  //     if (llvm::isa<CommandBaton>(callback_baton_sp))
  // at relevant callsites instead of storing a boolean.
  m_callback_is_synchronous = callback_is_synchronous;
  m_callback = callback;
  m_callback_baton_sp = callback_baton_sp;
  m_baton_is_command_baton = false;
  m_set_flags.Set(eCallback);
}

void BreakpointOptions::SetCallback(
    BreakpointHitCallback callback,
    const BreakpointOptions::CommandBatonSP &callback_baton_sp,
    bool callback_is_synchronous) {
  m_callback_is_synchronous = callback_is_synchronous;
  m_callback = callback;
  m_callback_baton_sp = callback_baton_sp;
  m_baton_is_command_baton = true;
  m_set_flags.Set(eCallback);
}

void BreakpointOptions::ClearCallback() {
  m_callback = BreakpointOptions::NullCallback;
  m_callback_is_synchronous = false;
  m_callback_baton_sp.reset();
  m_baton_is_command_baton = false;
  m_set_flags.Clear(eCallback);
}

Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }

const Baton *BreakpointOptions::GetBaton() const {
  return m_callback_baton_sp.get();
}

bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
                                       lldb::user_id_t break_id,
                                       lldb::user_id_t break_loc_id) {
  if (m_callback) {
    if (context->is_synchronous == IsCallbackSynchronous()) {
        return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
                                          : nullptr,
                      context, break_id, break_loc_id);
    } else if (IsCallbackSynchronous()) {
      // If a synchronous callback is called at async time, it should not say
      // to stop.
      return false;
    }
  }
  return true;
}

bool BreakpointOptions::HasCallback() const {
  return m_callback != BreakpointOptions::NullCallback;
}

bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
  if (!HasCallback())
    return false;
  if (!m_baton_is_command_baton)
    return false;

  auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
  CommandData *data = cmd_baton->getItem();
  if (!data)
    return false;
  command_list = data->user_source;
  return true;
}

void BreakpointOptions::SetCondition(const char *condition) {
  if (!condition || condition[0] == '\0') {
    condition = "";
    m_set_flags.Clear(eCondition);
  }
  else
    m_set_flags.Set(eCondition);

  m_condition_text.assign(condition);
  std::hash<std::string> hasher;
  m_condition_text_hash = hasher(m_condition_text);
}

const char *BreakpointOptions::GetConditionText(size_t *hash) const {
  if (!m_condition_text.empty()) {
    if (hash)
      *hash = m_condition_text_hash;

    return m_condition_text.c_str();
  } else {
    return nullptr;
  }
}

const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
  return m_thread_spec_up.get();
}

ThreadSpec *BreakpointOptions::GetThreadSpec() {
  if (m_thread_spec_up == nullptr) {
    m_set_flags.Set(eThreadSpec);
    m_thread_spec_up = std::make_unique<ThreadSpec>();
  }

  return m_thread_spec_up.get();
}

void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
  GetThreadSpec()->SetTID(thread_id);
  m_set_flags.Set(eThreadSpec);
}

void BreakpointOptions::SetThreadSpec(
    std::unique_ptr<ThreadSpec> &thread_spec_up) {
  m_thread_spec_up = std::move(thread_spec_up);
  m_set_flags.Set(eThreadSpec);
}

void BreakpointOptions::GetDescription(Stream *s,
                                       lldb::DescriptionLevel level) const {
  // Figure out if there are any options not at their default value, and only
  // print anything if there are:

  if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
      (GetThreadSpecNoCreate() != nullptr &&
       GetThreadSpecNoCreate()->HasSpecification())) {
    if (level == lldb::eDescriptionLevelVerbose) {
      s->EOL();
      s->IndentMore();
      s->Indent();
      s->PutCString("Breakpoint Options:\n");
      s->IndentMore();
      s->Indent();
    } else
      s->PutCString(" Options: ");

    if (m_ignore_count > 0)
      s->Printf("ignore: %d ", m_ignore_count);
    s->Printf("%sabled ", m_enabled ? "en" : "dis");

    if (m_one_shot)
      s->Printf("one-shot ");

    if (m_auto_continue)
      s->Printf("auto-continue ");

    if (m_thread_spec_up)
      m_thread_spec_up->GetDescription(s, level);

    if (level == lldb::eDescriptionLevelFull) {
      s->IndentLess();
      s->IndentMore();
    }
  }

  if (m_callback_baton_sp.get()) {
    if (level != eDescriptionLevelBrief) {
      s->EOL();
      m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
                                          s->GetIndentLevel());
    }
  }
  if (!m_condition_text.empty()) {
    if (level != eDescriptionLevelBrief) {
      s->EOL();
      s->Printf("Condition: %s\n", m_condition_text.c_str());
    }
  }
}

void BreakpointOptions::CommandBaton::GetDescription(
    llvm::raw_ostream &s, lldb::DescriptionLevel level,
    unsigned indentation) const {
  const CommandData *data = getItem();

  if (level == eDescriptionLevelBrief) {
    s << ", commands = "
      << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
    return;
  }

  indentation += 2;
  s.indent(indentation);
  s << "Breakpoint commands";
  if (data->interpreter != eScriptLanguageNone)
    s << llvm::formatv(" ({0}):\n",
                       ScriptInterpreter::LanguageToString(data->interpreter));
  else
    s << ":\n";

  indentation += 2;
  if (data && data->user_source.GetSize() > 0) {
    for (llvm::StringRef str : data->user_source) {
      s.indent(indentation);
      s << str << "\n";
    }
  } else
    s << "No commands.\n";
}

void BreakpointOptions::SetCommandDataCallback(
    std::unique_ptr<CommandData> &cmd_data) {
  cmd_data->interpreter = eScriptLanguageNone;
  auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
  SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
  m_set_flags.Set(eCallback);
}

bool BreakpointOptions::BreakpointOptionsCallbackFunction(
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
    lldb::user_id_t break_loc_id) {
  bool ret_value = true;
  if (baton == nullptr)
    return true;

  CommandData *data = (CommandData *)baton;
  StringList &commands = data->user_source;

  if (commands.GetSize() > 0) {
    ExecutionContext exe_ctx(context->exe_ctx_ref);
    Target *target = exe_ctx.GetTargetPtr();
    if (target) {
      Debugger &debugger = target->GetDebugger();
      CommandReturnObject result(debugger.GetUseColor());

      // Rig up the results secondary output stream to the debugger's, so the
      // output will come out synchronously if the debugger is set up that way.
      StreamSP output_stream(debugger.GetAsyncOutputStream());
      StreamSP error_stream(debugger.GetAsyncErrorStream());
      result.SetImmediateOutputStream(output_stream);
      result.SetImmediateErrorStream(error_stream);

      CommandInterpreterRunOptions options;
      options.SetStopOnContinue(true);
      options.SetStopOnError(data->stop_on_error);
      options.SetEchoCommands(true);
      options.SetPrintResults(true);
      options.SetPrintErrors(true);
      options.SetAddToHistory(false);

      debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx,
                                                      options, result);
      result.GetImmediateOutputStream()->Flush();
      result.GetImmediateErrorStream()->Flush();
    }
  }
  return ret_value;
}

void BreakpointOptions::Clear()
{
  m_set_flags.Clear();
  m_thread_spec_up.release();
  m_one_shot = false;
  m_ignore_count = 0;
  m_auto_continue = false;
  m_callback = nullptr;
  m_callback_baton_sp.reset();
  m_baton_is_command_baton = false;
  m_callback_is_synchronous = false;
  m_enabled = false;
  m_condition_text.clear();
}
