//===-- 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/Core/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/ThreadPlanContinue.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;
    int 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->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()
    {
    }


    bool
    Execute
    (
        Args& command,
        CommandContext *context,
        CommandInterpreter *interpreter,
        CommandReturnObject &result
    )
    {
        if (command.GetArgumentCount() == 0)
        {
            ExecutionContext exe_ctx(context->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;
};


typedef 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 (Args& command,
             CommandContext *context,
             CommandInterpreter *interpreter,
             CommandReturnObject &result)
    {
        Process *process = context->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);
                    if (new_plan)
                    {
                        ThreadPlanStepInRange *real_plan = dynamic_cast<ThreadPlanStepInRange *> (new_plan);
                        if (real_plan)
                        {
                            if (m_options.m_avoid_no_debug)
                            {
                                real_plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
                            }
                            else
                            {
                                real_plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
                            }
                        }
                    }
                }
                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);
                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[] =
{
{ 0, true, "avoid_no_debug", 'a', required_argument,       NULL, 0, "<avoid_no_debug>",        "Should step-in step over functions with no debug information"},
{ 0, true, "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 (Args& command,
             CommandContext *context,
             CommandInterpreter *interpreter,
             CommandReturnObject &result)
    {
        bool synchronous_execution = interpreter->GetSynchronous ();

        if (!context->GetTarget())
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Process *process = context->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 (Args& command,
             CommandContext *context,
             CommandInterpreter *interpreter,
             CommandReturnObject &result)
    {
        bool synchronous_execution = interpreter->GetSynchronous ();

        if (!context->GetTarget())
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Process *process = context->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[] =
{
{ 0, true, "frame", 'f', required_argument,       NULL, 0, "<frame>",        "Frame index for until operation - defaults to 0"},
{ 0, true, "thread", 't', required_argument,       NULL, 0, "<thread>",      "Thread index for the thread for until operation"},
{ 0, true, "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 (Args& command,
             CommandContext *context,
             CommandInterpreter *interpreter,
             CommandReturnObject &result)
    {
        Process *process = context->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
//-------------------------------------------------------------------------

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

CommandObjectThreadList::~CommandObjectThreadList()
{
}

bool
CommandObjectThreadList::Execute
(
    Args& command,
    CommandContext *context,
    CommandInterpreter *interpreter,
    CommandReturnObject &result
)
{
    StreamString &strm = result.GetOutputStream();
    result.SetStatus (eReturnStatusSuccessFinishNoResult);
    ExecutionContext exe_ctx(context->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 (CommandObjectSP (new CommandObjectThreadBacktrace ()), "backtrace", interpreter);
    LoadSubCommand (CommandObjectSP (new CommandObjectThreadContinue ()), "continue", interpreter);
    LoadSubCommand (CommandObjectSP (new CommandObjectThreadList ()), "list", interpreter);
    LoadSubCommand (CommandObjectSP (new CommandObjectThreadSelect ()), "select", interpreter);
    LoadSubCommand (CommandObjectSP (new CommandObjectThreadUntil ()), "until", interpreter);
    LoadSubCommand (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)),
                    "step-in", interpreter);

    LoadSubCommand (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)),
                    "step-out", interpreter);

    LoadSubCommand (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)),
                    "step-over", interpreter);

    LoadSubCommand (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)),
                    "step-inst", interpreter);
    LoadSubCommand (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)),
                    "step-inst-over", interpreter);
}

CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
{
}


