//===-- SBDebugger.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/API/SBDebugger.h"
#include "SystemInitializerFull.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/LLDBLog.h"

#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandInterpreterRunOptions.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFile.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTypeCategory.h"
#include "lldb/API/SBTypeFilter.h"
#include "lldb/API/SBTypeFormat.h"
#include "lldb/API/SBTypeNameSpecifier.h"
#include "lldb/API/SBTypeSummary.h"
#include "lldb/API/SBTypeSynthetic.h"

#include "lldb/Core/Debugger.h"
#include "lldb/Core/DebuggerEvents.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Host/XML.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Diagnostics.h"
#include "lldb/Utility/State.h"
#include "lldb/Version/Version.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"

using namespace lldb;
using namespace lldb_private;

static llvm::ManagedStatic<SystemLifetimeManager> g_debugger_lifetime;

SBError SBInputReader::Initialize(
    lldb::SBDebugger &sb_debugger,
    unsigned long (*callback)(void *, lldb::SBInputReader *,
                              lldb::InputReaderAction, char const *,
                              unsigned long),
    void *a, lldb::InputReaderGranularity b, char const *c, char const *d,
    bool e) {
  LLDB_INSTRUMENT_VA(this, sb_debugger, callback, a, b, c, d, e);

  return SBError();
}

void SBInputReader::SetIsDone(bool b) { LLDB_INSTRUMENT_VA(this, b); }

bool SBInputReader::IsActive() const {
  LLDB_INSTRUMENT_VA(this);

  return false;
}

SBDebugger::SBDebugger() { LLDB_INSTRUMENT_VA(this); }

SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp)
    : m_opaque_sp(debugger_sp) {
  LLDB_INSTRUMENT_VA(this, debugger_sp);
}

SBDebugger::SBDebugger(const SBDebugger &rhs) : m_opaque_sp(rhs.m_opaque_sp) {
  LLDB_INSTRUMENT_VA(this, rhs);
}

SBDebugger::~SBDebugger() = default;

SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  if (this != &rhs) {
    m_opaque_sp = rhs.m_opaque_sp;
  }
  return *this;
}

const char *SBDebugger::GetBroadcasterClass() {
  LLDB_INSTRUMENT();

  return ConstString(Debugger::GetStaticBroadcasterClass()).AsCString();
}

const char *SBDebugger::GetProgressFromEvent(const lldb::SBEvent &event,
                                             uint64_t &progress_id,
                                             uint64_t &completed,
                                             uint64_t &total,
                                             bool &is_debugger_specific) {
  LLDB_INSTRUMENT_VA(event);

  const ProgressEventData *progress_data =
      ProgressEventData::GetEventDataFromEvent(event.get());
  if (progress_data == nullptr)
    return nullptr;
  progress_id = progress_data->GetID();
  completed = progress_data->GetCompleted();
  total = progress_data->GetTotal();
  is_debugger_specific = progress_data->IsDebuggerSpecific();
  ConstString message(progress_data->GetMessage());
  return message.AsCString();
}

lldb::SBStructuredData
SBDebugger::GetProgressDataFromEvent(const lldb::SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  StructuredData::DictionarySP dictionary_sp =
      ProgressEventData::GetAsStructuredData(event.get());

  if (!dictionary_sp)
    return {};

  SBStructuredData data;
  data.m_impl_up->SetObjectSP(std::move(dictionary_sp));
  return data;
}

lldb::SBStructuredData
SBDebugger::GetDiagnosticFromEvent(const lldb::SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  StructuredData::DictionarySP dictionary_sp =
      DiagnosticEventData::GetAsStructuredData(event.get());

  if (!dictionary_sp)
    return {};

  SBStructuredData data;
  data.m_impl_up->SetObjectSP(std::move(dictionary_sp));
  return data;
}

SBBroadcaster SBDebugger::GetBroadcaster() {
  LLDB_INSTRUMENT_VA(this);
  SBBroadcaster broadcaster(&m_opaque_sp->GetBroadcaster(), false);
  return broadcaster;
}

void SBDebugger::Initialize() {
  LLDB_INSTRUMENT();
  SBError ignored = SBDebugger::InitializeWithErrorHandling();
}

lldb::SBError SBDebugger::InitializeWithErrorHandling() {
  LLDB_INSTRUMENT();

  auto LoadPlugin = [](const lldb::DebuggerSP &debugger_sp,
                       const FileSpec &spec,
                       Status &error) -> llvm::sys::DynamicLibrary {
    llvm::sys::DynamicLibrary dynlib =
        llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str());
    if (dynlib.isValid()) {
      typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger & debugger);

      lldb::SBDebugger debugger_sb(debugger_sp);
      // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger)
      // function.
      // TODO: mangle this differently for your system - on OSX, the first
      // underscore needs to be removed and the second one stays
      LLDBCommandPluginInit init_func =
          (LLDBCommandPluginInit)(uintptr_t)dynlib.getAddressOfSymbol(
              "_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
      if (init_func) {
        if (init_func(debugger_sb))
          return dynlib;
        else
          error.SetErrorString("plug-in refused to load "
                               "(lldb::PluginInitialize(lldb::SBDebugger) "
                               "returned false)");
      } else {
        error.SetErrorString("plug-in is missing the required initialization: "
                             "lldb::PluginInitialize(lldb::SBDebugger)");
      }
    } else {
      if (FileSystem::Instance().Exists(spec))
        error.SetErrorString("this file does not represent a loadable dylib");
      else
        error.SetErrorString("no such file");
    }
    return llvm::sys::DynamicLibrary();
  };

  SBError error;
  if (auto e = g_debugger_lifetime->Initialize(
          std::make_unique<SystemInitializerFull>(), LoadPlugin)) {
    error.SetError(Status(std::move(e)));
  }
  return error;
}

void SBDebugger::PrintStackTraceOnError() {
  LLDB_INSTRUMENT();

  llvm::EnablePrettyStackTrace();
  static std::string executable =
      llvm::sys::fs::getMainExecutable(nullptr, nullptr);
  llvm::sys::PrintStackTraceOnErrorSignal(executable);
}

static void DumpDiagnostics(void *cookie) {
  Diagnostics::Instance().Dump(llvm::errs());
}

void SBDebugger::PrintDiagnosticsOnError() {
  LLDB_INSTRUMENT();

  llvm::sys::AddSignalHandler(&DumpDiagnostics, nullptr);
}

void SBDebugger::Terminate() {
  LLDB_INSTRUMENT();

  g_debugger_lifetime->Terminate();
}

void SBDebugger::Clear() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp)
    m_opaque_sp->ClearIOHandlers();

  m_opaque_sp.reset();
}

SBDebugger SBDebugger::Create() {
  LLDB_INSTRUMENT();

  return SBDebugger::Create(false, nullptr, nullptr);
}

SBDebugger SBDebugger::Create(bool source_init_files) {
  LLDB_INSTRUMENT_VA(source_init_files);

  return SBDebugger::Create(source_init_files, nullptr, nullptr);
}

SBDebugger SBDebugger::Create(bool source_init_files,
                              lldb::LogOutputCallback callback, void *baton)

{
  LLDB_INSTRUMENT_VA(source_init_files, callback, baton);

  SBDebugger debugger;

  // Currently we have issues if this function is called simultaneously on two
  // different threads. The issues mainly revolve around the fact that the
  // lldb_private::FormatManager uses global collections and having two threads
  // parsing the .lldbinit files can cause mayhem. So to get around this for
  // now we need to use a mutex to prevent bad things from happening.
  static std::recursive_mutex g_mutex;
  std::lock_guard<std::recursive_mutex> guard(g_mutex);

  debugger.reset(Debugger::CreateInstance(callback, baton));

  SBCommandInterpreter interp = debugger.GetCommandInterpreter();
  if (source_init_files) {
    interp.get()->SkipLLDBInitFiles(false);
    interp.get()->SkipAppInitFiles(false);
    SBCommandReturnObject result;
    interp.SourceInitFileInGlobalDirectory(result);
    interp.SourceInitFileInHomeDirectory(result, false);
  } else {
    interp.get()->SkipLLDBInitFiles(true);
    interp.get()->SkipAppInitFiles(true);
  }
  return debugger;
}

void SBDebugger::Destroy(SBDebugger &debugger) {
  LLDB_INSTRUMENT_VA(debugger);

  Debugger::Destroy(debugger.m_opaque_sp);

  if (debugger.m_opaque_sp.get() != nullptr)
    debugger.m_opaque_sp.reset();
}

void SBDebugger::MemoryPressureDetected() {
  LLDB_INSTRUMENT();

  // Since this function can be call asynchronously, we allow it to be non-
  // mandatory. We have seen deadlocks with this function when called so we
  // need to safeguard against this until we can determine what is causing the
  // deadlocks.

  const bool mandatory = false;

  ModuleList::RemoveOrphanSharedModules(mandatory);
}

bool SBDebugger::IsValid() const {
  LLDB_INSTRUMENT_VA(this);
  return this->operator bool();
}
SBDebugger::operator bool() const {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_sp.get() != nullptr;
}

void SBDebugger::SetAsync(bool b) {
  LLDB_INSTRUMENT_VA(this, b);

  if (m_opaque_sp)
    m_opaque_sp->SetAsyncExecution(b);
}

bool SBDebugger::GetAsync() {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false);
}

void SBDebugger::SkipLLDBInitFiles(bool b) {
  LLDB_INSTRUMENT_VA(this, b);

  if (m_opaque_sp)
    m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles(b);
}

void SBDebugger::SkipAppInitFiles(bool b) {
  LLDB_INSTRUMENT_VA(this, b);

  if (m_opaque_sp)
    m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b);
}

void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
  LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
  if (m_opaque_sp)
    m_opaque_sp->SetInputFile(
        (FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}

SBError SBDebugger::SetInputString(const char *data) {
  LLDB_INSTRUMENT_VA(this, data);
  SBError sb_error;
  if (data == nullptr) {
    sb_error.SetErrorString("String data is null");
    return sb_error;
  }

  size_t size = strlen(data);
  if (size == 0) {
    sb_error.SetErrorString("String data is empty");
    return sb_error;
  }

  if (!m_opaque_sp) {
    sb_error.SetErrorString("invalid debugger");
    return sb_error;
  }

  sb_error.SetError(m_opaque_sp->SetInputString(data));
  return sb_error;
}

// Shouldn't really be settable after initialization as this could cause lots
// of problems; don't want users trying to switch modes in the middle of a
// debugging session.
SBError SBDebugger::SetInputFile(SBFile file) {
  LLDB_INSTRUMENT_VA(this, file);

  SBError error;
  if (!m_opaque_sp) {
    error.ref().SetErrorString("invalid debugger");
    return error;
  }
  if (!file) {
    error.ref().SetErrorString("invalid file");
    return error;
  }
  m_opaque_sp->SetInputFile(file.m_opaque_sp);
  return error;
}

SBError SBDebugger::SetInputFile(FileSP file_sp) {
  LLDB_INSTRUMENT_VA(this, file_sp);
  return SetInputFile(SBFile(file_sp));
}

SBError SBDebugger::SetOutputFile(FileSP file_sp) {
  LLDB_INSTRUMENT_VA(this, file_sp);
  return SetOutputFile(SBFile(file_sp));
}

void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
  LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
  SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}

SBError SBDebugger::SetOutputFile(SBFile file) {
  LLDB_INSTRUMENT_VA(this, file);
  SBError error;
  if (!m_opaque_sp) {
    error.ref().SetErrorString("invalid debugger");
    return error;
  }
  if (!file) {
    error.ref().SetErrorString("invalid file");
    return error;
  }
  m_opaque_sp->SetOutputFile(file.m_opaque_sp);
  return error;
}

void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
  LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);
  SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}

SBError SBDebugger::SetErrorFile(FileSP file_sp) {
  LLDB_INSTRUMENT_VA(this, file_sp);
  return SetErrorFile(SBFile(file_sp));
}

SBError SBDebugger::SetErrorFile(SBFile file) {
  LLDB_INSTRUMENT_VA(this, file);
  SBError error;
  if (!m_opaque_sp) {
    error.ref().SetErrorString("invalid debugger");
    return error;
  }
  if (!file) {
    error.ref().SetErrorString("invalid file");
    return error;
  }
  m_opaque_sp->SetErrorFile(file.m_opaque_sp);
  return error;
}

lldb::SBStructuredData SBDebugger::GetSetting(const char *setting) {
  LLDB_INSTRUMENT_VA(this, setting);

  SBStructuredData data;
  if (!m_opaque_sp)
    return data;

  StreamString json_strm;
  ExecutionContext exe_ctx(
      m_opaque_sp->GetCommandInterpreter().GetExecutionContext());
  if (setting && strlen(setting) > 0)
    m_opaque_sp->DumpPropertyValue(&exe_ctx, json_strm, setting,
                                   /*dump_mask*/ 0,
                                   /*is_json*/ true);
  else
    m_opaque_sp->DumpAllPropertyValues(&exe_ctx, json_strm, /*dump_mask*/ 0,
                                       /*is_json*/ true);

  data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_strm.GetString()));
  return data;
}

FILE *SBDebugger::GetInputFileHandle() {
  LLDB_INSTRUMENT_VA(this);
  if (m_opaque_sp) {
    File &file_sp = m_opaque_sp->GetInputFile();
    return file_sp.GetStream();
  }
  return nullptr;
}

SBFile SBDebugger::GetInputFile() {
  LLDB_INSTRUMENT_VA(this);
  if (m_opaque_sp) {
    return SBFile(m_opaque_sp->GetInputFileSP());
  }
  return SBFile();
}

FILE *SBDebugger::GetOutputFileHandle() {
  LLDB_INSTRUMENT_VA(this);
  if (m_opaque_sp) {
    StreamFile &stream_file = m_opaque_sp->GetOutputStream();
    return stream_file.GetFile().GetStream();
  }
  return nullptr;
}

SBFile SBDebugger::GetOutputFile() {
  LLDB_INSTRUMENT_VA(this);
  if (m_opaque_sp) {
    SBFile file(m_opaque_sp->GetOutputStream().GetFileSP());
    return file;
  }
  return SBFile();
}

FILE *SBDebugger::GetErrorFileHandle() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp) {
    StreamFile &stream_file = m_opaque_sp->GetErrorStream();
    return stream_file.GetFile().GetStream();
  }
  return nullptr;
}

SBFile SBDebugger::GetErrorFile() {
  LLDB_INSTRUMENT_VA(this);
  SBFile file;
  if (m_opaque_sp) {
    SBFile file(m_opaque_sp->GetErrorStream().GetFileSP());
    return file;
  }
  return SBFile();
}

void SBDebugger::SaveInputTerminalState() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp)
    m_opaque_sp->SaveInputTerminalState();
}

void SBDebugger::RestoreInputTerminalState() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp)
    m_opaque_sp->RestoreInputTerminalState();
}
SBCommandInterpreter SBDebugger::GetCommandInterpreter() {
  LLDB_INSTRUMENT_VA(this);

  SBCommandInterpreter sb_interpreter;
  if (m_opaque_sp)
    sb_interpreter.reset(&m_opaque_sp->GetCommandInterpreter());

  return sb_interpreter;
}

void SBDebugger::HandleCommand(const char *command) {
  LLDB_INSTRUMENT_VA(this, command);

  if (m_opaque_sp) {
    TargetSP target_sp(m_opaque_sp->GetSelectedTarget());
    std::unique_lock<std::recursive_mutex> lock;
    if (target_sp)
      lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());

    SBCommandInterpreter sb_interpreter(GetCommandInterpreter());
    SBCommandReturnObject result;

    sb_interpreter.HandleCommand(command, result, false);

    result.PutError(m_opaque_sp->GetErrorStream().GetFileSP());
    result.PutOutput(m_opaque_sp->GetOutputStream().GetFileSP());

    if (!m_opaque_sp->GetAsyncExecution()) {
      SBProcess process(GetCommandInterpreter().GetProcess());
      ProcessSP process_sp(process.GetSP());
      if (process_sp) {
        EventSP event_sp;
        ListenerSP lldb_listener_sp = m_opaque_sp->GetListener();
        while (lldb_listener_sp->GetEventForBroadcaster(
            process_sp.get(), event_sp, std::chrono::seconds(0))) {
          SBEvent event(event_sp);
          HandleProcessEvent(process, event, GetOutputFile(), GetErrorFile());
        }
      }
    }
  }
}

SBListener SBDebugger::GetListener() {
  LLDB_INSTRUMENT_VA(this);

  SBListener sb_listener;
  if (m_opaque_sp)
    sb_listener.reset(m_opaque_sp->GetListener());

  return sb_listener;
}

void SBDebugger::HandleProcessEvent(const SBProcess &process,
                                    const SBEvent &event, SBFile out,
                                    SBFile err) {
  LLDB_INSTRUMENT_VA(this, process, event, out, err);

  return HandleProcessEvent(process, event, out.m_opaque_sp, err.m_opaque_sp);
}

void SBDebugger::HandleProcessEvent(const SBProcess &process,
                                    const SBEvent &event, FILE *out,
                                    FILE *err) {
  LLDB_INSTRUMENT_VA(this, process, event, out, err);

  FileSP outfile = std::make_shared<NativeFile>(out, false);
  FileSP errfile = std::make_shared<NativeFile>(err, false);
  return HandleProcessEvent(process, event, outfile, errfile);
}

void SBDebugger::HandleProcessEvent(const SBProcess &process,
                                    const SBEvent &event, FileSP out_sp,
                                    FileSP err_sp) {

  LLDB_INSTRUMENT_VA(this, process, event, out_sp, err_sp);

  if (!process.IsValid())
    return;

  TargetSP target_sp(process.GetTarget().GetSP());
  if (!target_sp)
    return;

  const uint32_t event_type = event.GetType();
  char stdio_buffer[1024];
  size_t len;

  std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());

  if (event_type &
      (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged)) {
    // Drain stdout when we stop just in case we have any bytes
    while ((len = process.GetSTDOUT(stdio_buffer, sizeof(stdio_buffer))) > 0)
      if (out_sp)
        out_sp->Write(stdio_buffer, len);
  }

  if (event_type &
      (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged)) {
    // Drain stderr when we stop just in case we have any bytes
    while ((len = process.GetSTDERR(stdio_buffer, sizeof(stdio_buffer))) > 0)
      if (err_sp)
        err_sp->Write(stdio_buffer, len);
  }

  if (event_type & Process::eBroadcastBitStateChanged) {
    StateType event_state = SBProcess::GetStateFromEvent(event);

    if (event_state == eStateInvalid)
      return;

    bool is_stopped = StateIsStoppedState(event_state);
    if (!is_stopped)
      process.ReportEventState(event, out_sp);
  }
}

SBSourceManager SBDebugger::GetSourceManager() {
  LLDB_INSTRUMENT_VA(this);

  SBSourceManager sb_source_manager(*this);
  return sb_source_manager;
}

bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) {
  LLDB_INSTRUMENT_VA(arch_name, arch_name_len);

  if (arch_name && arch_name_len) {
    ArchSpec default_arch = Target::GetDefaultArchitecture();

    if (default_arch.IsValid()) {
      const std::string &triple_str = default_arch.GetTriple().str();
      if (!triple_str.empty())
        ::snprintf(arch_name, arch_name_len, "%s", triple_str.c_str());
      else
        ::snprintf(arch_name, arch_name_len, "%s",
                   default_arch.GetArchitectureName());
      return true;
    }
  }
  if (arch_name && arch_name_len)
    arch_name[0] = '\0';
  return false;
}

bool SBDebugger::SetDefaultArchitecture(const char *arch_name) {
  LLDB_INSTRUMENT_VA(arch_name);

  if (arch_name) {
    ArchSpec arch(arch_name);
    if (arch.IsValid()) {
      Target::SetDefaultArchitecture(arch);
      return true;
    }
  }
  return false;
}

ScriptLanguage
SBDebugger::GetScriptingLanguage(const char *script_language_name) {
  LLDB_INSTRUMENT_VA(this, script_language_name);

  if (!script_language_name)
    return eScriptLanguageDefault;
  return OptionArgParser::ToScriptLanguage(
      llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr);
}

SBStructuredData
SBDebugger::GetScriptInterpreterInfo(lldb::ScriptLanguage language) {
  LLDB_INSTRUMENT_VA(this, language);
  SBStructuredData data;
  if (m_opaque_sp) {
    lldb_private::ScriptInterpreter *interp =
        m_opaque_sp->GetScriptInterpreter(language);
    if (interp) {
      data.m_impl_up->SetObjectSP(interp->GetInterpreterInfo());
    }
  }
  return data;
}

const char *SBDebugger::GetVersionString() {
  LLDB_INSTRUMENT();

  return lldb_private::GetVersion();
}

const char *SBDebugger::StateAsCString(StateType state) {
  LLDB_INSTRUMENT_VA(state);

  return lldb_private::StateAsCString(state);
}

static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
                               llvm::StringRef name, bool value,
                               llvm::StringRef description) {
  auto entry_up = std::make_unique<StructuredData::Dictionary>();
  entry_up->AddBooleanItem("value", value);
  entry_up->AddStringItem("description", description);
  dict.AddItem(name, std::move(entry_up));
}

static void AddLLVMTargets(StructuredData::Dictionary &dict) {
  auto array_up = std::make_unique<StructuredData::Array>();
#define LLVM_TARGET(target)                                                    \
  array_up->AddItem(std::make_unique<StructuredData::String>(#target));
#include "llvm/Config/Targets.def"
  auto entry_up = std::make_unique<StructuredData::Dictionary>();
  entry_up->AddItem("value", std::move(array_up));
  entry_up->AddStringItem("description", "A list of configured LLVM targets.");
  dict.AddItem("targets", std::move(entry_up));
}

SBStructuredData SBDebugger::GetBuildConfiguration() {
  LLDB_INSTRUMENT();

  auto config_up = std::make_unique<StructuredData::Dictionary>();
  AddBoolConfigEntry(
      *config_up, "xml", XMLDocument::XMLEnabled(),
      "A boolean value that indicates if XML support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "curses", LLDB_ENABLE_CURSES,
      "A boolean value that indicates if curses support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "editline", LLDB_ENABLE_LIBEDIT,
      "A boolean value that indicates if editline support is enabled in LLDB");
  AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR,
                     "A boolean value that indicates if editline wide "
                     "characters support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "lzma", LLDB_ENABLE_LZMA,
      "A boolean value that indicates if lzma support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "python", LLDB_ENABLE_PYTHON,
      "A boolean value that indicates if python support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "lua", LLDB_ENABLE_LUA,
      "A boolean value that indicates if lua support is enabled in LLDB");
  AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE,
                     "A boolean value that indicates if fbsdvmcore support is "
                     "enabled in LLDB");
  AddLLVMTargets(*config_up);

  SBStructuredData data;
  data.m_impl_up->SetObjectSP(std::move(config_up));
  return data;
}

bool SBDebugger::StateIsRunningState(StateType state) {
  LLDB_INSTRUMENT_VA(state);

  const bool result = lldb_private::StateIsRunningState(state);

  return result;
}

bool SBDebugger::StateIsStoppedState(StateType state) {
  LLDB_INSTRUMENT_VA(state);

  const bool result = lldb_private::StateIsStoppedState(state, false);

  return result;
}

lldb::SBTarget SBDebugger::CreateTarget(const char *filename,
                                        const char *target_triple,
                                        const char *platform_name,
                                        bool add_dependent_modules,
                                        lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, filename, target_triple, platform_name,
                     add_dependent_modules, sb_error);

  SBTarget sb_target;
  TargetSP target_sp;
  if (m_opaque_sp) {
    sb_error.Clear();
    OptionGroupPlatform platform_options(false);
    platform_options.SetPlatformName(platform_name);

    sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget(
        *m_opaque_sp, filename, target_triple,
        add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo,
        &platform_options, target_sp);

    if (sb_error.Success())
      sb_target.SetSP(target_sp);
  } else {
    sb_error.SetErrorString("invalid debugger");
  }

  Log *log = GetLog(LLDBLog::API);
  LLDB_LOGF(log,
            "SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, "
            "platform_name=%s, add_dependent_modules=%u, error=%s) => "
            "SBTarget(%p)",
            static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
            platform_name, add_dependent_modules, sb_error.GetCString(),
            static_cast<void *>(target_sp.get()));

  return sb_target;
}

SBTarget
SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename,
                                                const char *target_triple) {
  LLDB_INSTRUMENT_VA(this, filename, target_triple);

  SBTarget sb_target;
  TargetSP target_sp;
  if (m_opaque_sp) {
    const bool add_dependent_modules = true;
    Status error(m_opaque_sp->GetTargetList().CreateTarget(
        *m_opaque_sp, filename, target_triple,
        add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
        target_sp));
    sb_target.SetSP(target_sp);
  }

  Log *log = GetLog(LLDBLog::API);
  LLDB_LOGF(log,
            "SBDebugger(%p)::CreateTargetWithFileAndTargetTriple "
            "(filename=\"%s\", triple=%s) => SBTarget(%p)",
            static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
            static_cast<void *>(target_sp.get()));

  return sb_target;
}

SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename,
                                                 const char *arch_cstr) {
  LLDB_INSTRUMENT_VA(this, filename, arch_cstr);

  Log *log = GetLog(LLDBLog::API);

  SBTarget sb_target;
  TargetSP target_sp;
  if (m_opaque_sp) {
    Status error;
    if (arch_cstr == nullptr) {
      // The version of CreateTarget that takes an ArchSpec won't accept an
      // empty ArchSpec, so when the arch hasn't been specified, we need to
      // call the target triple version.
      error = m_opaque_sp->GetTargetList().CreateTarget(
          *m_opaque_sp, filename, arch_cstr, eLoadDependentsYes, nullptr,
          target_sp);
    } else {
      PlatformSP platform_sp =
          m_opaque_sp->GetPlatformList().GetSelectedPlatform();
      ArchSpec arch =
          Platform::GetAugmentedArchSpec(platform_sp.get(), arch_cstr);
      if (arch.IsValid())
        error = m_opaque_sp->GetTargetList().CreateTarget(
            *m_opaque_sp, filename, arch, eLoadDependentsYes, platform_sp,
            target_sp);
      else
        error.SetErrorStringWithFormat("invalid arch_cstr: %s", arch_cstr);
    }
    if (error.Success())
      sb_target.SetSP(target_sp);
  }

  LLDB_LOGF(log,
            "SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", "
            "arch=%s) => SBTarget(%p)",
            static_cast<void *>(m_opaque_sp.get()),
            filename ? filename : "<unspecified>",
            arch_cstr ? arch_cstr : "<unspecified>",
            static_cast<void *>(target_sp.get()));

  return sb_target;
}

SBTarget SBDebugger::CreateTarget(const char *filename) {
  LLDB_INSTRUMENT_VA(this, filename);

  SBTarget sb_target;
  TargetSP target_sp;
  if (m_opaque_sp) {
    Status error;
    const bool add_dependent_modules = true;
    error = m_opaque_sp->GetTargetList().CreateTarget(
        *m_opaque_sp, filename, "",
        add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
        target_sp);

    if (error.Success())
      sb_target.SetSP(target_sp);
  }
  Log *log = GetLog(LLDBLog::API);
  LLDB_LOGF(log,
            "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
            static_cast<void *>(m_opaque_sp.get()), filename,
            static_cast<void *>(target_sp.get()));
  return sb_target;
}

SBTarget SBDebugger::GetDummyTarget() {
  LLDB_INSTRUMENT_VA(this);

  SBTarget sb_target;
  if (m_opaque_sp) {
    sb_target.SetSP(m_opaque_sp->GetDummyTarget().shared_from_this());
  }
  Log *log = GetLog(LLDBLog::API);
  LLDB_LOGF(log, "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)",
            static_cast<void *>(m_opaque_sp.get()),
            static_cast<void *>(sb_target.GetSP().get()));
  return sb_target;
}

bool SBDebugger::DeleteTarget(lldb::SBTarget &target) {
  LLDB_INSTRUMENT_VA(this, target);

  bool result = false;
  if (m_opaque_sp) {
    TargetSP target_sp(target.GetSP());
    if (target_sp) {
      // No need to lock, the target list is thread safe
      result = m_opaque_sp->GetTargetList().DeleteTarget(target_sp);
      target_sp->Destroy();
      target.Clear();
    }
  }

  Log *log = GetLog(LLDBLog::API);
  LLDB_LOGF(log, "SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i",
            static_cast<void *>(m_opaque_sp.get()),
            static_cast<void *>(target.m_opaque_sp.get()), result);

  return result;
}

SBTarget SBDebugger::GetTargetAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBTarget sb_target;
  if (m_opaque_sp) {
    // No need to lock, the target list is thread safe
    sb_target.SetSP(m_opaque_sp->GetTargetList().GetTargetAtIndex(idx));
  }
  return sb_target;
}

uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) {
  LLDB_INSTRUMENT_VA(this, target);

  lldb::TargetSP target_sp = target.GetSP();
  if (!target_sp)
    return UINT32_MAX;

  if (!m_opaque_sp)
    return UINT32_MAX;

  return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP());
}

SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) {
  LLDB_INSTRUMENT_VA(this, pid);

  SBTarget sb_target;
  if (m_opaque_sp) {
    // No need to lock, the target list is thread safe
    sb_target.SetSP(m_opaque_sp->GetTargetList().FindTargetWithProcessID(pid));
  }
  return sb_target;
}

SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename,
                                               const char *arch_name) {
  LLDB_INSTRUMENT_VA(this, filename, arch_name);

  SBTarget sb_target;
  if (m_opaque_sp && filename && filename[0]) {
    // No need to lock, the target list is thread safe
    ArchSpec arch = Platform::GetAugmentedArchSpec(
        m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name);
    TargetSP target_sp(
        m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(
            FileSpec(filename), arch_name ? &arch : nullptr));
    sb_target.SetSP(target_sp);
  }
  return sb_target;
}

SBTarget SBDebugger::FindTargetWithLLDBProcess(const ProcessSP &process_sp) {
  SBTarget sb_target;
  if (m_opaque_sp) {
    // No need to lock, the target list is thread safe
    sb_target.SetSP(
        m_opaque_sp->GetTargetList().FindTargetWithProcess(process_sp.get()));
  }
  return sb_target;
}

uint32_t SBDebugger::GetNumTargets() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp) {
    // No need to lock, the target list is thread safe
    return m_opaque_sp->GetTargetList().GetNumTargets();
  }
  return 0;
}

SBTarget SBDebugger::GetSelectedTarget() {
  LLDB_INSTRUMENT_VA(this);

  Log *log = GetLog(LLDBLog::API);

  SBTarget sb_target;
  TargetSP target_sp;
  if (m_opaque_sp) {
    // No need to lock, the target list is thread safe
    target_sp = m_opaque_sp->GetTargetList().GetSelectedTarget();
    sb_target.SetSP(target_sp);
  }

  if (log) {
    SBStream sstr;
    sb_target.GetDescription(sstr, eDescriptionLevelBrief);
    LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s",
              static_cast<void *>(m_opaque_sp.get()),
              static_cast<void *>(target_sp.get()), sstr.GetData());
  }

  return sb_target;
}

void SBDebugger::SetSelectedTarget(SBTarget &sb_target) {
  LLDB_INSTRUMENT_VA(this, sb_target);

  Log *log = GetLog(LLDBLog::API);

  TargetSP target_sp(sb_target.GetSP());
  if (m_opaque_sp) {
    m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp);
  }
  if (log) {
    SBStream sstr;
    sb_target.GetDescription(sstr, eDescriptionLevelBrief);
    LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s",
              static_cast<void *>(m_opaque_sp.get()),
              static_cast<void *>(target_sp.get()), sstr.GetData());
  }
}

SBPlatform SBDebugger::GetSelectedPlatform() {
  LLDB_INSTRUMENT_VA(this);

  Log *log = GetLog(LLDBLog::API);

  SBPlatform sb_platform;
  DebuggerSP debugger_sp(m_opaque_sp);
  if (debugger_sp) {
    sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
  }
  LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s",
            static_cast<void *>(m_opaque_sp.get()),
            static_cast<void *>(sb_platform.GetSP().get()),
            sb_platform.GetName());
  return sb_platform;
}

void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) {
  LLDB_INSTRUMENT_VA(this, sb_platform);

  Log *log = GetLog(LLDBLog::API);

  DebuggerSP debugger_sp(m_opaque_sp);
  if (debugger_sp) {
    debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
  }

  LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)",
            static_cast<void *>(m_opaque_sp.get()),
            static_cast<void *>(sb_platform.GetSP().get()),
            sb_platform.GetName());
}

uint32_t SBDebugger::GetNumPlatforms() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp) {
    // No need to lock, the platform list is thread safe
    return m_opaque_sp->GetPlatformList().GetSize();
  }
  return 0;
}

SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBPlatform sb_platform;
  if (m_opaque_sp) {
    // No need to lock, the platform list is thread safe
    sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx));
  }
  return sb_platform;
}

uint32_t SBDebugger::GetNumAvailablePlatforms() {
  LLDB_INSTRUMENT_VA(this);

  uint32_t idx = 0;
  while (true) {
    if (PluginManager::GetPlatformPluginNameAtIndex(idx).empty()) {
      break;
    }
    ++idx;
  }
  // +1 for the host platform, which should always appear first in the list.
  return idx + 1;
}

SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBStructuredData data;
  auto platform_dict = std::make_unique<StructuredData::Dictionary>();
  llvm::StringRef name_str("name"), desc_str("description");

  if (idx == 0) {
    PlatformSP host_platform_sp(Platform::GetHostPlatform());
    platform_dict->AddStringItem(name_str, host_platform_sp->GetPluginName());
    platform_dict->AddStringItem(
        desc_str, llvm::StringRef(host_platform_sp->GetDescription()));
  } else if (idx > 0) {
    llvm::StringRef plugin_name =
        PluginManager::GetPlatformPluginNameAtIndex(idx - 1);
    if (plugin_name.empty()) {
      return data;
    }
    platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name));

    llvm::StringRef plugin_desc =
        PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1);
    platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc));
  }

  data.m_impl_up->SetObjectSP(
      StructuredData::ObjectSP(platform_dict.release()));
  return data;
}

void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) {
  LLDB_INSTRUMENT_VA(this, baton, data, data_len);

  DispatchInput(data, data_len);
}

void SBDebugger::DispatchInput(const void *data, size_t data_len) {
  LLDB_INSTRUMENT_VA(this, data, data_len);

  //    Log *log(GetLog (LLDBLog::API));
  //
  //    if (log)
  //        LLDB_LOGF(log, "SBDebugger(%p)::DispatchInput (data=\"%.*s\",
  //        size_t=%" PRIu64 ")",
  //                     m_opaque_sp.get(),
  //                     (int) data_len,
  //                     (const char *) data,
  //                     (uint64_t)data_len);
  //
  //    if (m_opaque_sp)
  //        m_opaque_sp->DispatchInput ((const char *) data, data_len);
}

void SBDebugger::DispatchInputInterrupt() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp)
    m_opaque_sp->DispatchInputInterrupt();
}

void SBDebugger::DispatchInputEndOfFile() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_sp)
    m_opaque_sp->DispatchInputEndOfFile();
}

void SBDebugger::PushInputReader(SBInputReader &reader) {
  LLDB_INSTRUMENT_VA(this, reader);
}

void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
                                       bool spawn_thread) {
  LLDB_INSTRUMENT_VA(this, auto_handle_events, spawn_thread);

  if (m_opaque_sp) {
    CommandInterpreterRunOptions options;
    options.SetAutoHandleEvents(auto_handle_events);
    options.SetSpawnThread(spawn_thread);
    m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(options);
  }
}

void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
                                       bool spawn_thread,
                                       SBCommandInterpreterRunOptions &options,
                                       int &num_errors, bool &quit_requested,
                                       bool &stopped_for_crash)

{
  LLDB_INSTRUMENT_VA(this, auto_handle_events, spawn_thread, options,
                     num_errors, quit_requested, stopped_for_crash);

  if (m_opaque_sp) {
    options.SetAutoHandleEvents(auto_handle_events);
    options.SetSpawnThread(spawn_thread);
    CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
    CommandInterpreterRunResult result =
        interp.RunCommandInterpreter(options.ref());
    num_errors = result.GetNumErrors();
    quit_requested =
        result.IsResult(lldb::eCommandInterpreterResultQuitRequested);
    stopped_for_crash =
        result.IsResult(lldb::eCommandInterpreterResultInferiorCrash);
  }
}

SBCommandInterpreterRunResult SBDebugger::RunCommandInterpreter(
    const SBCommandInterpreterRunOptions &options) {
  LLDB_INSTRUMENT_VA(this, options);

  if (!m_opaque_sp)
    return SBCommandInterpreterRunResult();

  CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
  CommandInterpreterRunResult result =
      interp.RunCommandInterpreter(options.ref());

  return SBCommandInterpreterRunResult(result);
}

SBError SBDebugger::RunREPL(lldb::LanguageType language,
                            const char *repl_options) {
  LLDB_INSTRUMENT_VA(this, language, repl_options);

  SBError error;
  if (m_opaque_sp)
    error.ref() = m_opaque_sp->RunREPL(language, repl_options);
  else
    error.SetErrorString("invalid debugger");
  return error;
}

void SBDebugger::reset(const DebuggerSP &debugger_sp) {
  m_opaque_sp = debugger_sp;
}

Debugger *SBDebugger::get() const { return m_opaque_sp.get(); }

Debugger &SBDebugger::ref() const {
  assert(m_opaque_sp.get());
  return *m_opaque_sp;
}

const lldb::DebuggerSP &SBDebugger::get_sp() const { return m_opaque_sp; }

SBDebugger SBDebugger::FindDebuggerWithID(int id) {
  LLDB_INSTRUMENT_VA(id);

  // No need to lock, the debugger list is thread safe
  SBDebugger sb_debugger;
  DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(id);
  if (debugger_sp)
    sb_debugger.reset(debugger_sp);
  return sb_debugger;
}

const char *SBDebugger::GetInstanceName() {
  LLDB_INSTRUMENT_VA(this);

  if (!m_opaque_sp)
    return nullptr;

  return ConstString(m_opaque_sp->GetInstanceName()).AsCString();
}

SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value,
                                        const char *debugger_instance_name) {
  LLDB_INSTRUMENT_VA(var_name, value, debugger_instance_name);

  SBError sb_error;
  DebuggerSP debugger_sp(
      Debugger::FindDebuggerWithInstanceName(debugger_instance_name));
  Status error;
  if (debugger_sp) {
    ExecutionContext exe_ctx(
        debugger_sp->GetCommandInterpreter().GetExecutionContext());
    error = debugger_sp->SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
                                          var_name, value);
  } else {
    error.SetErrorStringWithFormat("invalid debugger instance name '%s'",
                                   debugger_instance_name);
  }
  if (error.Fail())
    sb_error.SetError(error);
  return sb_error;
}

SBStringList
SBDebugger::GetInternalVariableValue(const char *var_name,
                                     const char *debugger_instance_name) {
  LLDB_INSTRUMENT_VA(var_name, debugger_instance_name);

  DebuggerSP debugger_sp(
      Debugger::FindDebuggerWithInstanceName(debugger_instance_name));
  Status error;
  if (debugger_sp) {
    ExecutionContext exe_ctx(
        debugger_sp->GetCommandInterpreter().GetExecutionContext());
    lldb::OptionValueSP value_sp(
        debugger_sp->GetPropertyValue(&exe_ctx, var_name, error));
    if (value_sp) {
      StreamString value_strm;
      value_sp->DumpValue(&exe_ctx, value_strm, OptionValue::eDumpOptionValue);
      const std::string &value_str = std::string(value_strm.GetString());
      if (!value_str.empty()) {
        StringList string_list;
        string_list.SplitIntoLines(value_str);
        return SBStringList(&string_list);
      }
    }
  }
  return SBStringList();
}

uint32_t SBDebugger::GetTerminalWidth() const {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
}

void SBDebugger::SetTerminalWidth(uint32_t term_width) {
  LLDB_INSTRUMENT_VA(this, term_width);

  if (m_opaque_sp)
    m_opaque_sp->SetTerminalWidth(term_width);
}

const char *SBDebugger::GetPrompt() const {
  LLDB_INSTRUMENT_VA(this);

  Log *log = GetLog(LLDBLog::API);

  LLDB_LOG(log, "SBDebugger({0:x})::GetPrompt () => \"{1}\"",
           static_cast<void *>(m_opaque_sp.get()),
           (m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));

  return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString()
                      : nullptr);
}

void SBDebugger::SetPrompt(const char *prompt) {
  LLDB_INSTRUMENT_VA(this, prompt);

  if (m_opaque_sp)
    m_opaque_sp->SetPrompt(llvm::StringRef(prompt));
}

const char *SBDebugger::GetReproducerPath() const {
  LLDB_INSTRUMENT_VA(this);

  return "GetReproducerPath has been deprecated";
}

ScriptLanguage SBDebugger::GetScriptLanguage() const {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
}

void SBDebugger::SetScriptLanguage(ScriptLanguage script_lang) {
  LLDB_INSTRUMENT_VA(this, script_lang);

  if (m_opaque_sp) {
    m_opaque_sp->SetScriptLanguage(script_lang);
  }
}

LanguageType SBDebugger::GetREPLLanguage() const {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetREPLLanguage() : eLanguageTypeUnknown);
}

void SBDebugger::SetREPLLanguage(LanguageType repl_lang) {
  LLDB_INSTRUMENT_VA(this, repl_lang);

  if (m_opaque_sp) {
    m_opaque_sp->SetREPLLanguage(repl_lang);
  }
}

bool SBDebugger::SetUseExternalEditor(bool value) {
  LLDB_INSTRUMENT_VA(this, value);

  return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false);
}

bool SBDebugger::GetUseExternalEditor() {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false);
}

bool SBDebugger::SetUseColor(bool value) {
  LLDB_INSTRUMENT_VA(this, value);

  return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false);
}

bool SBDebugger::GetUseColor() const {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false);
}

bool SBDebugger::SetUseSourceCache(bool value) {
  LLDB_INSTRUMENT_VA(this, value);

  return (m_opaque_sp ? m_opaque_sp->SetUseSourceCache(value) : false);
}

bool SBDebugger::GetUseSourceCache() const {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetUseSourceCache() : false);
}

bool SBDebugger::GetDescription(SBStream &description) {
  LLDB_INSTRUMENT_VA(this, description);

  Stream &strm = description.ref();

  if (m_opaque_sp) {
    const char *name = m_opaque_sp->GetInstanceName().c_str();
    user_id_t id = m_opaque_sp->GetID();
    strm.Printf("Debugger (instance: \"%s\", id: %" PRIu64 ")", name, id);
  } else
    strm.PutCString("No value");

  return true;
}

user_id_t SBDebugger::GetID() {
  LLDB_INSTRUMENT_VA(this);

  return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID);
}

SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) {
  LLDB_INSTRUMENT_VA(this, platform_name_cstr);

  SBError sb_error;
  if (m_opaque_sp) {
    if (platform_name_cstr && platform_name_cstr[0]) {
      PlatformList &platforms = m_opaque_sp->GetPlatformList();
      if (PlatformSP platform_sp = platforms.GetOrCreate(platform_name_cstr))
        platforms.SetSelectedPlatform(platform_sp);
      else
        sb_error.ref().SetErrorString("platform not found");
    } else {
      sb_error.ref().SetErrorString("invalid platform name");
    }
  } else {
    sb_error.ref().SetErrorString("invalid debugger");
  }
  return sb_error;
}

bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) {
  LLDB_INSTRUMENT_VA(this, sysroot);

  if (SBPlatform platform = GetSelectedPlatform()) {
    platform.SetSDKRoot(sysroot);
    return true;
  }
  return false;
}

bool SBDebugger::GetCloseInputOnEOF() const {
  LLDB_INSTRUMENT_VA(this);

  return false;
}

void SBDebugger::SetCloseInputOnEOF(bool b) {
  LLDB_INSTRUMENT_VA(this, b);
}

SBTypeCategory SBDebugger::GetCategory(const char *category_name) {
  LLDB_INSTRUMENT_VA(this, category_name);

  if (!category_name || *category_name == 0)
    return SBTypeCategory();

  TypeCategoryImplSP category_sp;

  if (DataVisualization::Categories::GetCategory(ConstString(category_name),
                                                 category_sp, false)) {
    return SBTypeCategory(category_sp);
  } else {
    return SBTypeCategory();
  }
}

SBTypeCategory SBDebugger::GetCategory(lldb::LanguageType lang_type) {
  LLDB_INSTRUMENT_VA(this, lang_type);

  TypeCategoryImplSP category_sp;
  if (DataVisualization::Categories::GetCategory(lang_type, category_sp)) {
    return SBTypeCategory(category_sp);
  } else {
    return SBTypeCategory();
  }
}

SBTypeCategory SBDebugger::CreateCategory(const char *category_name) {
  LLDB_INSTRUMENT_VA(this, category_name);

  if (!category_name || *category_name == 0)
    return SBTypeCategory();

  TypeCategoryImplSP category_sp;

  if (DataVisualization::Categories::GetCategory(ConstString(category_name),
                                                 category_sp, true)) {
    return SBTypeCategory(category_sp);
  } else {
    return SBTypeCategory();
  }
}

bool SBDebugger::DeleteCategory(const char *category_name) {
  LLDB_INSTRUMENT_VA(this, category_name);

  if (!category_name || *category_name == 0)
    return false;

  return DataVisualization::Categories::Delete(ConstString(category_name));
}

uint32_t SBDebugger::GetNumCategories() {
  LLDB_INSTRUMENT_VA(this);

  return DataVisualization::Categories::GetCount();
}

SBTypeCategory SBDebugger::GetCategoryAtIndex(uint32_t index) {
  LLDB_INSTRUMENT_VA(this, index);

  return SBTypeCategory(
      DataVisualization::Categories::GetCategoryAtIndex(index));
}

SBTypeCategory SBDebugger::GetDefaultCategory() {
  LLDB_INSTRUMENT_VA(this);

  return GetCategory("default");
}

SBTypeFormat SBDebugger::GetFormatForType(SBTypeNameSpecifier type_name) {
  LLDB_INSTRUMENT_VA(this, type_name);

  SBTypeCategory default_category_sb = GetDefaultCategory();
  if (default_category_sb.GetEnabled())
    return default_category_sb.GetFormatForType(type_name);
  return SBTypeFormat();
}

SBTypeSummary SBDebugger::GetSummaryForType(SBTypeNameSpecifier type_name) {
  LLDB_INSTRUMENT_VA(this, type_name);

  if (!type_name.IsValid())
    return SBTypeSummary();
  return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
}

SBTypeFilter SBDebugger::GetFilterForType(SBTypeNameSpecifier type_name) {
  LLDB_INSTRUMENT_VA(this, type_name);

  if (!type_name.IsValid())
    return SBTypeFilter();
  return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP()));
}

SBTypeSynthetic SBDebugger::GetSyntheticForType(SBTypeNameSpecifier type_name) {
  LLDB_INSTRUMENT_VA(this, type_name);

  if (!type_name.IsValid())
    return SBTypeSynthetic();
  return SBTypeSynthetic(
      DataVisualization::GetSyntheticForType(type_name.GetSP()));
}

static llvm::ArrayRef<const char *> GetCategoryArray(const char **categories) {
  if (categories == nullptr)
    return {};
  size_t len = 0;
  while (categories[len] != nullptr)
    ++len;
  return llvm::ArrayRef(categories, len);
}

bool SBDebugger::EnableLog(const char *channel, const char **categories) {
  LLDB_INSTRUMENT_VA(this, channel, categories);

  if (m_opaque_sp) {
    uint32_t log_options =
        LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
    std::string error;
    llvm::raw_string_ostream error_stream(error);
    return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "",
                                  log_options, /*buffer_size=*/0,
                                  eLogHandlerStream, error_stream);
  } else
    return false;
}

void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
                                    void *baton) {
  LLDB_INSTRUMENT_VA(this, log_callback, baton);

  if (m_opaque_sp) {
    return m_opaque_sp->SetLoggingCallback(log_callback, baton);
  }
}

void SBDebugger::SetDestroyCallback(
    lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
  LLDB_INSTRUMENT_VA(this, destroy_callback, baton);
  if (m_opaque_sp) {
    return m_opaque_sp->SetDestroyCallback(
        destroy_callback, baton);
  }
}

SBTrace
SBDebugger::LoadTraceFromFile(SBError &error,
                              const SBFileSpec &trace_description_file) {
  LLDB_INSTRUMENT_VA(this, error, trace_description_file);
  return SBTrace::LoadTraceFromFile(error, *this, trace_description_file);
}

void SBDebugger::RequestInterrupt() {
  LLDB_INSTRUMENT_VA(this);
  
  if (m_opaque_sp)
    m_opaque_sp->RequestInterrupt();  
}
void SBDebugger::CancelInterruptRequest()  {
  LLDB_INSTRUMENT_VA(this);
  
  if (m_opaque_sp)
    m_opaque_sp->CancelInterruptRequest();  
}

bool SBDebugger::InterruptRequested()   {
  LLDB_INSTRUMENT_VA(this);
  
  if (m_opaque_sp)
    return m_opaque_sp->InterruptRequested();
  return false;
}
