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

#include "lldb/lldb-python.h"

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

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

static void
AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level)
{
    s->IndentMore();
    bp->GetDescription (s, level, true);
    s->IndentLess();
    s->EOL();
}

//-------------------------------------------------------------------------
// CommandObjectBreakpointSet
//-------------------------------------------------------------------------


class CommandObjectBreakpointSet : public CommandObjectParsed
{
public:

    typedef enum BreakpointSetType
    {
        eSetTypeInvalid,
        eSetTypeFileAndLine,
        eSetTypeAddress,
        eSetTypeFunctionName,
        eSetTypeFunctionRegexp,
        eSetTypeSourceRegexp,
        eSetTypeException
    } BreakpointSetType;

    CommandObjectBreakpointSet (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "breakpoint set", 
                             "Sets a breakpoint or set of breakpoints in the executable.", 
                             "breakpoint set <cmd-options>"),
        m_options (interpreter)
    {
    }


    virtual
    ~CommandObjectBreakpointSet () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_condition (),
            m_filenames (),
            m_line_num (0),
            m_column (0),
            m_func_names (),
            m_func_name_type_mask (eFunctionNameTypeNone),
            m_func_regexp (),
            m_source_text_regexp(),
            m_modules (),
            m_load_addr(),
            m_ignore_count (0),
            m_thread_id(LLDB_INVALID_THREAD_ID),
            m_thread_index (UINT32_MAX),
            m_thread_name(),
            m_queue_name(),
            m_catch_bp (false),
            m_throw_bp (true),
            m_hardware (false),
            m_language (eLanguageTypeUnknown),
            m_skip_prologue (eLazyBoolCalculate),
            m_one_shot (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 'a':
                    {
                        ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
                        m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
                    }
                    break;

                case 'b':
                    m_func_names.push_back (option_arg);
                    m_func_name_type_mask |= eFunctionNameTypeBase;
                    break;

                case 'C':
                    m_column = Args::StringToUInt32 (option_arg, 0);
                    break;

                case 'c':
                    m_condition.assign(option_arg);
                    break;

                case 'D':
                    m_use_dummy = true;
                    break;

                case 'E':
                {
                    LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);

                    switch (language)
                    {
                        case eLanguageTypeC89:
                        case eLanguageTypeC:
                        case eLanguageTypeC99:
                        case eLanguageTypeC11:
                            m_language = eLanguageTypeC;
                            break;
                        case eLanguageTypeC_plus_plus:
                        case eLanguageTypeC_plus_plus_03:
                        case eLanguageTypeC_plus_plus_11:
                            m_language = eLanguageTypeC_plus_plus;
                            break;
                        case eLanguageTypeObjC:
                            m_language = eLanguageTypeObjC;
                            break;
                        case eLanguageTypeObjC_plus_plus:
                            error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
                            break;
                        case eLanguageTypeUnknown:
                            error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg);
                            break;
                        default:
                            error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg);
                    }
                }
                break;

                case 'f':
                    m_filenames.AppendIfUnique (FileSpec(option_arg, false));
                    break;

                case 'F':
                    m_func_names.push_back (option_arg);
                    m_func_name_type_mask |= eFunctionNameTypeFull;
                    break;

                case 'h':
                    {
                        bool success;
                        m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
                        if (!success)
                            error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
                    }
                    break;

                case 'H':
                    m_hardware = true;
                    break;

                case 'i':
                {
                    m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
                    if (m_ignore_count == UINT32_MAX)
                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
                    break;
                }

                case 'K':
                {
                    bool success;
                    bool value;
                    value = Args::StringToBoolean (option_arg, true, &success);
                    if (value)
                        m_skip_prologue = eLazyBoolYes;
                    else
                        m_skip_prologue = eLazyBoolNo;
                        
                    if (!success)
                        error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg);
                }
                break;

                case 'l':
                    m_line_num = Args::StringToUInt32 (option_arg, 0);
                    break;

                case 'M':
                    m_func_names.push_back (option_arg);
                    m_func_name_type_mask |= eFunctionNameTypeMethod;
                    break;

                case 'n':
                    m_func_names.push_back (option_arg);
                    m_func_name_type_mask |= eFunctionNameTypeAuto;
                    break;

                case 'N':
                    if (BreakpointID::StringIsBreakpointName(option_arg, error))
                        m_breakpoint_names.push_back (option_arg);
                    break;

                case 'o':
                    m_one_shot = true;
                    break;

                case 'p':
                    m_source_text_regexp.assign (option_arg);
                    break;
                    
                case 'q':
                    m_queue_name.assign (option_arg);
                    break;

                case 'r':
                    m_func_regexp.assign (option_arg);
                    break;

                case 's':
                {
                    m_modules.AppendIfUnique (FileSpec (option_arg, false));
                    break;
                }
                    
                case 'S':
                    m_func_names.push_back (option_arg);
                    m_func_name_type_mask |= eFunctionNameTypeSelector;
                    break;

                case 't' :
                {
                    m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
                    if (m_thread_id == LLDB_INVALID_THREAD_ID)
                       error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
                }
                break;

                case 'T':
                    m_thread_name.assign (option_arg);
                    break;

                case 'w':
                {
                    bool success;
                    m_throw_bp = Args::StringToBoolean (option_arg, true, &success);
                    if (!success)
                        error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
                }
                break;

                case 'x':
                {
                    m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
                    if (m_thread_id == UINT32_MAX)
                       error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
                    
                }
                break;

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

            return error;
        }
        void
        OptionParsingStarting ()
        {
            m_condition.clear();
            m_filenames.Clear();
            m_line_num = 0;
            m_column = 0;
            m_func_names.clear();
            m_func_name_type_mask = eFunctionNameTypeNone;
            m_func_regexp.clear();
            m_source_text_regexp.clear();
            m_modules.Clear();
            m_load_addr = LLDB_INVALID_ADDRESS;
            m_ignore_count = 0;
            m_thread_id = LLDB_INVALID_THREAD_ID;
            m_thread_index = UINT32_MAX;
            m_thread_name.clear();
            m_queue_name.clear();
            m_catch_bp = false;
            m_throw_bp = true;
            m_hardware = false;
            m_language = eLanguageTypeUnknown;
            m_skip_prologue = eLazyBoolCalculate;
            m_one_shot = false;
            m_use_dummy = false;
            m_breakpoint_names.clear();
        }
    
        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.

        std::string m_condition;
        FileSpecList m_filenames;
        uint32_t m_line_num;
        uint32_t m_column;
        std::vector<std::string> m_func_names;
        std::vector<std::string> m_breakpoint_names;
        uint32_t m_func_name_type_mask;
        std::string m_func_regexp;
        std::string m_source_text_regexp;
        FileSpecList m_modules;
        lldb::addr_t m_load_addr;
        uint32_t m_ignore_count;
        lldb::tid_t m_thread_id;
        uint32_t m_thread_index;
        std::string m_thread_name;
        std::string m_queue_name;
        bool m_catch_bp;
        bool m_throw_bp;
        bool m_hardware; // Request to use hardware breakpoints
        lldb::LanguageType m_language;
        LazyBool m_skip_prologue;
        bool m_one_shot;
        bool m_use_dummy;

    };

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

        if (target == nullptr)
        {
            result.AppendError ("Invalid target.  Must set target before setting breakpoints (see 'target create' command).");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        // The following are the various types of breakpoints that could be set:
        //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
        //   2).  -a  [-s -g]         (setting breakpoint by address)
        //   3).  -n  [-s -g]         (setting breakpoint by function name)
        //   4).  -r  [-s -g]         (setting breakpoint by function name regular expression)
        //   5).  -p -f               (setting a breakpoint by comparing a reg-exp to source text)
        //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a given language.)

        BreakpointSetType break_type = eSetTypeInvalid;

        if (m_options.m_line_num != 0)
            break_type = eSetTypeFileAndLine;
        else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
            break_type = eSetTypeAddress;
        else if (!m_options.m_func_names.empty())
            break_type = eSetTypeFunctionName;
        else if  (!m_options.m_func_regexp.empty())
            break_type = eSetTypeFunctionRegexp;
        else if (!m_options.m_source_text_regexp.empty())
            break_type = eSetTypeSourceRegexp;
        else if (m_options.m_language != eLanguageTypeUnknown)
            break_type = eSetTypeException;

        Breakpoint *bp = NULL;
        FileSpec module_spec;
        const bool internal = false;

        switch (break_type)
        {
            case eSetTypeFileAndLine: // Breakpoint by source position
                {
                    FileSpec file;
                    const size_t num_files = m_options.m_filenames.GetSize();
                    if (num_files == 0)
                    {
                        if (!GetDefaultFile (target, file, result))
                        {
                            result.AppendError("No file supplied and no default file available.");
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                    }
                    else if (num_files > 1)
                    {
                        result.AppendError("Only one file at a time is allowed for file and line breakpoints.");
                        result.SetStatus (eReturnStatusFailed);
                        return false;
                    }
                    else
                        file = m_options.m_filenames.GetFileSpecAtIndex(0);
                    
                    // Only check for inline functions if 
                    LazyBool check_inlines = eLazyBoolCalculate;
                    
                    bp = target->CreateBreakpoint (&(m_options.m_modules),
                                                   file,
                                                   m_options.m_line_num,
                                                   check_inlines,
                                                   m_options.m_skip_prologue,
                                                   internal,
                                                   m_options.m_hardware).get();
                }
                break;

            case eSetTypeAddress: // Breakpoint by address
                bp = target->CreateBreakpoint (m_options.m_load_addr,
                                               internal,
                                               m_options.m_hardware).get();
                break;

            case eSetTypeFunctionName: // Breakpoint by function name
                {
                    uint32_t name_type_mask = m_options.m_func_name_type_mask;
                    
                    if (name_type_mask == 0)
                        name_type_mask = eFunctionNameTypeAuto;
                    
                    bp = target->CreateBreakpoint (&(m_options.m_modules),
                                                   &(m_options.m_filenames),
                                                   m_options.m_func_names,
                                                   name_type_mask,
                                                   m_options.m_skip_prologue,
                                                   internal,
                                                   m_options.m_hardware).get();
                }
                break;

            case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
                {
                    RegularExpression regexp(m_options.m_func_regexp.c_str());
                    if (!regexp.IsValid())
                    {
                        char err_str[1024];
                        regexp.GetErrorAsCString(err_str, sizeof(err_str));
                        result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"",
                                                     err_str);
                        result.SetStatus (eReturnStatusFailed);
                        return false;
                    }
                    
                    bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules),
                                                            &(m_options.m_filenames),
                                                            regexp,
                                                            m_options.m_skip_prologue,
                                                            internal,
                                                            m_options.m_hardware).get();
                }
                break;
            case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
                {
                    const size_t num_files = m_options.m_filenames.GetSize();
                    
                    if (num_files == 0)
                    {
                        FileSpec file;
                        if (!GetDefaultFile (target, file, result))
                        {
                            result.AppendError ("No files provided and could not find default file.");
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                        else
                        {
                            m_options.m_filenames.Append (file);
                        }
                    }
                    
                    RegularExpression regexp(m_options.m_source_text_regexp.c_str());
                    if (!regexp.IsValid())
                    {
                        char err_str[1024];
                        regexp.GetErrorAsCString(err_str, sizeof(err_str));
                        result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"",
                                                     err_str);
                        result.SetStatus (eReturnStatusFailed);
                        return false;
                    }
                    bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules),
                                                              &(m_options.m_filenames),
                                                              regexp,
                                                              internal,
                                                              m_options.m_hardware).get();
                }
                break;
            case eSetTypeException:
                {
                    bp = target->CreateExceptionBreakpoint (m_options.m_language,
                                                            m_options.m_catch_bp,
                                                            m_options.m_throw_bp,
                                                            m_options.m_hardware).get();
                }
                break;
            default:
                break;
        }

        // Now set the various options that were passed in:
        if (bp)
        {
            if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
                bp->SetThreadID (m_options.m_thread_id);
                
            if (m_options.m_thread_index != UINT32_MAX)
                bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
            
            if (!m_options.m_thread_name.empty())
                bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
            
            if (!m_options.m_queue_name.empty())
                bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
                
            if (m_options.m_ignore_count != 0)
                bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);

            if (!m_options.m_condition.empty())
                bp->GetOptions()->SetCondition(m_options.m_condition.c_str());

            if (!m_options.m_breakpoint_names.empty())
            {
                Error error;  // We don't need to check the error here, since the option parser checked it...
                for (auto name : m_options.m_breakpoint_names)
                    bp->AddName(name.c_str(), error);
            }
            
            bp->SetOneShot (m_options.m_one_shot);
        }
        
        if (bp)
        {
            Stream &output_stream = result.GetOutputStream();
            const bool show_locations = false;
            bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations);
            if (target == m_interpreter.GetDebugger().GetDummyTarget())
                    output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n");
            else
            {
                // Don't print out this warning for exception breakpoints.  They can get set before the target
                // is set, but we won't know how to actually set the breakpoint till we run.
                if (bp->GetNumLocations() == 0 && break_type != eSetTypeException)
                {
                    output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n");
                }
            }
            result.SetStatus (eReturnStatusSuccessFinishResult);
        }
        else if (!bp)
        {
            result.AppendError ("Breakpoint creation failed: No breakpoint created.");
            result.SetStatus (eReturnStatusFailed);
        }

        return result.Succeeded();
    }

private:
    bool
    GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result)
    {
        uint32_t default_line;
        // First use the Source Manager's default file. 
        // Then use the current stack frame's file.
        if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
        {
            StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
            if (cur_frame == NULL)
            {
                result.AppendError ("No selected frame to use to find the default file.");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            else if (!cur_frame->HasDebugInformation())
            {
                result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info.");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            else
            {
                const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
                if (sc.line_entry.file)
                {
                    file = sc.line_entry.file;
                }
                else
                {
                    result.AppendError ("Can't find the file for the selected frame to use as the default file.");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
        }
        return true;
    }
    
    CommandOptions m_options;
};
// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
#define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 )
#define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 )
#define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) )

OptionDefinition
CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
        "Set the breakpoint only in this shared library.  "
        "Can repeat this option multiple times to specify multiple shared libraries."},

    { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument,   NULL, NULL, 0, eArgTypeCount,
        "Set the number of times this breakpoint is skipped before stopping." },

    { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument,   NULL, NULL, 0, eArgTypeNone,
        "The breakpoint is deleted the first time it causes a stop." },

    { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression,
        "The breakpoint stops only if this condition expression evaluates to true."},

    { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex,
        "The breakpoint stops only for the thread whose indeX matches this argument."},

    { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID,
        "The breakpoint stops only for the thread whose TID matches this argument."},

    { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName,
        "The breakpoint stops only for the thread whose thread name matches this argument."},

    { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Require the breakpoint to use hardware breakpoints."},

    { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName,
        "The breakpoint stops only for threads in the queue whose name is given by this argument."},

    { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
        "Specifies the source file in which to set this breakpoint.  "
        "Note, by default lldb only looks for files that are #included if they use the standard include file extensions.  "
        "To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy"
        " to \"always\"."},

    { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
        "Specifies the line number on which to set this breakpoint."},

    // Comment out this option for the moment, as we don't actually use it, but will in the future.
    // This way users won't see it, but the infrastructure is left in place.
    //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, NULL, "<column>",
    //    "Set the breakpoint by source location at this particular column."},

    { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
        "Set the breakpoint by address, at the specified address."},

    { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
        "Set the breakpoint by function name.  Can be repeated multiple times to make one breakpoint for multiple names" },

    { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
        "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and "
        "for Objective C this means a full function prototype with class and selector.   "
        "Can be repeated multiple times to make one breakpoint for multiple names." },

    { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSelector,
        "Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." },

    { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeMethod,
        "Set the breakpoint by C++ method names.  Can be repeated multiple times to make one breakpoint for multiple methods." },

    { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
        "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },

    { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
        "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). "
        "Can be repeated multiple times to make one breakpoint for multiple symbols." },

    { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
        "Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files "
        "specified with the -f option.  The -f option can be specified more than once.  "
        "If no source files are specified, uses the current \"default source file\"" },

    { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,
        "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" },

    { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
        "Set the breakpoint on exception throW." },

    { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
        "Set the breakpoint on exception catcH." },

    { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
        "sKip the prologue if the breakpoint is at the beginning of a function.  If not set the target.skip-prologue setting is used." },

    { 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."},

    { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName,
        "Adds this to the list of names for this breakopint."},

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

//-------------------------------------------------------------------------
// CommandObjectBreakpointModify
//-------------------------------------------------------------------------
#pragma mark Modify

class CommandObjectBreakpointModify : public CommandObjectParsed
{
public:

    CommandObjectBreakpointModify (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "breakpoint modify", 
                             "Modify the options on a breakpoint or set of breakpoints in the executable.  "
                             "If no breakpoint is specified, acts on the last created breakpoint.  "
                             "With the exception of -e, -d and -i, passing an empty argument clears the modification.", 
                             NULL),
        m_options (interpreter)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back (arg);   
    }


    virtual
    ~CommandObjectBreakpointModify () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_ignore_count (0),
            m_thread_id(LLDB_INVALID_THREAD_ID),
            m_thread_id_passed(false),
            m_thread_index (UINT32_MAX),
            m_thread_index_passed(false),
            m_thread_name(),
            m_queue_name(),
            m_condition (),
            m_one_shot (false),
            m_enable_passed (false),
            m_enable_value (false),
            m_name_passed (false),
            m_queue_passed (false),
            m_condition_passed (false),
            m_one_shot_passed (false),
            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 'c':
                    if (option_arg != NULL)
                        m_condition.assign (option_arg);
                    else
                        m_condition.clear();
                    m_condition_passed = true;
                    break;
                case 'd':
                    m_enable_passed = true;
                    m_enable_value = false;
                    break;
                case 'D':
                    m_use_dummy = true;
                    break;
                case 'e':
                    m_enable_passed = true;
                    m_enable_value = true;
                    break;
                case 'i':
                {
                    m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
                    if (m_ignore_count == UINT32_MAX)
                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
                }
                break;
                case 'o':
                {
                    bool value, success;
                    value = Args::StringToBoolean(option_arg, false, &success);
                    if (success)
                    {
                        m_one_shot_passed = true;
                        m_one_shot = value;
                    }
                    else
                        error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg);
                }
                break;
                case 't' :
                {
                    if (option_arg[0] == '\0')
                    {
                        m_thread_id = LLDB_INVALID_THREAD_ID;
                        m_thread_id_passed = true;
                    }
                    else
                    {
                        m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
                        if (m_thread_id == LLDB_INVALID_THREAD_ID)
                           error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
                        else
                            m_thread_id_passed = true;
                    }
                }
                break;
                case 'T':
                    if (option_arg != NULL)
                        m_thread_name.assign (option_arg);
                    else
                        m_thread_name.clear();
                    m_name_passed = true;
                    break;
                case 'q':
                    if (option_arg != NULL)
                        m_queue_name.assign (option_arg);
                    else
                        m_queue_name.clear();
                    m_queue_passed = true;
                    break;
                case 'x':
                {
                    if (option_arg[0] == '\n')
                    {
                        m_thread_index = UINT32_MAX;
                        m_thread_index_passed = true;
                    }
                    else
                    {
                        m_thread_index = Args::StringToUInt32 (option_arg, UINT32_MAX, 0);
                        if (m_thread_id == UINT32_MAX)
                           error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
                        else
                            m_thread_index_passed = true;
                    }
                }
                break;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }
        void
        OptionParsingStarting ()
        {
            m_ignore_count = 0;
            m_thread_id = LLDB_INVALID_THREAD_ID;
            m_thread_id_passed = false;
            m_thread_index = UINT32_MAX;
            m_thread_index_passed = false;
            m_thread_name.clear();
            m_queue_name.clear();
            m_condition.clear();
            m_one_shot = false;
            m_enable_passed = false;
            m_queue_passed = false;
            m_name_passed = false;
            m_condition_passed = false;
            m_one_shot_passed = false;
            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.

        uint32_t m_ignore_count;
        lldb::tid_t m_thread_id;
        bool m_thread_id_passed;
        uint32_t m_thread_index;
        bool m_thread_index_passed;
        std::string m_thread_name;
        std::string m_queue_name;
        std::string m_condition;
        bool m_one_shot;
        bool m_enable_passed;
        bool m_enable_value;
        bool m_name_passed;
        bool m_queue_passed;
        bool m_condition_passed;
        bool m_one_shot_passed;
        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 ("Invalid target.  No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);
        
        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)
                    {
                        BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get();
                        if (location)
                        {
                            if (m_options.m_thread_id_passed)
                                location->SetThreadID (m_options.m_thread_id);
                                
                            if (m_options.m_thread_index_passed)
                                location->SetThreadIndex(m_options.m_thread_index);
                            
                            if (m_options.m_name_passed)
                                location->SetThreadName(m_options.m_thread_name.c_str());
                            
                            if (m_options.m_queue_passed)
                                location->SetQueueName(m_options.m_queue_name.c_str());
                                
                            if (m_options.m_ignore_count != 0)
                                location->SetIgnoreCount(m_options.m_ignore_count);
                                
                            if (m_options.m_enable_passed)
                                location->SetEnabled (m_options.m_enable_value);
                                
                            if (m_options.m_condition_passed)
                                location->SetCondition (m_options.m_condition.c_str());
                        }
                    }
                    else
                    {
                        if (m_options.m_thread_id_passed)
                            bp->SetThreadID (m_options.m_thread_id);
                            
                        if (m_options.m_thread_index_passed)
                            bp->SetThreadIndex(m_options.m_thread_index);
                        
                        if (m_options.m_name_passed)
                            bp->SetThreadName(m_options.m_thread_name.c_str());
                        
                        if (m_options.m_queue_passed)
                            bp->SetQueueName(m_options.m_queue_name.c_str());
                            
                        if (m_options.m_ignore_count != 0)
                            bp->SetIgnoreCount(m_options.m_ignore_count);
                            
                        if (m_options.m_enable_passed)
                            bp->SetEnabled (m_options.m_enable_value);
                            
                        if (m_options.m_condition_passed)
                            bp->SetCondition (m_options.m_condition.c_str());
                    }
                }
            }
        }
        
        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

#pragma mark Modify::CommandOptions
OptionDefinition
CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
{ LLDB_OPT_SET_ALL, false, "one-shot",     'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
{ LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
{ LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
{ LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
{ LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
{ 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 }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointEnable
//-------------------------------------------------------------------------
#pragma mark Enable

class CommandObjectBreakpointEnable : public CommandObjectParsed
{
public:
    CommandObjectBreakpointEnable (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "enable",
                             "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.",
                             NULL)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back (arg);   
    }


    virtual
    ~CommandObjectBreakpointEnable () {}

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget();
        if (target == NULL)
        {
            result.AppendError ("Invalid target.  No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);

        const BreakpointList &breakpoints = target->GetBreakpointList();

        size_t num_breakpoints = breakpoints.GetSize();

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

        if (command.GetArgumentCount() == 0)
        {
            // No breakpoint selected; enable all currently set breakpoints.
            target->EnableAllBreakpoints ();
            result.AppendMessageWithFormat ("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular breakpoint selected; enable that breakpoint.
            BreakpointIDList valid_bp_ids;
            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

            if (result.Succeeded())
            {
                int enable_count = 0;
                int loc_count = 0;
                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 *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
                        {
                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
                            if (location)
                            {
                                location->SetEnabled (true);
                                ++loc_count;
                            }
                        }
                        else
                        {
                            breakpoint->SetEnabled (true);
                            ++enable_count;
                        }
                    }
                }
                result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
                result.SetStatus (eReturnStatusSuccessFinishNoResult);
            }
        }

        return result.Succeeded();
    }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointDisable
//-------------------------------------------------------------------------
#pragma mark Disable

class CommandObjectBreakpointDisable : public CommandObjectParsed
{
public:
    CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "breakpoint disable",
                             "Disable the specified breakpoint(s) without removing it/them.  If no breakpoints are specified, disable them all.",
                             NULL)
    {
        SetHelpLong(
"Disable the specified breakpoint(s) without removing it/them.  \n\
If no breakpoints are specified, disable them all.\n\
\n\
Note: disabling a breakpoint will cause none of its locations to be hit\n\
regardless of whether they are enabled or disabled.  So the sequence: \n\
\n\
    (lldb) break disable 1\n\
    (lldb) break enable 1.1\n\
\n\
will NOT cause location 1.1 to get hit.  To achieve that, do:\n\
\n\
    (lldb) break disable 1.*\n\
    (lldb) break enable 1.1\n\
\n\
The first command disables all the locations of breakpoint 1, \n\
the second re-enables the first location."
                    );
        
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back (arg);

    }


    virtual
    ~CommandObjectBreakpointDisable () {}

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget();
        if (target == NULL)
        {
            result.AppendError ("Invalid target.  No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);

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

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

        if (command.GetArgumentCount() == 0)
        {
            // No breakpoint selected; disable all currently set breakpoints.
            target->DisableAllBreakpoints ();
            result.AppendMessageWithFormat ("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular breakpoint selected; disable that breakpoint.
            BreakpointIDList valid_bp_ids;

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

            if (result.Succeeded())
            {
                int disable_count = 0;
                int loc_count = 0;
                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 *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
                        {
                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
                            if (location)
                            {
                                location->SetEnabled (false);
                                ++loc_count;
                            }
                        }
                        else
                        {
                            breakpoint->SetEnabled (false);
                            ++disable_count;
                        }
                    }
                }
                result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
                result.SetStatus (eReturnStatusSuccessFinishNoResult);
            }
        }

        return result.Succeeded();
    }

};

//-------------------------------------------------------------------------
// CommandObjectBreakpointList
//-------------------------------------------------------------------------
#pragma mark List

class CommandObjectBreakpointList : public CommandObjectParsed
{
public:
    CommandObjectBreakpointList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "breakpoint list",
                             "List some or all breakpoints at configurable levels of detail.",
                             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 = 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
    ~CommandObjectBreakpointList () {}

    virtual Options *
    GetOptions ()
    {
        return &m_options;
    }
    
    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_level (lldb::eDescriptionLevelBrief),
            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 'b':
                    m_level = lldb::eDescriptionLevelBrief;
                    break;
                case 'D':
                    m_use_dummy = true;
                    break;
                case 'f':
                    m_level = lldb::eDescriptionLevelFull;
                    break;
                case 'v':
                    m_level = lldb::eDescriptionLevelVerbose;
                    break;
                case 'i':
                    m_internal = true;
                    break;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_level = lldb::eDescriptionLevelFull;
            m_internal = false;
            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.

        lldb::DescriptionLevel m_level;

        bool m_internal;
        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 ("Invalid target. No current target or breakpoints.");
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            return true;
        }

        const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
        Mutex::Locker locker;
        target->GetBreakpointList(m_options.m_internal).GetListMutex(locker);

        size_t num_breakpoints = breakpoints.GetSize();

        if (num_breakpoints == 0)
        {
            result.AppendMessage ("No breakpoints currently set.");
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            return true;
        }

        Stream &output_stream = result.GetOutputStream();

        if (command.GetArgumentCount() == 0)
        {
            // No breakpoint selected; show info about all currently set breakpoints.
            result.AppendMessage ("Current breakpoints:");
            for (size_t i = 0; i < num_breakpoints; ++i)
            {
                Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get();
                AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
            }
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular breakpoints selected; show info about that breakpoint.
            BreakpointIDList valid_bp_ids;
            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

            if (result.Succeeded())
            {
                for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i)
                {
                    BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
                    Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                    AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
                }
                result.SetStatus (eReturnStatusSuccessFinishNoResult);
            }
            else
            {
                result.AppendError ("Invalid breakpoint id.");
                result.SetStatus (eReturnStatusFailed);
            }
        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

#pragma mark List::CommandOptions
OptionDefinition
CommandObjectBreakpointList::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Show debugger internal breakpoints" },

    { LLDB_OPT_SET_1, false, "brief",    'b', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Give a brief description of the breakpoint (no location info)."},

    // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
    // But I need to see it for now, and don't want to wait.
    { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Give a full description of the breakpoint and its locations."},

    { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Explain everything we know about the breakpoint (for debugging debugger bugs)." },

    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "List 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 }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointClear
//-------------------------------------------------------------------------
#pragma mark Clear

class CommandObjectBreakpointClear : public CommandObjectParsed
{
public:

    typedef enum BreakpointClearType
    {
        eClearTypeInvalid,
        eClearTypeFileAndLine
    } BreakpointClearType;

    CommandObjectBreakpointClear (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "breakpoint clear", 
                             "Clears a breakpoint or set of breakpoints in the executable.", 
                             "breakpoint clear <cmd-options>"),
        m_options (interpreter)
    {
    }

    virtual
    ~CommandObjectBreakpointClear () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_filename (),
            m_line_num (0)
        {
        }

        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 'f':
                    m_filename.assign (option_arg);
                    break;

                case 'l':
                    m_line_num = Args::StringToUInt32 (option_arg, 0);
                    break;

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

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_filename.clear();
            m_line_num = 0;
        }

        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.

        std::string m_filename;
        uint32_t m_line_num;

    };

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget();
        if (target == NULL)
        {
            result.AppendError ("Invalid target. No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        // The following are the various types of breakpoints that could be cleared:
        //   1). -f -l (clearing breakpoint by source location)

        BreakpointClearType break_type = eClearTypeInvalid;

        if (m_options.m_line_num != 0)
            break_type = eClearTypeFileAndLine;

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);

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

        // Early return if there's no breakpoint at all.
        if (num_breakpoints == 0)
        {
            result.AppendError ("Breakpoint clear: No breakpoint cleared.");
            result.SetStatus (eReturnStatusFailed);
            return result.Succeeded();
        }

        // Find matching breakpoints and delete them.

        // First create a copy of all the IDs.
        std::vector<break_id_t> BreakIDs;
        for (size_t i = 0; i < num_breakpoints; ++i)
            BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i).get()->GetID());

        int num_cleared = 0;
        StreamString ss;
        switch (break_type)
        {
            case eClearTypeFileAndLine: // Breakpoint by source position
                {
                    const ConstString filename(m_options.m_filename.c_str());
                    BreakpointLocationCollection loc_coll;

                    for (size_t i = 0; i < num_breakpoints; ++i)
                    {
                        Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
                        
                        if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll))
                        {
                            // If the collection size is 0, it's a full match and we can just remove the breakpoint.
                            if (loc_coll.GetSize() == 0)
                            {
                                bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
                                ss.EOL();
                                target->RemoveBreakpointByID (bp->GetID());
                                ++num_cleared;
                            }
                        }
                    }
                }
                break;

            default:
                break;
        }

        if (num_cleared > 0)
        {
            Stream &output_stream = result.GetOutputStream();
            output_stream.Printf ("%d breakpoints cleared:\n", num_cleared);
            output_stream << ss.GetData();
            output_stream.EOL();
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            result.AppendError ("Breakpoint clear: No breakpoint cleared.");
            result.SetStatus (eReturnStatusFailed);
        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

#pragma mark Clear::CommandOptions

OptionDefinition
CommandObjectBreakpointClear::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
        "Specify the breakpoint by source location in this particular file."},

    { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
        "Specify the breakpoint by source location at this particular line."},

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

//-------------------------------------------------------------------------
// CommandObjectBreakpointDelete
//-------------------------------------------------------------------------
#pragma mark Delete

class CommandObjectBreakpointDelete : public CommandObjectParsed
{
public:
    CommandObjectBreakpointDelete (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "breakpoint delete",
                             "Delete the specified breakpoint(s).  If no breakpoints are specified, delete them all.",
                             NULL),
        m_options (interpreter)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back (arg);   
    }

    virtual
    ~CommandObjectBreakpointDelete () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_use_dummy (false),
            m_force (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 'f':
                    m_force = true;
                    break;

                case 'D':
                    m_use_dummy = true;
                    break;

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

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_use_dummy = false;
            m_force = 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;
        bool m_force;
    };

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

        if (target == NULL)
        {
            result.AppendError ("Invalid target. No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);
        
        const BreakpointList &breakpoints = target->GetBreakpointList();

        size_t num_breakpoints = breakpoints.GetSize();

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

        if (command.GetArgumentCount() == 0)
        {
            if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
            {
                result.AppendMessage("Operation cancelled...");
            }
            else
            {
                target->RemoveAllBreakpoints ();
                result.AppendMessageWithFormat ("All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
            }
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular breakpoint selected; disable that breakpoint.
            BreakpointIDList valid_bp_ids;
            CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);

            if (result.Succeeded())
            {
                int delete_count = 0;
                int disable_count = 0;
                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)
                    {
                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
                        {
                            Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
                            // It makes no sense to try to delete individual locations, so we disable them instead.
                            if (location)
                            {
                                location->SetEnabled (false);
                                ++disable_count;
                            }
                        }
                        else
                        {
                            target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
                            ++delete_count;
                        }
                    }
                }
                result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
                                               delete_count, disable_count);
                result.SetStatus (eReturnStatusSuccessFinishNoResult);
            }
        }
        return result.Succeeded();
    }
private:
    CommandOptions m_options;
};

OptionDefinition
CommandObjectBreakpointDelete::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Delete all breakpoints without querying for confirmation."},

    { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Delete 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 }
};

//-------------------------------------------------------------------------
// CommandObjectBreakpointName
//-------------------------------------------------------------------------

static OptionDefinition
g_breakpoint_name_options[] =
{
    { LLDB_OPT_SET_1,   false, "name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
    { LLDB_OPT_SET_2,   false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointID,   "Specify a breakpoint id to use."},
    { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
        "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
};
class BreakpointNameOptionGroup : public OptionGroup
{
public:
    BreakpointNameOptionGroup() :
        OptionGroup(),
        m_breakpoint(LLDB_INVALID_BREAK_ID),
        m_use_dummy (false)
    {

    }

    virtual
    ~BreakpointNameOptionGroup ()
    {
    }
    
    virtual uint32_t
    GetNumDefinitions ()
    {
      return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition);
    }

    virtual const OptionDefinition*
    GetDefinitions ()
    {
        return g_breakpoint_name_options;
    }

    virtual Error
    SetOptionValue (CommandInterpreter &interpreter,
                    uint32_t option_idx,
                    const char *option_value)
    {
        Error error;
        const int short_option = g_breakpoint_name_options[option_idx].short_option;
      
        switch (short_option)
        {
        case 'N':
            if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success())
                m_name.SetValueFromCString(option_value);
            break;
          
        case 'B':
            if (m_breakpoint.SetValueFromCString(option_value).Fail())
                error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value);
            break;
        case 'D':
            if (m_use_dummy.SetValueFromCString(option_value).Fail())
                error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value);
            break;

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

    virtual void
    OptionParsingStarting (CommandInterpreter &interpreter)
    {
        m_name.Clear();
        m_breakpoint.Clear();
        m_use_dummy.Clear();
        m_use_dummy.SetDefaultValue(false);
    }

    OptionValueString m_name;
    OptionValueUInt64 m_breakpoint;
    OptionValueBoolean m_use_dummy;
};


class CommandObjectBreakpointNameAdd : public CommandObjectParsed
{
public:
    CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "add",
                             "Add a name to the breakpoints provided.",
                             "breakpoint name add <command-options> <breakpoint-id-list>"),
        m_name_options(),
        m_option_group(interpreter)
        {
            // Create the first variant for the first (and only) argument for this command.
            CommandArgumentEntry arg1;
            CommandArgumentData id_arg;
            id_arg.arg_type = eArgTypeBreakpointID;
            id_arg.arg_repetition = eArgRepeatOptional;
            arg1.push_back(id_arg);
            m_arguments.push_back (arg1);

            m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
            m_option_group.Finalize();
        }

    virtual
    ~CommandObjectBreakpointNameAdd () {}

  Options *
  GetOptions ()
  {
    return &m_option_group;
  }
  
protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        if (!m_name_options.m_name.OptionWasSet())
        {
            result.SetError("No name option provided.");
            return false;
        }

        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());

        if (target == NULL)
        {
            result.AppendError ("Invalid target. No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);
        
        const BreakpointList &breakpoints = target->GetBreakpointList();

        size_t num_breakpoints = breakpoints.GetSize();
        if (num_breakpoints == 0)
        {
            result.SetError("No breakpoints, cannot add names.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        // Particular breakpoint selected; disable that breakpoint.
        BreakpointIDList valid_bp_ids;
        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);

        if (result.Succeeded())
        {
            if (valid_bp_ids.GetSize() == 0)
            {
                result.SetError("No breakpoints specified, cannot add names.");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            size_t num_valid_ids = valid_bp_ids.GetSize();
            for (size_t index = 0; index < num_valid_ids; index++)
            {
                lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
                BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
                Error error;  // We don't need to check the error here, since the option parser checked it...
                bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
            }
        }

        return true;
    }

private:
    BreakpointNameOptionGroup m_name_options;
    OptionGroupOptions m_option_group;
};



class CommandObjectBreakpointNameDelete : public CommandObjectParsed
{
public:
    CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "delete",
                             "Delete a name from the breakpoints provided.",
                             "breakpoint name delete <command-options> <breakpoint-id-list>"),
        m_name_options(),
        m_option_group(interpreter)
    {
        // Create the first variant for the first (and only) argument for this command.
        CommandArgumentEntry arg1;
        CommandArgumentData id_arg;
        id_arg.arg_type = eArgTypeBreakpointID;
        id_arg.arg_repetition = eArgRepeatOptional;
        arg1.push_back(id_arg);
        m_arguments.push_back (arg1);

        m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
        m_option_group.Finalize();
    }

    virtual
    ~CommandObjectBreakpointNameDelete () {}

  Options *
  GetOptions ()
  {
    return &m_option_group;
  }
  
protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        if (!m_name_options.m_name.OptionWasSet())
        {
            result.SetError("No name option provided.");
            return false;
        }

        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());

        if (target == NULL)
        {
            result.AppendError ("Invalid target. No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        Mutex::Locker locker;
        target->GetBreakpointList().GetListMutex(locker);
        
        const BreakpointList &breakpoints = target->GetBreakpointList();

        size_t num_breakpoints = breakpoints.GetSize();
        if (num_breakpoints == 0)
        {
            result.SetError("No breakpoints, cannot delete names.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        // Particular breakpoint selected; disable that breakpoint.
        BreakpointIDList valid_bp_ids;
        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);

        if (result.Succeeded())
        {
            if (valid_bp_ids.GetSize() == 0)
            {
                result.SetError("No breakpoints specified, cannot delete names.");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
            size_t num_valid_ids = valid_bp_ids.GetSize();
            for (size_t index = 0; index < num_valid_ids; index++)
            {
                lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
                BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
                bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
            }
        }

        return true;
    }

private:
    BreakpointNameOptionGroup m_name_options;
    OptionGroupOptions m_option_group;
};

class CommandObjectBreakpointNameList : public CommandObjectParsed
{
public:
    CommandObjectBreakpointNameList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "list",
                             "List either the names for a breakpoint or the breakpoints for a given name.",
                             "breakpoint name list <command-options>"),
        m_name_options(),
        m_option_group(interpreter)
    {
        m_option_group.Append (&m_name_options);
        m_option_group.Finalize();
    }

    virtual
    ~CommandObjectBreakpointNameList () {}

  Options *
  GetOptions ()
  {
    return &m_option_group;
  }
  
protected:
protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());

        if (target == NULL)
        {
            result.AppendError ("Invalid target. No existing target or breakpoints.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        if (m_name_options.m_name.OptionWasSet())
        {
            const char *name = m_name_options.m_name.GetCurrentValue();
            Mutex::Locker locker;
            target->GetBreakpointList().GetListMutex(locker);
            
            BreakpointList &breakpoints = target->GetBreakpointList();
            for (BreakpointSP bp_sp : breakpoints.Breakpoints())
            {
                if (bp_sp->MatchesName(name))
                {
                    StreamString s;
                    bp_sp->GetDescription(&s, eDescriptionLevelBrief);
                    s.EOL();
                    result.AppendMessage(s.GetData());
                }
            }

        }
        else if (m_name_options.m_breakpoint.OptionWasSet())
        {
            BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue());
            if (bp_sp)
            {
                std::vector<std::string> names;
                bp_sp->GetNames (names);
                result.AppendMessage ("Names:");
                for (auto name : names)
                    result.AppendMessageWithFormat ("    %s\n", name.c_str());
            }
            else
            {
                result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n",
                                           m_name_options.m_breakpoint.GetCurrentValue());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        else
        {
            result.SetError ("Must specify -N or -B option to list.");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        return true;
    }

private:
    BreakpointNameOptionGroup m_name_options;
    OptionGroupOptions m_option_group;
};

//-------------------------------------------------------------------------
// CommandObjectMultiwordBreakpoint
//-------------------------------------------------------------------------
class CommandObjectBreakpointName : public CommandObjectMultiword
{
public:
    CommandObjectBreakpointName (CommandInterpreter &interpreter) :
        CommandObjectMultiword(interpreter,
                                "name",
                                "A set of commands to manage name tags for breakpoints",
                                "breakpoint name <command> [<command-options>]")
    {
        CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter));
        CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter));
        CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter));

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

    }

    virtual
    ~CommandObjectBreakpointName ()
    {
    }

};


//-------------------------------------------------------------------------
// CommandObjectMultiwordBreakpoint
//-------------------------------------------------------------------------
#pragma mark MultiwordBreakpoint

CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter) :
    CommandObjectMultiword (interpreter, 
                            "breakpoint",
                            "A set of commands for operating on breakpoints. Also see _regexp-break.",
                            "breakpoint <command> [<command-options>]")
{
    CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter));
    CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter));
    CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter));
    CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter));
    CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter));
    CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));
    CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
    CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter));
    CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter));

    list_command_object->SetCommandName ("breakpoint list");
    enable_command_object->SetCommandName("breakpoint enable");
    disable_command_object->SetCommandName("breakpoint disable");
    clear_command_object->SetCommandName("breakpoint clear");
    delete_command_object->SetCommandName("breakpoint delete");
    set_command_object->SetCommandName("breakpoint set");
    command_command_object->SetCommandName ("breakpoint command");
    modify_command_object->SetCommandName ("breakpoint modify");
    name_command_object->SetCommandName ("breakpoint name");

    LoadSubCommand ("list",       list_command_object);
    LoadSubCommand ("enable",     enable_command_object);
    LoadSubCommand ("disable",    disable_command_object);
    LoadSubCommand ("clear",      clear_command_object);
    LoadSubCommand ("delete",     delete_command_object);
    LoadSubCommand ("set",        set_command_object);
    LoadSubCommand ("command",    command_command_object);
    LoadSubCommand ("modify",     modify_command_object);
    LoadSubCommand ("name",       name_command_object);
}

CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
{
}

void
CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args,
                                             Target *target,
                                             bool allow_locations,
                                             CommandReturnObject &result,
                                             BreakpointIDList *valid_ids)
{
    // args can be strings representing 1). integers (for breakpoint ids)
    //                                  2). the full breakpoint & location canonical representation
    //                                  3). the word "to" or a hyphen, representing a range (in which case there
    //                                      had *better* be an entry both before & after of one of the first two types.
    //                                  4). A breakpoint name
    // If args is empty, we will use the last created breakpoint (if there is one.)

    Args temp_args;

    if (args.GetArgumentCount() == 0)
    {
        if (target->GetLastCreatedBreakpoint())
        {
            valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        } 
        else
        {   
            result.AppendError("No breakpoint specified and no last created breakpoint.");
            result.SetStatus (eReturnStatusFailed);
        }
        return;
    }
    
    // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
    // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for
    // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.

    BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args);

    // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:

    valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result);

    // At this point,  all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
    // and put into valid_ids.

    if (result.Succeeded())
    {
        // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
        // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.

        const size_t count = valid_ids->GetSize();
        for (size_t i = 0; i < count; ++i)
        {
            BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
            Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
            if (breakpoint != NULL)
            {
                const size_t num_locations = breakpoint->GetNumLocations();
                if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations)
                {
                    StreamString id_str;
                    BreakpointID::GetCanonicalReference (&id_str, 
                                                         cur_bp_id.GetBreakpointID(),
                                                         cur_bp_id.GetLocationID());
                    i = valid_ids->GetSize() + 1;
                    result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
                                                 id_str.GetData());
                    result.SetStatus (eReturnStatusFailed);
                }
            }
            else
            {
                i = valid_ids->GetSize() + 1;
                result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
                result.SetStatus (eReturnStatusFailed);
            }
        }
    }
}
