//===-- 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/Host/StringConvert.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionValueBoolean.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/LanguageRuntime.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),
            m_all_files (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 'A':
                    m_all_files = true;
                    break;

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

                case 'C':
                {
                    bool success;
                    m_column = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
                    if (!success)
                        error.SetErrorStringWithFormat("invalid column number: %s", option_arg);
                    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:
                        case eLanguageTypeC_plus_plus_14:
                            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 = StringConvert::ToUInt32(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':
                {
                    bool success;
                    m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
                    if (!success)
                        error.SetErrorStringWithFormat ("invalid line number: %s.", option_arg);
                    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 = StringConvert::ToUInt64(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 = StringConvert::ToUInt32(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();
            m_all_files = 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.

        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;
        bool m_all_files;

    };

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 && !m_options.m_all_files)
                    {
                        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_9, false, "all-files", 'A', OptionParser::eNoArgument,   NULL, NULL, 0, eArgTypeNone,
        "All files are searched for source pattern matches." },

    { 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 = StringConvert::ToUInt32(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 = StringConvert::ToUInt64(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 = StringConvert::ToUInt32 (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 = StringConvert::ToUInt32 (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.SetValueFromString(option_value);
            break;
          
        case 'B':
            if (m_breakpoint.SetValueFromString(option_value).Fail())
                error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value);
            break;
        case 'D':
            if (m_use_dummy.SetValueFromString(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:
    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);
            }
        }
    }
}
