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

// C Includes
// C++ Includes


#include "CommandObjectBreakpointCommand.h"
#include "CommandObjectBreakpoint.h"

#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/State.h"

using namespace lldb;
using namespace lldb_private;

//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandAdd
//-------------------------------------------------------------------------


class CommandObjectBreakpointCommandAdd :
    public CommandObjectParsed,
    public IOHandlerDelegateMultiline
{
public:

    CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "add",
                             "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
                             "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
                             NULL),
        IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
        m_options (interpreter)
    {
        SetHelpLong (
"\nGeneral information about entering breakpoint commands\n\
------------------------------------------------------\n\
\n\
This command will cause you to be prompted to enter the command or set of\n\
commands you wish to be executed when the specified breakpoint is hit. You\n\
will be told to enter your command(s), and will see a '> 'prompt. Because\n\
you can enter one or many commands to be executed when a breakpoint is hit,\n\
you will continue to be prompted after each new-line that you enter, until you\n\
enter the word 'DONE', which will cause the commands you have entered to be\n\
stored with the breakpoint and executed when the breakpoint is hit.\n\
\n\
Syntax checking is not necessarily done when breakpoint commands are entered.\n\
An improperly written breakpoint command will attempt to get executed when the\n\
breakpoint gets hit, and usually silently fail.  If your breakpoint command does\n\
not appear to be getting executed, go back and check your syntax.\n\
\n\
Special information about PYTHON breakpoint commands\n\
----------------------------------------------------\n\
\n\
You may enter either one line of Python, multiple lines of Python (including\n\
function definitions), or specify a Python function in a module that has already,\n\
or will be imported.  If you enter a single line of Python, that will be passed\n\
to the Python interpreter 'as is' when the breakpoint gets hit.  If you enter\n\
function definitions, they will be passed to the Python interpreter as soon as\n\
you finish entering the breakpoint command, and they can be called later (don't\n\
forget to add calls to them, if you want them called when the breakpoint is\n\
hit).  If you enter multiple lines of Python that are not function definitions,\n\
they will be collected into a new, automatically generated Python function, and\n\
a call to the newly generated function will be attached to the breakpoint.\n\
\n\
\n\
This auto-generated function is passed in three arguments:\n\
\n\
    frame:  a lldb.SBFrame object for the frame which hit breakpoint.\n\
    bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
            location that was hit.\n\
    dict:   the python session dictionary hit.\n\
\n\
When specifying a python function with the --python-function option, you need\n\
to supply the function name prepended by the module name. So if you import a\n\
module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
specify the option as:\n\
\n\
    --python-function myutils.breakpoint_callback\n\
\n\
The function itself must have the following prototype:\n\
\n\
def breakpoint_callback(frame, bp_loc, dict):\n\
  # Your code goes here\n\
\n\
The arguments are the same as the 3 auto generation function arguments listed\n\
above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
can get you to the thread (frame.GetThread()), the thread can get you to the\n\
process (thread.GetProcess()), and the process can get you back to the target\n\
(process.GetTarget()).\n\
\n\
Important Note: Because loose Python code gets collected into functions, if you\n\
want to access global variables in the 'loose' code, you need to specify that\n\
they are global, using the 'global' keyword.  Be sure to use correct Python\n\
syntax, including indentation, when entering Python breakpoint commands.\n\
\n\
As a third option, you can pass the name of an already existing Python function\n\
and that function will be attached to the breakpoint. It will get passed the\n\
frame and bp_loc arguments mentioned above.\n\
\n\
Example Python one-line breakpoint command:\n\
\n\
(lldb) breakpoint command add -s python 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> print \"Hit this breakpoint!\"\n\
> DONE\n\
\n\
As a convenience, this also works for a short Python one-liner:\n\
(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
(lldb) run\n\
Launching '.../a.out'  (x86_64)\n\
(lldb) Fri Sep 10 12:17:45 2010\n\
Process 21778 Stopped\n\
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
  36   	\n\
  37   	int c(int val)\n\
  38   	{\n\
  39 ->	    return val + 3;\n\
  40   	}\n\
  41   	\n\
  42   	int main (int argc, char const *argv[])\n\
(lldb)\n\
\n\
Example multiple line Python breakpoint command, using function definition:\n\
\n\
(lldb) breakpoint command add -s python 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> def breakpoint_output (bp_no):\n\
>     out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
>     print out_string\n\
>     return True\n\
> breakpoint_output (1)\n\
> DONE\n\
\n\
\n\
Example multiple line Python breakpoint command, using 'loose' Python:\n\
\n\
(lldb) breakpoint command add -s p 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> global bp_count\n\
> bp_count = bp_count + 1\n\
> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
> DONE\n\
\n\
In this case, since there is a reference to a global variable,\n\
'bp_count', you will also need to make sure 'bp_count' exists and is\n\
initialized:\n\
\n\
(lldb) script\n\
>>> bp_count = 0\n\
>>> quit()\n\
\n\
(lldb)\n\
\n\
\n\
Your Python code, however organized, can optionally return a value.\n\
If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
to which the code is associated. Returning anything other than False, or even\n\
returning None, or even omitting a return statement entirely, will cause\n\
LLDB to stop.\n\
\n\
Final Note:  If you get a warning that no breakpoint command was generated, but\n\
you did not get any syntax errors, you probably forgot to add a call to your\n\
functions.\n\
\n\
Special information about debugger command breakpoint commands\n\
--------------------------------------------------------------\n\
\n\
You may enter any debugger command, exactly as you would at the debugger prompt.\n\
You may enter as many debugger commands as you like, but do NOT enter more than\n\
one command per line.\n" );

        CommandArgumentEntry arg;
        CommandArgumentData bp_id_arg;

        // Define the first (and only) variant of this arg.
        bp_id_arg.arg_type = eArgTypeBreakpointID;
        bp_id_arg.arg_repetition = eArgRepeatOptional;

        // There is only one variant this argument could be; put it into the argument entry.
        arg.push_back (bp_id_arg);

        // Push the data for the first argument into the m_arguments vector.
        m_arguments.push_back (arg);
    }

    virtual
    ~CommandObjectBreakpointCommandAdd () {}

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

    virtual void
    IOHandlerActivated (IOHandler &io_handler)
    {
        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
        if (output_sp)
        {
            output_sp->PutCString(g_reader_instructions);
            output_sp->Flush();
        }
    }
    
    
    virtual void
    IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
    {
        io_handler.SetIsDone(true);
        
        std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
        for (BreakpointOptions *bp_options : *bp_options_vec)
        {
            if (!bp_options)
                continue;
                    
            std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
            if (data_ap.get())
            {
                data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
                BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
                bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
            }
        }
    }
    
    void
    CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
                                             CommandReturnObject &result)
    {
        m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
                                                    *this,          // IOHandlerDelegate
                                                    true,           // Run IOHandler in async mode
                                                    &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
    }
    
    /// Set a one-liner as the callback for the breakpoint.
    void 
    SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
                                  const char *oneliner)
    {
        for (auto bp_options : bp_options_vec)
        {
            std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());

            // It's necessary to set both user_source and script_source to the oneliner.
            // The former is used to generate callback description (as in breakpoint command list)
            // while the latter is used for Python to interpret during the actual callback.
            data_ap->user_source.AppendString (oneliner);
            data_ap->script_source.assign (oneliner);
            data_ap->stop_on_error = m_options.m_stop_on_error;

            BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
            bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
        }
        return;
    }
    
    static bool
    BreakpointOptionsCallbackFunction (void *baton,
                                       StoppointCallbackContext *context, 
                                       lldb::user_id_t break_id,
                                       lldb::user_id_t break_loc_id)
    {
        bool ret_value = true;
        if (baton == NULL)
            return true;
        
        
        BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
        StringList &commands = data->user_source;
        
        if (commands.GetSize() > 0)
        {
            ExecutionContext exe_ctx (context->exe_ctx_ref);
            Target *target = exe_ctx.GetTargetPtr();
            if (target)
            {
                CommandReturnObject result;
                Debugger &debugger = target->GetDebugger();
                // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
                // if the debugger is set up that way.
                    
                StreamSP output_stream (debugger.GetAsyncOutputStream());
                StreamSP error_stream (debugger.GetAsyncErrorStream());
                result.SetImmediateOutputStream (output_stream);
                result.SetImmediateErrorStream (error_stream);
        
                CommandInterpreterRunOptions options;
                options.SetStopOnContinue(true);
                options.SetStopOnError (data->stop_on_error);
                options.SetEchoCommands (true);
                options.SetPrintResults (true);
                options.SetAddToHistory (false);

                debugger.GetCommandInterpreter().HandleCommands (commands,
                                                                 &exe_ctx,
                                                                 options,
                                                                 result);
                result.GetImmediateOutputStream()->Flush();
                result.GetImmediateErrorStream()->Flush();
           }
        }
        return ret_value;
    }    

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_use_commands (false),
            m_use_script_language (false),
            m_script_language (eScriptLanguageNone),
            m_use_one_liner (false),
            m_one_liner(),
            m_function_name()
        {
        }

        virtual
        ~CommandOptions () {}

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

            switch (short_option)
            {
            case 'o':
                m_use_one_liner = true;
                m_one_liner = option_arg;
                break;

            case 's':
                m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, 
                                                                                     g_option_table[option_idx].enum_values, 
                                                                                     eScriptLanguageNone,
                                                                                     error);

                if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
                {
                    m_use_script_language = true;
                }
                else
                {
                    m_use_script_language = false;
                }          
                break;

            case 'e':
                {
                    bool success = false;
                    m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
                    if (!success)
                        error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
                }
                break;
                    
            case 'F':
                {
                    m_use_one_liner = false;
                    m_use_script_language = true;
                    m_function_name.assign(option_arg);
                }
                break;

            case 'D':
                m_use_dummy = true;
                break;

            default:
                break;
            }
            return error;
        }
        void
        OptionParsingStarting ()
        {
            m_use_commands = true;
            m_use_script_language = false;
            m_script_language = eScriptLanguageNone;

            m_use_one_liner = false;
            m_stop_on_error = true;
            m_one_liner.clear();
            m_function_name.clear();
            m_use_dummy = false;
        }

        const OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        // Options table: Required for subclasses of Options.

        static OptionDefinition g_option_table[];

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

        bool m_use_commands;
        bool m_use_script_language;
        lldb::ScriptLanguage m_script_language;

        // Instance variables to hold the values for one_liner options.
        bool m_use_one_liner;
        std::string m_one_liner;
        bool m_stop_on_error;
        std::string m_function_name;
        bool m_use_dummy;
    };

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);

        if (target == NULL)
        {
            result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        const BreakpointList &breakpoints = target->GetBreakpointList();
        size_t num_breakpoints = breakpoints.GetSize();

        if (num_breakpoints == 0)
        {
            result.AppendError ("No breakpoints exist to have commands added");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        if (m_options.m_use_script_language == false && m_options.m_function_name.size())
        {
            result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        
        BreakpointIDList valid_bp_ids;
        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

        m_bp_options_vec.clear();
        
        if (result.Succeeded())
        {
            const size_t count = valid_bp_ids.GetSize();
            
            for (size_t i = 0; i < count; ++i)
            {
                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
                {
                    Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                    BreakpointOptions *bp_options = NULL;
                    if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
                    {
                        // This breakpoint does not have an associated location.
                        bp_options = bp->GetOptions();
                    }
                    else                    
                    {
                        BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
                        // This breakpoint does have an associated location.
                        // Get its breakpoint options.
                        if (bp_loc_sp)
                            bp_options = bp_loc_sp->GetLocationOptions();
                    }
                    if (bp_options)
                        m_bp_options_vec.push_back (bp_options);
                }
            }

            // If we are using script language, get the script interpreter
            // in order to set or collect command callback.  Otherwise, call
            // the methods associated with this object.
            if (m_options.m_use_script_language)
            {
                ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
                // Special handling for one-liner specified inline.
                if (m_options.m_use_one_liner)
                {
                    script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
                                                                 m_options.m_one_liner.c_str());
                }
                else if (m_options.m_function_name.size())
                {
                    script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
                                                                         m_options.m_function_name.c_str());
                }
                else
                {
                    script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
                                                                            result);
                }
            }
            else
            {
                // Special handling for one-liner specified inline.
                if (m_options.m_use_one_liner)
                    SetBreakpointCommandCallback (m_bp_options_vec,
                                                  m_options.m_one_liner.c_str());
                else
                    CollectDataForBreakpointCommandCallback (m_bp_options_vec,
                                                             result);
            }

        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
    std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
                                                        // collecting commands for.  In the CollectData... calls we need
                                                        // to hand this off to the IOHandler, which may run asynchronously.
                                                        // So we have to have some way to keep it alive, and not leak it.
                                                        // Making it an ivar of the command object, which never goes away
                                                        // achieves this.  Note that if we were able to run
                                                        // the same command concurrently in one interpreter we'd have to
                                                        // make this "per invocation".  But there are many more reasons
                                                        // why it is not in general safe to do that in lldb at present,
                                                        // so it isn't worthwhile to come up with a more complex mechanism
                                                        // to address this particular weakness right now.
    static const char *g_reader_instructions;

};

const char *
CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";

// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.

static OptionEnumValueElement
g_script_option_enumeration[4] =
{
    { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
    { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
    { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
    { 0,                      NULL,              NULL }
};

OptionDefinition
CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
        "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },

    { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
        "Specify whether breakpoint command execution should terminate on error." },

    { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
        "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},

    { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
        "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
    
    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},

    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandDelete
//-------------------------------------------------------------------------

class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
{
public:
    CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "delete",
                             "Delete the set of commands from a breakpoint.",
                             NULL),
        m_options (interpreter)
    {
        CommandArgumentEntry arg;
        CommandArgumentData bp_id_arg;

        // Define the first (and only) variant of this arg.
        bp_id_arg.arg_type = eArgTypeBreakpointID;
        bp_id_arg.arg_repetition = eArgRepeatPlain;

        // There is only one variant this argument could be; put it into the argument entry.
        arg.push_back (bp_id_arg);

        // Push the data for the first argument into the m_arguments vector.
        m_arguments.push_back (arg);
    }


    virtual
    ~CommandObjectBreakpointCommandDelete () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_use_dummy (false)
        {
        }

        virtual
        ~CommandOptions () {}

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

            switch (short_option)
            {
                case 'D':
                    m_use_dummy = true;
                    break;

                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_use_dummy = false;
        }

        const OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        // Options table: Required for subclasses of Options.

        static OptionDefinition g_option_table[];

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

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);

        if (target == NULL)
        {
            result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        const BreakpointList &breakpoints = target->GetBreakpointList();
        size_t num_breakpoints = breakpoints.GetSize();

        if (num_breakpoints == 0)
        {
            result.AppendError ("No breakpoints exist to have commands deleted");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        if (command.GetArgumentCount() == 0)
        {
            result.AppendError ("No breakpoint specified from which to delete the commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        BreakpointIDList valid_bp_ids;
        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

        if (result.Succeeded())
        {
            const size_t count = valid_bp_ids.GetSize();
            for (size_t i = 0; i < count; ++i)
            {
                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
                {
                    Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
                    {
                        BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
                        if (bp_loc_sp)
                            bp_loc_sp->ClearCallback();
                        else
                        {
                            result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 
                                                         cur_bp_id.GetBreakpointID(),
                                                         cur_bp_id.GetLocationID());
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                    }
                    else
                    {
                        bp->ClearCallback();
                    }
                }
            }
        }
        return result.Succeeded();
    }
private:
    CommandOptions m_options;
};

OptionDefinition
CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},

    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};


//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandList
//-------------------------------------------------------------------------

class CommandObjectBreakpointCommandList : public CommandObjectParsed
{
public:
    CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "list",
                             "List the script or set of commands to be executed when the breakpoint is hit.",
                              NULL)
    {
        CommandArgumentEntry arg;
        CommandArgumentData bp_id_arg;

        // Define the first (and only) variant of this arg.
        bp_id_arg.arg_type = eArgTypeBreakpointID;
        bp_id_arg.arg_repetition = eArgRepeatPlain;

        // There is only one variant this argument could be; put it into the argument entry.
        arg.push_back (bp_id_arg);

        // Push the data for the first argument into the m_arguments vector.
        m_arguments.push_back (arg);
    }

    virtual
    ~CommandObjectBreakpointCommandList () {}

protected:
    virtual bool
    DoExecute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();

        if (target == NULL)
        {
            result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        const BreakpointList &breakpoints = target->GetBreakpointList();
        size_t num_breakpoints = breakpoints.GetSize();

        if (num_breakpoints == 0)
        {
            result.AppendError ("No breakpoints exist for which to list commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        if (command.GetArgumentCount() == 0)
        {
            result.AppendError ("No breakpoint specified for which to list the commands");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        BreakpointIDList valid_bp_ids;
        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

        if (result.Succeeded())
        {
            const size_t count = valid_bp_ids.GetSize();
            for (size_t i = 0; i < count; ++i)
            {
                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
                {
                    Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                    
                    if (bp)
                    {
                        const BreakpointOptions *bp_options = NULL;
                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
                        {
                            BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
                            if (bp_loc_sp)
                                bp_options = bp_loc_sp->GetOptionsNoCreate();
                            else
                            {
                                result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 
                                                             cur_bp_id.GetBreakpointID(),
                                                             cur_bp_id.GetLocationID());
                                result.SetStatus (eReturnStatusFailed);
                                return false;
                            }
                        }
                        else
                        {
                            bp_options = bp->GetOptions();
                        }

                        if (bp_options)
                        {
                            StreamString id_str;
                            BreakpointID::GetCanonicalReference (&id_str, 
                                                                 cur_bp_id.GetBreakpointID(), 
                                                                 cur_bp_id.GetLocationID());
                            const Baton *baton = bp_options->GetBaton();
                            if (baton)
                            {
                                result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
                                result.GetOutputStream().IndentMore ();
                                baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
                                result.GetOutputStream().IndentLess ();
                            }
                            else
                            {
                                result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", 
                                                                id_str.GetData());
                            }
                        }
                        result.SetStatus (eReturnStatusSuccessFinishResult);
                    }
                    else
                    {
                        result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
                        result.SetStatus (eReturnStatusFailed);
                    }

                }
            }
        }

        return result.Succeeded();
    }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointCommand
//-------------------------------------------------------------------------

CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
    CommandObjectMultiword (interpreter,
                            "command",
                            "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
                            "command <sub-command> [<sub-command-options>] <breakpoint-id>")
{
    CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
    CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
    CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));

    add_command_object->SetCommandName ("breakpoint command add");
    delete_command_object->SetCommandName ("breakpoint command delete");
    list_command_object->SetCommandName ("breakpoint command list");

    LoadSubCommand ("add",    add_command_object);
    LoadSubCommand ("delete", delete_command_object);
    LoadSubCommand ("list",   list_command_object);
}

CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
{
}


