//===-- SBDebugger.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/API/SBDebugger.h"

#include "lldb/lldb-private.h"

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

#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"

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

using namespace lldb;
using namespace lldb_private;

static llvm::sys::DynamicLibrary
LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error)
{
    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)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 (spec.Exists())
            error.SetErrorString("this file does not represent a loadable dylib");
        else
            error.SetErrorString("no such file");
    }
    return llvm::sys::DynamicLibrary();
}

static llvm::ManagedStatic<SystemLifetimeManager> g_debugger_lifetime;

SBError
SBInputReader::Initialize(lldb::SBDebugger &sb_debugger,
                          unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction, char const *,
                                            unsigned long),
                          void *, lldb::InputReaderGranularity, char const *, char const *, bool)
{
    return SBError();
}

void
SBInputReader::SetIsDone(bool)
{
}

bool
SBInputReader::IsActive() const
{
    return false;
}

SBDebugger::SBDebugger() = default;

SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) :
    m_opaque_sp(debugger_sp)
{
}

SBDebugger::SBDebugger(const SBDebugger &rhs) :
    m_opaque_sp (rhs.m_opaque_sp)
{
}

SBDebugger::~SBDebugger() = default;

SBDebugger &
SBDebugger::operator = (const SBDebugger &rhs)
{
    if (this != &rhs)
    {
        m_opaque_sp = rhs.m_opaque_sp;
    }
    return *this;
}

void
SBDebugger::Initialize ()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger::Initialize ()");

    g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerFull>(), LoadPlugin);
}

void
SBDebugger::Terminate ()
{
    g_debugger_lifetime->Terminate();
}

void
SBDebugger::Clear ()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::Clear ()",
                     static_cast<void*>(m_opaque_sp.get()));

    if (m_opaque_sp)
        m_opaque_sp->ClearIOHandlers ();

    m_opaque_sp.reset();
}

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

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

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

{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    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));

    if (log)
    {
        SBStream sstr;
        debugger.GetDescription (sstr);
        log->Printf ("SBDebugger::Create () => SBDebugger(%p): %s",
                     static_cast<void*>(debugger.m_opaque_sp.get()),
                     sstr.GetData());
    }

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

void
SBDebugger::Destroy (SBDebugger &debugger)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
    {
        SBStream sstr;
        debugger.GetDescription (sstr);
        log->Printf ("SBDebugger::Destroy () => SBDebugger(%p): %s",
                     static_cast<void*>(debugger.m_opaque_sp.get()),
                     sstr.GetData());
    }

    Debugger::Destroy (debugger.m_opaque_sp);

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

void
SBDebugger::MemoryPressureDetected ()
{
    // 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.
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    const bool mandatory = false;
    if (log)
    {
        log->Printf ("SBDebugger::MemoryPressureDetected (), mandatory = %d", mandatory);
    }
    
    ModuleList::RemoveOrphanSharedModules(mandatory);
}

bool
SBDebugger::IsValid() const
{
    return m_opaque_sp.get() != nullptr;
}

void
SBDebugger::SetAsync (bool b)
{
    if (m_opaque_sp)
        m_opaque_sp->SetAsyncExecution(b);
}

bool
SBDebugger::GetAsync()
{
    return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false);
}

void
SBDebugger::SkipLLDBInitFiles (bool b)
{
    if (m_opaque_sp)
        m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles (b);
}

void
SBDebugger::SkipAppInitFiles (bool b)
{
    if (m_opaque_sp)
        m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles (b);
}

// 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.
void
SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::SetInputFileHandle (fh=%p, transfer_ownership=%i)",
                     static_cast<void*>(m_opaque_sp.get()),
                     static_cast<void*>(fh), transfer_ownership);

    if (m_opaque_sp)
        m_opaque_sp->SetInputFileHandle (fh, transfer_ownership);
}

void
SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));


    if (log)
        log->Printf ("SBDebugger(%p)::SetOutputFileHandle (fh=%p, transfer_ownership=%i)",
                     static_cast<void*>(m_opaque_sp.get()),
                     static_cast<void*>(fh), transfer_ownership);

    if (m_opaque_sp)
        m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership);
}

void
SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));


    if (log)
        log->Printf ("SBDebugger(%p)::SetErrorFileHandle (fh=%p, transfer_ownership=%i)",
                     static_cast<void*>(m_opaque_sp.get()),
                     static_cast<void*>(fh), transfer_ownership);

    if (m_opaque_sp)
        m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership);
}

FILE *
SBDebugger::GetInputFileHandle ()
{
    if (m_opaque_sp)
    {
        StreamFileSP stream_file_sp (m_opaque_sp->GetInputFile());
        if (stream_file_sp)
            return stream_file_sp->GetFile().GetStream();
    }
    return nullptr;
}

FILE *
SBDebugger::GetOutputFileHandle ()
{
    if (m_opaque_sp)
    {
        StreamFileSP stream_file_sp (m_opaque_sp->GetOutputFile());
        if (stream_file_sp)
            return stream_file_sp->GetFile().GetStream();
    }
    return nullptr;
}

FILE *
SBDebugger::GetErrorFileHandle ()
{
    if (m_opaque_sp)
    {
        StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile());
        if (stream_file_sp)
            return stream_file_sp->GetFile().GetStream();
    }
    return nullptr;
}

void
SBDebugger::SaveInputTerminalState()
{
    if (m_opaque_sp)
        m_opaque_sp->SaveInputTerminalState();
}

void
SBDebugger::RestoreInputTerminalState()
{
    if (m_opaque_sp)
        m_opaque_sp->RestoreInputTerminalState();

}
SBCommandInterpreter
SBDebugger::GetCommandInterpreter ()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

    if (log)
        log->Printf ("SBDebugger(%p)::GetCommandInterpreter () => SBCommandInterpreter(%p)",
                     static_cast<void*>(m_opaque_sp.get()),
                     static_cast<void*>(sb_interpreter.get()));

    return sb_interpreter;
}

void
SBDebugger::HandleCommand (const char *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);

        if (GetErrorFileHandle() != nullptr)
            result.PutError (GetErrorFileHandle());
        if (GetOutputFileHandle() != nullptr)
            result.PutOutput (GetOutputFileHandle());

        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->GetNextEventForBroadcaster (process_sp.get(), event_sp))
                {
                    SBEvent event(event_sp);
                    HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
                }
            }
        }
    }
}

SBListener
SBDebugger::GetListener ()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

    if (log)
        log->Printf ("SBDebugger(%p)::GetListener () => SBListener(%p)",
                     static_cast<void*>(m_opaque_sp.get()),
                     static_cast<void*>(sb_listener.get()));

    return sb_listener;
}

void
SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
{
    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 != nullptr)
                ::fwrite (stdio_buffer, 1, len, out);
    }
    
    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 != nullptr)
                ::fwrite (stdio_buffer, 1, len, err);
    }
    
    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);
    }
}

SBSourceManager
SBDebugger::GetSourceManager ()
{
    SBSourceManager sb_source_manager (*this);
    return sb_source_manager;
}

bool
SBDebugger::GetDefaultArchitecture (char *arch_name, size_t 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)
{
    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)
{
    return Args::StringToScriptLanguage(script_language_name,
                                        eScriptLanguageDefault,
                                        nullptr);
}

const char *
SBDebugger::GetVersionString ()
{
    return lldb_private::GetVersion();
}

const char *
SBDebugger::StateAsCString (StateType state)
{
    return lldb_private::StateAsCString (state);
}

bool
SBDebugger::StateIsRunningState (StateType state)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    const bool result = lldb_private::StateIsRunningState (state);
    if (log)
        log->Printf ("SBDebugger::StateIsRunningState (state=%s) => %i", 
                     StateAsCString (state), result);

    return result;
}

bool
SBDebugger::StateIsStoppedState (StateType state)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    const bool result = lldb_private::StateIsStoppedState (state, false);
    if (log)
        log->Printf ("SBDebugger::StateIsStoppedState (state=%s) => %i", 
                     StateAsCString (state), result);

    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)
{
    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, 
                                                                    &platform_options,
                                                                    target_sp);

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

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("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)
{
    SBTarget sb_target;
    TargetSP target_sp;
    if (m_opaque_sp)
    {
        const bool add_dependent_modules = true;
        Error error (m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
                                                               filename,
                                                               target_triple,
                                                               add_dependent_modules,
                                                               nullptr,
                                                               target_sp));
        sb_target.SetSP (target_sp);
    }

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("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)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBTarget sb_target;
    TargetSP target_sp;
    if (m_opaque_sp)
    {
        Error error;
        const bool add_dependent_modules = true;

        error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
                                                          filename,
                                                          arch_cstr,
                                                          add_dependent_modules,
                                                          nullptr,
                                                          target_sp);

        if (error.Success())
        {
            m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
            sb_target.SetSP (target_sp);
        }
    }

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

    return sb_target;
}

SBTarget
SBDebugger::CreateTarget (const char *filename)
{
    SBTarget sb_target;
    TargetSP target_sp;
    if (m_opaque_sp)
    {
        Error error;
        const bool add_dependent_modules = true;
        error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
                                                          filename,
                                                          nullptr,
                                                          add_dependent_modules,
                                                          nullptr,
                                                          target_sp);

        if (error.Success())
        {
            m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
            sb_target.SetSP (target_sp);
        }
    }
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
                     static_cast<void*>(m_opaque_sp.get()), filename,
                     static_cast<void*>(target_sp.get()));
    return sb_target;
}

bool
SBDebugger::DeleteTarget (lldb::SBTarget &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();
            const bool mandatory = true;
            ModuleList::RemoveOrphanSharedModules(mandatory);
        }
    }

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("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)
{
    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::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)
{
    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)
{
    SBTarget sb_target;
    if (m_opaque_sp && filename && filename[0])
    {
        // No need to lock, the target list is thread safe
        ArchSpec arch (arch_name, m_opaque_sp->GetPlatformList().GetSelectedPlatform().get());
        TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(FileSpec(filename, false), 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 ()
{
    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 ()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_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);
        log->Printf ("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)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

SBPlatform
SBDebugger::GetSelectedPlatform()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    SBPlatform sb_platform;
    DebuggerSP debugger_sp(m_opaque_sp);
    if (debugger_sp)
    {
        sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
    }
    if (log)
        log->Printf ("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)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

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

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

void
SBDebugger::DispatchInput (const void *data, size_t data_len)
{
//    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
//
//    if (log)
//        log->Printf ("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 ()
{
    if (m_opaque_sp)
        m_opaque_sp->DispatchInputInterrupt ();
}

void
SBDebugger::DispatchInputEndOfFile ()
{
    if (m_opaque_sp)
        m_opaque_sp->DispatchInputEndOfFile ();
}

void
SBDebugger::PushInputReader (SBInputReader &reader)
{
}

void
SBDebugger::RunCommandInterpreter (bool auto_handle_events,
                                   bool spawn_thread)
{
    if (m_opaque_sp)
    {
        CommandInterpreterRunOptions options;

        m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(auto_handle_events,
                                                                   spawn_thread,
                                                                   options);
    }
}

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

{
    if (m_opaque_sp)
    {
        CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
        interp.RunCommandInterpreter(auto_handle_events, spawn_thread, options.ref());
        num_errors = interp.GetNumErrors();
        quit_requested = interp.GetQuitRequested();
        stopped_for_crash = interp.GetStoppedForCrash();
    }
}

SBError
SBDebugger::RunREPL (lldb::LanguageType language, const char *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)
{
    // 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()
{
    return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr);
}

SBError
SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name)
{
    SBError sb_error;
    DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName (ConstString(debugger_instance_name)));
    Error 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)
{
    SBStringList ret_value;
    DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName (ConstString(debugger_instance_name)));
    Error error;
    if (debugger_sp)
    {
        ExecutionContext exe_ctx (debugger_sp->GetCommandInterpreter().GetExecutionContext());
        lldb::OptionValueSP value_sp (debugger_sp->GetPropertyValue (&exe_ctx,
                                                                     var_name,
                                                                     false,
                                                                     error));
        if (value_sp)
        {
            StreamString value_strm;
            value_sp->DumpValue (&exe_ctx, value_strm, OptionValue::eDumpOptionValue);
            const std::string &value_str = 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
{
    return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
}

void
SBDebugger::SetTerminalWidth (uint32_t term_width)
{
    if (m_opaque_sp)
        m_opaque_sp->SetTerminalWidth (term_width);
}

const char *
SBDebugger::GetPrompt() const
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::GetPrompt () => \"%s\"",
                     static_cast<void*>(m_opaque_sp.get()),
                     (m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));

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

void
SBDebugger::SetPrompt (const char *prompt)
{
    if (m_opaque_sp)
        m_opaque_sp->SetPrompt (prompt);
}
    
ScriptLanguage 
SBDebugger::GetScriptLanguage() const
{
    return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
}

void
SBDebugger::SetScriptLanguage (ScriptLanguage script_lang)
{
    if (m_opaque_sp)
    {
        m_opaque_sp->SetScriptLanguage (script_lang);
    }
}

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

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

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

bool
SBDebugger::GetUseColor() const
{
    return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false);
}

bool
SBDebugger::GetDescription (SBStream &description)
{
    Stream &strm = description.ref();

    if (m_opaque_sp)
    {
        const char *name = m_opaque_sp->GetInstanceName().AsCString();
        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()
{
    return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID);
}

SBError
SBDebugger::SetCurrentPlatform (const char *platform_name_cstr)
{
    SBError sb_error;
    if (m_opaque_sp)
    {
        if (platform_name_cstr && platform_name_cstr[0])
        {
            ConstString platform_name (platform_name_cstr);
            PlatformSP platform_sp (Platform::Find (platform_name));

            if (platform_sp)
            {
                // Already have a platform with this name, just select it
                m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp);
            }
            else
            {
                // We don't have a platform by this name yet, create one
                platform_sp = Platform::Create (platform_name, sb_error.ref());
                if (platform_sp)
                {
                    // We created the platform, now append and select it
                    bool make_selected = true;
                    m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected);
                }
            }
        }
        else
        {
            sb_error.ref().SetErrorString("invalid platform name");
        }
    }
    else
    {
        sb_error.ref().SetErrorString("invalid debugger");
    }
    return sb_error;
}

bool
SBDebugger::SetCurrentPlatformSDKRoot (const char *sysroot)
{
    if (m_opaque_sp)
    {
        PlatformSP platform_sp (m_opaque_sp->GetPlatformList().GetSelectedPlatform());
        
        if (platform_sp)
        {
            platform_sp->SetSDKRootDirectory (ConstString (sysroot));
            return true;
        }
    }
    return false;
}

bool
SBDebugger::GetCloseInputOnEOF() const
{
    return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false);
}

void
SBDebugger::SetCloseInputOnEOF (bool b)
{
    if (m_opaque_sp)
        m_opaque_sp->SetCloseInputOnEOF (b);
}

SBTypeCategory
SBDebugger::GetCategory (const char* 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)
{
    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)
{
    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)
{
    if (!category_name || *category_name == 0)
        return false;
    
    return DataVisualization::Categories::Delete(ConstString(category_name));
}

uint32_t
SBDebugger::GetNumCategories()
{
    return DataVisualization::Categories::GetCount();
}

SBTypeCategory
SBDebugger::GetCategoryAtIndex (uint32_t index)
{
    return SBTypeCategory(DataVisualization::Categories::GetCategoryAtIndex(index));
}

SBTypeCategory
SBDebugger::GetDefaultCategory()
{
    return GetCategory("default");
}

SBTypeFormat
SBDebugger::GetFormatForType (SBTypeNameSpecifier type_name)
{
    SBTypeCategory default_category_sb = GetDefaultCategory();
    if (default_category_sb.GetEnabled())
        return default_category_sb.GetFormatForType(type_name);
    return SBTypeFormat();
}

#ifndef LLDB_DISABLE_PYTHON
SBTypeSummary
SBDebugger::GetSummaryForType (SBTypeNameSpecifier type_name)
{
    if (!type_name.IsValid())
        return SBTypeSummary();
    return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
}
#endif // LLDB_DISABLE_PYTHON

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

#ifndef LLDB_DISABLE_PYTHON
SBTypeSynthetic
SBDebugger::GetSyntheticForType (SBTypeNameSpecifier type_name)
{
    if (!type_name.IsValid())
        return SBTypeSynthetic();
    return SBTypeSynthetic(DataVisualization::GetSyntheticForType(type_name.GetSP()));
}
#endif // LLDB_DISABLE_PYTHON

bool
SBDebugger::EnableLog (const char *channel, const char **categories)
{
    if (m_opaque_sp)
    {
        uint32_t log_options = LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
        StreamString errors;
        return m_opaque_sp->EnableLog(channel, categories, nullptr, log_options, errors);
    }
    else
        return false;
}

void
SBDebugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton)
{
    if (m_opaque_sp)
    {
        return m_opaque_sp->SetLoggingCallback (log_callback, baton);
    }
}
