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

#include "lldb/API/SBDebugger.h"

#include "lldb/lldb-private.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/SBInputReader.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/DataVisualization.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.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"

using namespace lldb;
using namespace lldb_private;

void
SBDebugger::Initialize ()
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

    SBCommandInterpreter::InitializeSWIG ();

    Debugger::Initialize();
}

void
SBDebugger::Terminate ()
{
    Debugger::Terminate();
}

void
SBDebugger::Clear ()
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::Clear ()", m_opaque_sp.get());
        
    if (m_opaque_sp)
        m_opaque_sp->CleanUpInputReaders ();

    m_opaque_sp.reset();
}

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

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

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

{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

    if (log)
    {
        SBStream sstr;
        debugger.GetDescription (sstr);
        log->Printf ("SBDebugger::Create () => SBDebugger(%p): %s", 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)
{
    LogSP log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (log)
    {
        SBStream sstr;
        debugger.GetDescription (sstr);
        log->Printf ("SBDebugger::Destroy () => SBDebugger(%p): %s", debugger.m_opaque_sp.get(), sstr.GetData());
    }
    
    Debugger::Destroy (debugger.m_opaque_sp);
    
    if (debugger.m_opaque_sp.get() != NULL)
        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.
    const bool mandatory = false;
    ModuleList::RemoveOrphanSharedModules(mandatory);
}

SBDebugger::SBDebugger () :
    m_opaque_sp ()
{
}

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::operator = (const SBDebugger &rhs)
{
    if (this != &rhs)
    {
        m_opaque_sp = rhs.m_opaque_sp;
    }
    return *this;
}

SBDebugger::~SBDebugger ()
{
}

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


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

bool
SBDebugger::GetAsync ()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetAsyncExecution();
    else
        return 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)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

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

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


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

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

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


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

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

FILE *
SBDebugger::GetInputFileHandle ()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetInputFile().GetStream();
    return NULL;
}

FILE *
SBDebugger::GetOutputFileHandle ()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetOutputFile().GetStream();
    return NULL;
}

FILE *
SBDebugger::GetErrorFileHandle ()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetErrorFile().GetStream();
    return NULL;
}

SBCommandInterpreter
SBDebugger::GetCommandInterpreter ()
{
    LogSP 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)", 
                     m_opaque_sp.get(), sb_interpreter.get());

    return sb_interpreter;
}

void
SBDebugger::HandleCommand (const char *command)
{
    if (m_opaque_sp)
    {
        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
        Mutex::Locker api_locker;
        if (target_sp)
            api_locker.Lock(target_sp->GetAPIMutex());

        SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
        SBCommandReturnObject result;

        sb_interpreter.HandleCommand (command, result, false);

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

        if (m_opaque_sp->GetAsyncExecution() == false)
        {
            SBProcess process(GetCommandInterpreter().GetProcess ());
            ProcessSP process_sp (process.GetSP());
            if (process_sp)
            {
                EventSP event_sp;
                Listener &lldb_listener = m_opaque_sp->GetListener();
                while (lldb_listener.GetNextEventForBroadcaster (process_sp.get(), event_sp))
                {
                    SBEvent event(event_sp);
                    HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
                }
            }
        }
    }
}

SBListener
SBDebugger::GetListener ()
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

    if (log)
        log->Printf ("SBDebugger(%p)::GetListener () => SBListener(%p)", m_opaque_sp.get(),
                     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;

    Mutex::Locker api_locker (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 != NULL)
                ::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 != NULL)
                ::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,
                                         NULL);
}

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

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

bool
SBDebugger::StateIsRunningState (StateType state)
{
    LogSP 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)
{
    LogSP 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();
        FileSpec filename_spec (filename, true);
        OptionGroupPlatform platform_options (false);
        platform_options.SetPlatformName (platform_name);
        
        sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, 
                                                                    filename_spec, 
                                                                    target_triple, 
                                                                    add_dependent_modules, 
                                                                    &platform_options,
                                                                    target_sp);
    
        if (sb_error.Success())
            sb_target.SetSP (target_sp);
    }
    else
    {
        sb_error.SetErrorString("invalid target");
    }
    
    LogSP 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)", 
                     m_opaque_sp.get(), 
                     filename, 
                     target_triple,
                     platform_name,
                     add_dependent_modules,
                     sb_error.GetCString(),
                     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)
    {
        FileSpec file_spec (filename, true);
        TargetSP target_sp;
        const bool add_dependent_modules = true;
        Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, 
                                                                file_spec, 
                                                                target_triple, 
                                                                add_dependent_modules, 
                                                                NULL,
                                                                target_sp));
        sb_target.SetSP (target_sp);
    }
    
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple (filename=\"%s\", triple=%s) => SBTarget(%p)", 
                     m_opaque_sp.get(), filename, target_triple, target_sp.get());
    }

    return sb_target;
}

SBTarget
SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *arch_cstr)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

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

        error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, 
                                                           file, 
                                                           arch_cstr, 
                                                           add_dependent_modules, 
                                                           NULL, 
                                                           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)", 
                     m_opaque_sp.get(), filename, arch_cstr, target_sp.get());
    }

    return sb_target;
}

SBTarget
SBDebugger::CreateTarget (const char *filename)
{
    SBTarget sb_target;
    TargetSP target_sp;
    if (m_opaque_sp)
    {
        FileSpec file (filename, true);
        ArchSpec arch = Target::GetDefaultArchitecture ();
        Error error;
        const bool add_dependent_modules = true;

        PlatformSP platform_sp(m_opaque_sp->GetPlatformList().GetSelectedPlatform());
        error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, 
                                                           file, 
                                                           arch, 
                                                           add_dependent_modules, 
                                                           platform_sp,
                                                           target_sp);

        if (error.Success())
        {
            m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
            sb_target.SetSP (target_sp);
        }
    }
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)", 
                     m_opaque_sp.get(), filename, 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);
        }
    }

    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
    {
        log->Printf ("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", m_opaque_sp.get(), 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 (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 : NULL));
        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 ()
{
    LogSP 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", m_opaque_sp.get(),
                     target_sp.get(), sstr.GetData());
    }

    return sb_target;
}

void
SBDebugger::SetSelectedTarget (SBTarget &sb_target)
{
    LogSP 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", m_opaque_sp.get(),
                     target_sp.get(), sstr.GetData());
    }
}

void
SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::DispatchInput (baton=%p, data=\"%.*s\", size_t=%zu)", m_opaque_sp.get(),
                     baton, (int) data_len, (const char *) data, 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 ();
}
    
bool
SBDebugger::InputReaderIsTopReader (const lldb::SBInputReader &reader)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::InputReaderIsTopReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);

    if (m_opaque_sp && reader.IsValid())
    {
        InputReaderSP reader_sp (*reader);
        return m_opaque_sp->InputReaderIsTopReader (reader_sp);
    }

    return false;
}


void
SBDebugger::PushInputReader (SBInputReader &reader)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::PushInputReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);

    if (m_opaque_sp && reader.IsValid())
    {
        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
        Mutex::Locker api_locker;
        if (target_sp)
            api_locker.Lock(target_sp->GetAPIMutex());
        InputReaderSP reader_sp(*reader);
        m_opaque_sp->PushInputReader (reader_sp);
    }
}

void
SBDebugger::NotifyTopInputReader (InputReaderAction notification)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBDebugger(%p)::NotifyTopInputReader (%d)", m_opaque_sp.get(), notification);
        
    if (m_opaque_sp)
        m_opaque_sp->NotifyTopInputReader (notification);
}

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()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetInstanceName().AsCString();
    else
        return NULL;
}

SBError
SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name)
{
    UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController();

    Error err = root_settings_controller->SetVariable (var_name, 
                                                       value, 
                                                       eVarSetOperationAssign, 
                                                       true,
                                                       debugger_instance_name);
    SBError sb_error;
    sb_error.SetError (err);

    return sb_error;
}

SBStringList
SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name)
{
    SBStringList ret_value;
    SettableVariableType var_type;
    Error err;

    UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController();

    StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err);
    
    if (err.Success())
    {
        for (unsigned i = 0; i != value.GetSize(); ++i)
            ret_value.AppendString (value.GetStringAtIndex(i));
    }
    else
    {
        ret_value.AppendString (err.AsCString());
    }


    return ret_value;
}

uint32_t
SBDebugger::GetTerminalWidth () const
{
    if (m_opaque_sp)
        return m_opaque_sp->GetTerminalWidth ();
    return 0;
}

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

const char *
SBDebugger::GetPrompt() const
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (log)
        log->Printf ("SBDebugger(%p)::GetPrompt () => \"%s\"", m_opaque_sp.get(), 
                     (m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));

    if (m_opaque_sp)
        return m_opaque_sp->GetPrompt ();
    return 0;
}

void
SBDebugger::SetPrompt (const char *prompt)
{
    if (m_opaque_sp)
        m_opaque_sp->SetPrompt (prompt);
}

    
ScriptLanguage 
SBDebugger::GetScriptLanguage() const
{
    if (m_opaque_sp)
        return m_opaque_sp->GetScriptLanguage ();
    return eScriptLanguageNone;
}

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

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

bool
SBDebugger::GetUseExternalEditor ()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetUseExternalEditor ();
    return 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: %llu)", name, id);
    }
    else
        strm.PutCString ("No value");
    
    return true;
}

user_id_t
SBDebugger::GetID()
{
    if (m_opaque_sp)
        return m_opaque_sp->GetID();
    return LLDB_INVALID_UID;
}


SBError
SBDebugger::SetCurrentPlatform (const char *platform_name)
{
    SBError sb_error;
    if (m_opaque_sp)
    {
        PlatformSP platform_sp (Platform::Create (platform_name, sb_error.ref()));
        
        if (platform_sp)
        {
            bool make_selected = true;
            m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected);
        }
    }
    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
{
    if (m_opaque_sp)
        return m_opaque_sp->GetCloseInputOnEOF ();
    return 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::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() == false)
        return SBTypeSummary();
    return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
}
#endif // LLDB_DISABLE_PYTHON

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

#ifndef LLDB_DISABLE_PYTHON
SBTypeSynthetic
SBDebugger::GetSyntheticForType (SBTypeNameSpecifier type_name)
{
    if (type_name.IsValid() == false)
        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, NULL, 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);
    }
}


