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

#include "CommandObjectThread.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Core/State.h"
#include "lldb/Core/SourceManager.h"

#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"

#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/LineEntry.h"

using namespace lldb;
using namespace lldb_private;


bool
lldb_private::DisplayThreadInfo
(
    CommandInterpreter &interpreter,
    Stream &strm,
    Thread *thread,
    bool only_threads_with_stop_reason,
    bool show_source
)
{
    if (thread)
    {
        if (only_threads_with_stop_reason)
        {
            StopReason thread_stop_reason = eStopReasonNone;
            Thread::StopInfo thread_stop_info;
            if (thread->GetStopInfo(&thread_stop_info))
            {
                thread_stop_reason = thread_stop_info.GetStopReason();
                if (thread_stop_reason == eStopReasonNone)
                    return false;
            }
        }

        strm.Indent();
        strm.Printf("%c ", thread->GetProcess().GetThreadList().GetCurrentThread().get() == thread ? '*' : ' ');

        // Show one frame with only the first showing source
        if (show_source)
        {
            DisplayFramesForExecutionContext (thread,
                                              interpreter,
                                              strm,
                                              true,
                                              0,    // Start at first frame
                                              1,    // Number of frames to show
                                              false,// Don't show the frame info since we already displayed most of it above...
                                              1,    // Show source for the first frame
                                              3,    // lines of source context before
                                              3);   // lines of source context after
        }
        else
        {
            thread->DumpInfo (strm,
                              true, // Dump the stop reason?
                              true, // Dump the thread name?
                              true, // Dump the queue name?
                              0);   // Display context info for stack frame zero

            strm.EOL();
        }

        return true;
    }
    return false;
}

size_t
lldb_private::DisplayThreadsInfo
(
    CommandInterpreter &interpreter,
    ExecutionContext *exe_ctx,
    CommandReturnObject &result,
    bool only_threads_with_stop_reason,
    bool show_source
)
{
    StreamString strm;

    size_t num_thread_infos_dumped = 0;

    if (!exe_ctx->process)
        return 0;

    const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
    if (num_threads > 0)
    {

        for (uint32_t i = 0; i < num_threads; i++)
        {
            Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
            if (thread)
            {
                if (DisplayThreadInfo (interpreter,
                                       strm,
                                       thread,
                                       only_threads_with_stop_reason,
                                       show_source))
                    ++num_thread_infos_dumped;
            }
        }
    }

    if (num_thread_infos_dumped > 0)
    {
        if (num_thread_infos_dumped < num_threads)
            result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);

        result.GetOutputStream().GetString().append(strm.GetString());
        result.SetStatus (eReturnStatusSuccessFinishNoResult);
    }
    return num_thread_infos_dumped;
}


size_t
lldb_private::DisplayFramesForExecutionContext
(
    Thread *thread,
    CommandInterpreter &interpreter,
    Stream& strm,
    bool ascending,
    uint32_t first_frame,
    uint32_t num_frames,
    bool show_frame_info,
    uint32_t num_frames_with_source,
    uint32_t source_lines_before,
    uint32_t source_lines_after
)
{
    if (thread == NULL)
        return 0;

    size_t num_frames_displayed = 0;

    if (num_frames == 0)
        return 0;
    
    thread->DumpInfo (strm,
                      true,     // Dump the stop reason?
                      true,     // Dump the thread name?
                      true,     // Dump the queue name?
                      0);       // Dump info for stack frame zero
    strm.EOL();
    strm.IndentMore();

    StackFrameSP frame_sp;
    uint32_t frame_idx = 0;

    if (ascending)
    {
        for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
        {
            frame_sp = thread->GetStackFrameAtIndex (frame_idx);
            if (frame_sp.get() == NULL)
                break;

            if (DisplayFrameForExecutionContext (thread,
                                                 frame_sp.get(),
                                                 interpreter,
                                                 strm,
                                                 show_frame_info,
                                                 num_frames_with_source > first_frame - frame_idx,
                                                 source_lines_before,
                                                 source_lines_after) == false)
                break;

            ++num_frames_displayed;
        }
    }
    else
    {
        for (frame_idx = first_frame + num_frames - 1; frame_idx >= first_frame; --frame_idx)
        {
            frame_sp = thread->GetStackFrameAtIndex (frame_idx);
            if (frame_sp == NULL)
                break;

            if (DisplayFrameForExecutionContext (thread,
                                                 frame_sp.get(),
                                                 interpreter,
                                                 strm,
                                                 show_frame_info,
                                                 num_frames_with_source > first_frame - frame_idx,
                                                 source_lines_before,
                                                 source_lines_after) == false)
                break;

            ++num_frames_displayed;
        }
    }
    strm.IndentLess();
    return num_frames_displayed;
}

bool
lldb_private::DisplayFrameForExecutionContext
(
    Thread *thread,
    StackFrame *frame,
    CommandInterpreter &interpreter,
    Stream& strm,
    bool show_frame_info,
    bool show_source,
    uint32_t source_lines_before,
    uint32_t source_lines_after
)
{
    // thread and frame must be filled in prior to calling this function
    if (thread && frame)
    {
        if (show_frame_info)
        {
            strm.Indent();
            frame->Dump (&strm, true);
            strm.EOL();
        }

        SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));

        if (show_source && sc.comp_unit && sc.line_entry.IsValid())
        {
            interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
                    sc.line_entry.file,
                    sc.line_entry.line,
                    3,
                    3,
                    "->",
                    &strm);

        }
        return true;
    }
    return false;
}


//-------------------------------------------------------------------------
// CommandObjectThreadBacktrace
//-------------------------------------------------------------------------

class CommandObjectThreadBacktrace : public CommandObject
{
public:

    CommandObjectThreadBacktrace () :
        CommandObject ("thread backtrace",
                       "Shows the stack for one or more threads.",
                       "thread backtrace [<thread-idx>] ...",
                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
        m_ascending (true)
    {
    }

    ~CommandObjectThreadBacktrace()
    {
    }


    virtual bool
    Execute
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        if (command.GetArgumentCount() == 0)
        {
            ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
            if (exe_ctx.thread)
            {
                bool show_frame_info = true;
                uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing
                if (DisplayFramesForExecutionContext (exe_ctx.thread,
                                                      interpreter,
                                                      result.GetOutputStream(),
                                                      m_ascending,
                                                      0,
                                                      UINT32_MAX,
                                                      show_frame_info,
                                                      num_frames_with_source,
                                                      3,
                                                      3))
                {
                    result.SetStatus (eReturnStatusSuccessFinishResult);
                }
            }
            else
            {
                result.AppendError ("invalid thread");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("backtrace doesn't take arguments (for now)");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
protected:
    bool m_ascending;
};


enum StepScope
{
    eStepScopeSource,
    eStepScopeInstruction
};

class CommandObjectThreadStepWithTypeAndScope : public CommandObject
{
public:

    class CommandOptions : public Options
    {
    public:

        CommandOptions () :
            Options()
        {
            // Keep default values of all options in one place: ResetOptionValues ()
            ResetOptionValues ();
        }

        virtual
        ~CommandOptions ()
        {
        }

        virtual Error
        SetOptionValue (int option_idx, const char *option_arg)
        {
            Error error;
            char short_option = (char) m_getopt_table[option_idx].val;

            switch (short_option)
            {
                case 'a':
                {
                    bool success;
                    m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
                    if (!success)
                        error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
                }
                break;
                case 'm':
                {
                    bool found_one = false;
                    OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
                    m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
                    if (!found_one)
                        error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
                }
                break;
                default:
                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
                    break;

            }
            return error;
        }

        void
        ResetOptionValues ()
        {
            Options::ResetOptionValues();
            m_avoid_no_debug = true;
            m_run_mode = eOnlyDuringStepping;
        }

        const lldb::OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        // Options table: Required for subclasses of Options.

        static lldb::OptionDefinition g_option_table[];

        // Instance variables to hold the values for command options.
        bool m_avoid_no_debug;
        RunMode m_run_mode;
    };

    CommandObjectThreadStepWithTypeAndScope (const char *name,
                         const char *help,
                         const char *syntax,
                         uint32_t flags,
                         StepType step_type,
                         StepScope step_scope) :
        CommandObject (name, help, syntax, flags),
        m_step_type (step_type),
        m_step_scope (step_scope),
        m_options ()
    {
    }

    virtual
    ~CommandObjectThreadStepWithTypeAndScope ()
    {
    }

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

    virtual bool
    Execute 
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        Process *process = interpreter.GetDebugger().GetExecutionContext().process;
        bool synchronous_execution = interpreter.GetSynchronous();

        if (process == NULL)
        {
            result.AppendError ("need a valid process to step");
            result.SetStatus (eReturnStatusFailed);

        }
        else
        {
            const uint32_t num_threads = process->GetThreadList().GetSize();
            Thread *thread = NULL;

            if (command.GetArgumentCount() == 0)
            {
                thread = process->GetThreadList().GetCurrentThread().get();
                if (thread == NULL)
                {
                    result.AppendError ("no current thread in process");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
                uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
                if (step_thread_idx == LLDB_INVALID_INDEX32)
                {
                    result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
                if (thread == NULL)
                {
                    result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 
                                                  step_thread_idx, 0, num_threads);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }

            const bool abort_other_plans = false;
            const lldb::RunMode stop_other_threads = m_options.m_run_mode;
            
            // This is a bit unfortunate, but not all the commands in this command object support
            // only while stepping, so I use the bool for them.
            bool bool_stop_other_threads;
            if (m_options.m_run_mode == eAllThreads)
                bool_stop_other_threads = false;
            else
                bool_stop_other_threads = true;

            if (m_step_type == eStepTypeInto)
            {
                StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
                ThreadPlan *new_plan;

                if (frame->HasDebugInformation ())
                {
                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 
                                                                    frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
                                                                    stop_other_threads,
                                                                    m_options.m_avoid_no_debug);
                }
                else
                    new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);

                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                process->Resume ();
            }
            else if (m_step_type == eStepTypeOver)
            {
                StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
                ThreadPlan *new_plan;

                if (frame->HasDebugInformation())
                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 
                                                                    m_step_type, 
                                                                    frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
                                                                    stop_other_threads,
                                                                    false);
                else
                    new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 
                                                                                abort_other_plans, 
                                                                                bool_stop_other_threads);

                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
                // Maybe there should be a parameter to control this.
                new_plan->SetOkayToDiscard(false);

                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                process->Resume ();
            }
            else if (m_step_type == eStepTypeTrace)
            {
                thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                process->Resume ();
            }
            else if (m_step_type == eStepTypeTraceOver)
            {
                thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                process->Resume ();
            }
            else if (m_step_type == eStepTypeOut)
            {
                ThreadPlan *new_plan;

                new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
                // Maybe there should be a parameter to control this.
                new_plan->SetOkayToDiscard(false);

                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                process->Resume ();
            }
            else
            {
                result.AppendError ("step type is not supported");
                result.SetStatus (eReturnStatusFailed);
            }
            if (synchronous_execution)
            {
                StateType state = process->WaitForProcessToStop (NULL);
                
                //EventSP event_sp;
                //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
                //while (! StateIsStoppedState (state))
                //  {
                //    state = process->WaitForStateChangedEvents (NULL, event_sp);
                //  }
                process->GetThreadList().SetCurrentThreadByID (thread->GetID());
                result.SetDidChangeProcessState (true);
                result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
                result.SetStatus (eReturnStatusSuccessFinishNoResult);
            }
        }
        return result.Succeeded();
    }

protected:
    StepType m_step_type;
    StepScope m_step_scope;
    CommandOptions m_options;
};

static lldb::OptionEnumValueElement
g_tri_running_mode[] =
{
{ eOnlyThisThread,     "thisThread",    "Run only this thread"},
{ eAllThreads,         "allThreads",    "Run all threads"},
{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
{ 0, NULL, NULL }
};

static lldb::OptionEnumValueElement
g_duo_running_mode[] =
{
{ eOnlyThisThread,     "thisThread",    "Run only this thread"},
{ eAllThreads,         "allThreads",    "Run all threads"},
{ 0, NULL, NULL }
};

lldb::OptionDefinition
CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "avoid_no_debug", 'a', required_argument, NULL,               0, "<avoid_no_debug>", "Should step-in step over functions with no debug information"},
{ LLDB_OPT_SET_1, false, "run_mode",       'm', required_argument, g_tri_running_mode, 0, "<run_mode>",       "Determine how to run other threads while stepping this one"},
{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
};


//-------------------------------------------------------------------------
// CommandObjectThreadContinue
//-------------------------------------------------------------------------

class CommandObjectThreadContinue : public CommandObject
{
public:

    CommandObjectThreadContinue () :
        CommandObject ("thread continue",
                       "Continues execution of one or more threads in an active process.",
                       "thread continue <thread-index> [<thread-index> ...]",
                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
    {
    }


    virtual
    ~CommandObjectThreadContinue ()
    {
    }

    virtual bool
    Execute
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        bool synchronous_execution = interpreter.GetSynchronous ();

        if (!interpreter.GetDebugger().GetCurrentTarget().get())
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Process *process = interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError ("no process exists. Cannot continue");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        StateType state = process->GetState();
        if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
        {
            const uint32_t num_threads = process->GetThreadList().GetSize();
            uint32_t idx;
            const size_t argc = command.GetArgumentCount();
            if (argc > 0)
            {
                std::vector<uint32_t> resume_thread_indexes;
                for (uint32_t i=0; i<argc; ++i)
                {
                    idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
                    if (idx < num_threads)
                        resume_thread_indexes.push_back(idx);
                    else
                        result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
                }

                if (resume_thread_indexes.empty())
                {
                    result.AppendError ("no valid thread indexes were specified");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                else
                {
                    result.AppendMessage ("Resuming thread ");
                    for (idx=0; idx<num_threads; ++idx)
                    {
                        Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
                        if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
                        {
                            result.AppendMessageWithFormat ("%u ", idx);
                            thread->SetResumeState (eStateRunning);
                        }
                        else
                        {
                            thread->SetResumeState (eStateSuspended);
                        }
                    }
                    result.AppendMessageWithFormat ("in process %i\n", process->GetID());
                }
            }
            else
            {
                Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
                if (current_thread == NULL)
                {
                    result.AppendError ("the process doesn't have a current thread");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
                // Set the actions that the threads should each take when resuming
                for (idx=0; idx<num_threads; ++idx)
                {
                    Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
                    if (thread == current_thread)
                    {
                        result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
                        thread->SetResumeState (eStateRunning);
                    }
                    else
                    {
                        thread->SetResumeState (eStateSuspended);
                    }
                }
            }

            Error error (process->Resume());
            if (error.Success())
            {
                result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
                if (synchronous_execution)
                {
                    StateType state = process->WaitForProcessToStop (NULL);

                    result.SetDidChangeProcessState (true);
                    result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
                }
                else
                {
                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
                }
            }
            else
            {
                result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
                                          StateAsCString(state));
            result.SetStatus (eReturnStatusFailed);
        }

        return result.Succeeded();
    }

};

//-------------------------------------------------------------------------
// CommandObjectThreadUntil
//-------------------------------------------------------------------------

class CommandObjectThreadUntil : public CommandObject
{
public:

    class CommandOptions : public Options
    {
    public:
        uint32_t m_thread_idx;
        uint32_t m_frame_idx;

        CommandOptions () :
            Options(),
            m_thread_idx(LLDB_INVALID_THREAD_ID),
            m_frame_idx(LLDB_INVALID_FRAME_ID)
        {
            // Keep default values of all options in one place: ResetOptionValues ()
            ResetOptionValues ();
        }

        virtual
        ~CommandOptions ()
        {
        }

        virtual Error
        SetOptionValue (int option_idx, const char *option_arg)
        {
            Error error;
            char short_option = (char) m_getopt_table[option_idx].val;

            switch (short_option)
            {
                case 't':
                {
                    uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
                    if (m_thread_idx == LLDB_INVALID_INDEX32)
                    {
                        error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
                    }
                }
                break;
                case 'f':
                {
                    m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
                    if (m_frame_idx == LLDB_INVALID_FRAME_ID)
                    {
                        error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
                    }
                }
                break;
                case 'm':
                {
                    bool found_one = false;
                    OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
                    lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);

                    if (!found_one)
                        error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
                    else if (run_mode == eAllThreads)
                        m_stop_others = false;
                    else
                        m_stop_others = true;
        
                }
                break;
                default:
                    error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
                    break;

            }
            return error;
        }

        void
        ResetOptionValues ()
        {
            Options::ResetOptionValues();
            m_thread_idx = LLDB_INVALID_THREAD_ID;
            m_frame_idx = 0;
            m_stop_others = false;
        }

        const lldb::OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        uint32_t m_step_thread_idx;
        bool m_stop_others;

        // Options table: Required for subclasses of Options.

        static lldb::OptionDefinition g_option_table[];

        // Instance variables to hold the values for command options.
    };

    CommandObjectThreadUntil () :
        CommandObject ("thread until",
                       "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
                       "thread until [<cmd-options>] <line-number>",
                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
        m_options ()
    {
    }


    virtual
    ~CommandObjectThreadUntil ()
    {
    }

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

    virtual bool
    Execute 
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        bool synchronous_execution = interpreter.GetSynchronous ();

        if (!interpreter.GetDebugger().GetCurrentTarget().get())
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Process *process = interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError ("need a valid process to step");
            result.SetStatus (eReturnStatusFailed);

        }
        else
        {
            Thread *thread = NULL;
            uint32_t line_number;

            if (command.GetArgumentCount() != 1)
            {
                result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
            if (line_number == UINT32_MAX)
            {
                result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
            {
                thread = process->GetThreadList().GetCurrentThread().get();
            }
            else
            {
                thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
            }

            if (thread == NULL)
            {
                const uint32_t num_threads = process->GetThreadList().GetSize();
                result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            const bool abort_other_plans = true;

            StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
            if (frame == NULL)
            {

                result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
                result.SetStatus (eReturnStatusFailed);
                return false;
            }

            ThreadPlan *new_plan;

            if (frame->HasDebugInformation ())
            {
                // Finally we got here...  Translate the given line number to a bunch of addresses:
                SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
                LineTable *line_table = NULL;
                if (sc.comp_unit)
                    line_table = sc.comp_unit->GetLineTable();

                if (line_table == NULL)
                {
                    result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
                                                 m_options.m_frame_idx, m_options.m_thread_idx);
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }

                LineEntry function_start;
                uint32_t index_ptr = 0, end_ptr;
                std::vector<addr_t> address_list;

                // Find the beginning & end index of the
                AddressRange fun_addr_range = sc.function->GetAddressRange();
                Address fun_start_addr = fun_addr_range.GetBaseAddress();
                line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);

                Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
                line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);

                while (index_ptr <= end_ptr)
                {
                    LineEntry line_entry;
                    index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
                    if (index_ptr == UINT32_MAX)
                        break;

                    addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
                    if (address != LLDB_INVALID_ADDRESS)
                        address_list.push_back (address);
                    index_ptr++;
                }

                new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others);
                new_plan->SetOkayToDiscard(false);
            }
            else
            {
                result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
                result.SetStatus (eReturnStatusFailed);
                return false;

            }

            process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
            Error error (process->Resume ());
            if (error.Success())
            {
                result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
                if (synchronous_execution)
                {
                    StateType state = process->WaitForProcessToStop (NULL);

                    result.SetDidChangeProcessState (true);
                    result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
                }
                else
                {
                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
                }
            }
            else
            {
                result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
                result.SetStatus (eReturnStatusFailed);
            }

        }
        return result.Succeeded();
    }
protected:
    CommandOptions m_options;

};

lldb::OptionDefinition
CommandObjectThreadUntil::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "frame",   'f', required_argument, NULL,               0, "<frame>",   "Frame index for until operation - defaults to 0"},
{ LLDB_OPT_SET_1, false, "thread",  't', required_argument, NULL,               0, "<thread>",  "Thread index for the thread for until operation"},
{ LLDB_OPT_SET_1, false, "run_mode",'m', required_argument, g_duo_running_mode, 0, "<run_mode>","Determine how to run other threads while stepping this one"},
{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
};


//-------------------------------------------------------------------------
// CommandObjectThreadSelect
//-------------------------------------------------------------------------

class CommandObjectThreadSelect : public CommandObject
{
public:

    CommandObjectThreadSelect () :
        CommandObject ("thread select",
                         "Selects a threads as the currently active thread.",
                         "thread select <thread-index>",
                         eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
    {
    }


    virtual
    ~CommandObjectThreadSelect ()
    {
    }

    virtual bool
    Execute 
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        Process *process = interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError ("no process");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else if (command.GetArgumentCount() != 1)
        {
            result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);

        Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
        if (new_thread == NULL)
        {
            result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
        
        DisplayThreadInfo (interpreter,
                           result.GetOutputStream(),
                           new_thread,
                           false,
                           true);

        return result.Succeeded();
    }

};


//-------------------------------------------------------------------------
// CommandObjectThreadList
//-------------------------------------------------------------------------

class CommandObjectThreadList : public CommandObject
{
public:


    CommandObjectThreadList ():
        CommandObject ("thread list",
                       "Shows a summary of all current threads in a process.",
                       "thread list",
                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
    {
    }

    ~CommandObjectThreadList()
    {
    }

    bool
    Execute
    (
        CommandInterpreter &interpreter,
        Args& command,
        CommandReturnObject &result
    )
    {
        StreamString &strm = result.GetOutputStream();
        result.SetStatus (eReturnStatusSuccessFinishNoResult);
        ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
        if (exe_ctx.process)
        {
            const StateType state = exe_ctx.process->GetState();

            if (StateIsStoppedState(state))
            {
                if (state == eStateExited)
                {
                    int exit_status = exe_ctx.process->GetExitStatus();
                    const char *exit_description = exe_ctx.process->GetExitDescription();
                    strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
                                          exe_ctx.process->GetID(),
                                          exit_status,
                                          exit_status,
                                          exit_description ? exit_description : "");
                }
                else
                {
                    strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
                    if (exe_ctx.thread == NULL)
                        exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
                    if (exe_ctx.thread != NULL)
                    {
                        DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
                    }
                    else
                    {
                        result.AppendError ("no valid thread found in current process");
                        result.SetStatus (eReturnStatusFailed);
                    }
                }
            }
            else
            {
                result.AppendError ("process is currently running");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        else
        {
            result.AppendError ("no current location or status available");
            result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
};

//-------------------------------------------------------------------------
// CommandObjectMultiwordThread
//-------------------------------------------------------------------------

CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
    CommandObjectMultiword ("thread",
                            "A set of commands for operating on one or more thread within a running process.",
                            "thread <subcommand> [<subcommand-options>]")
{
    LoadSubCommand (interpreter, "backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace ()));
    LoadSubCommand (interpreter, "continue",   CommandObjectSP (new CommandObjectThreadContinue ()));
    LoadSubCommand (interpreter, "list",       CommandObjectSP (new CommandObjectThreadList ()));
    LoadSubCommand (interpreter, "select",     CommandObjectSP (new CommandObjectThreadSelect ()));
    LoadSubCommand (interpreter, "until",      CommandObjectSP (new CommandObjectThreadUntil ()));
    LoadSubCommand (interpreter, "step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
                                                    "thread step-in",
                                                     "Source level single step in in specified thread (current thread, if none specified).",
                                                     "thread step-in [<thread-id>]",
                                                     eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
                                                     eStepTypeInto,
                                                     eStepScopeSource)));
    
    LoadSubCommand (interpreter, "step-out",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
                                                                                      "Source level single step out in specified thread (current thread, if none specified).",
                                                                                      "thread step-out [<thread-id>]",
                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
                                                                                      eStepTypeOut,
                                                                                      eStepScopeSource)));

    LoadSubCommand (interpreter, "step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
                                                                                      "Source level single step over in specified thread (current thread, if none specified).",
                                                                                      "thread step-over [<thread-id>]",
                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
                                                                                      eStepTypeOver,
                                                                                      eStepScopeSource)));

    LoadSubCommand (interpreter, "step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
                                                                                      "Single step one instruction in specified thread (current thread, if none specified).",
                                                                                      "thread step-inst [<thread-id>]",
                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
                                                                                      eStepTypeTrace,
                                                                                      eStepScopeInstruction)));

    LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
                                                                                      "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
                                                                                      "thread step-inst-over [<thread-id>]",
                                                                                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
                                                                                      eStepTypeTraceOver,
                                                                                      eStepScopeInstruction)));
}

CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
{
}


