//===-- CommandObjectWatchpoint.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 "CommandObjectWatchpoint.h"
#include "CommandObjectWatchpointCommand.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Target.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

static void
AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level)
{
    s->IndentMore();
    wp->GetDescription(s, level);
    s->IndentLess();
    s->EOL();
}

static bool
CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result)
{
    if (target == NULL)
    {
        result.AppendError ("Invalid target.  No existing target or watchpoints.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive();
    if (!process_is_valid)
    {
        result.AppendError ("Thre's no process or it is not alive.");
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    // Target passes our checks, return true.
    return true;
}

// FIXME: This doesn't seem to be the right place for this functionality.
#include "llvm/ADT/StringRef.h"
static inline void StripLeadingSpaces(llvm::StringRef &Str)
{
    while (!Str.empty() && isspace(Str[0]))
        Str = Str.substr(1);
}

// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
static const char* RSA[4] = { "-", "to", "To", "TO" };

// Return the index to RSA if found; otherwise -1 is returned.
static int32_t
WithRSAIndex(llvm::StringRef &Arg)
{
    
    uint32_t i;
    for (i = 0; i < 4; ++i)
        if (Arg.find(RSA[i]) != llvm::StringRef::npos)
            return i;
    return -1;
}

// Return true if wp_ids is successfully populated with the watch ids.
// False otherwise.
bool
CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args, std::vector<uint32_t> &wp_ids)
{
    // Pre-condition: args.GetArgumentCount() > 0.
    if (args.GetArgumentCount() == 0)
    {
        if (target == NULL)
            return false;
        WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
        if (watch_sp)
        {
            wp_ids.push_back(watch_sp->GetID());
            return true;
        }
        else
            return false;
    }

    llvm::StringRef Minus("-");
    std::vector<llvm::StringRef> StrRefArgs;
    std::pair<llvm::StringRef, llvm::StringRef> Pair;
    size_t i;
    int32_t idx;
    // Go through the argments and make a canonical form of arg list containing
    // only numbers with possible "-" in between.
    for (i = 0; i < args.GetArgumentCount(); ++i) {
        llvm::StringRef Arg(args.GetArgumentAtIndex(i));
        if ((idx = WithRSAIndex(Arg)) == -1) {
            StrRefArgs.push_back(Arg);
            continue;
        }
        // The Arg contains the range specifier, split it, then.
        Pair = Arg.split(RSA[idx]);
        if (!Pair.first.empty())
            StrRefArgs.push_back(Pair.first);
        StrRefArgs.push_back(Minus);
        if (!Pair.second.empty())
            StrRefArgs.push_back(Pair.second);
    }
    // Now process the canonical list and fill in the vector of uint32_t's.
    // If there is any error, return false and the client should ignore wp_ids.
    uint32_t beg, end, id;
    size_t size = StrRefArgs.size();
    bool in_range = false;
    for (i = 0; i < size; ++i) {
        llvm::StringRef Arg = StrRefArgs[i];
        if (in_range) {
            // Look for the 'end' of the range.  Note StringRef::getAsInteger()
            // returns true to signify error while parsing.
            if (Arg.getAsInteger(0, end))
                return false;
            // Found a range!  Now append the elements.
            for (id = beg; id <= end; ++id)
                wp_ids.push_back(id);
            in_range = false;
            continue;
        }
        if (i < (size - 1) && StrRefArgs[i+1] == Minus) {
            if (Arg.getAsInteger(0, beg))
                return false;
            // Turn on the in_range flag, we are looking for end of range next.
            ++i; in_range = true;
            continue;
        }
        // Otherwise, we have a simple ID.  Just append it.
        if (Arg.getAsInteger(0, beg))
            return false;
        wp_ids.push_back(beg);
    }
    // It is an error if after the loop, we're still in_range.
    if (in_range)
        return false;

    return true; // Success!
}

//-------------------------------------------------------------------------
// CommandObjectWatchpointList
//-------------------------------------------------------------------------
#pragma mark List

class CommandObjectWatchpointList : public CommandObjectParsed
{
public:
    CommandObjectWatchpointList (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter, 
                             "watchpoint list",
                             "List all watchpoints at configurable levels of detail.",
                             NULL),
        m_options(interpreter)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back(arg);
    }

    virtual
    ~CommandObjectWatchpointList () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options(interpreter),
            m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions
        {
        }

        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 'f':
                    m_level = lldb::eDescriptionLevelFull;
                    break;
                case 'v':
                    m_level = lldb::eDescriptionLevelVerbose;
                    break;
                default:
                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_level = lldb::eDescriptionLevelFull;
        }

        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;
    };

protected:
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        if (target == NULL)
        {
            result.AppendError ("Invalid target. No current target or watchpoints.");
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            return true;
        }

        if (target->GetProcessSP() && target->GetProcessSP()->IsAlive())
        {
            uint32_t num_supported_hardware_watchpoints;
            Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints);
            if (error.Success())
                result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n",
                                               num_supported_hardware_watchpoints);
        }

        const WatchpointList &watchpoints = target->GetWatchpointList();
        Mutex::Locker locker;
        target->GetWatchpointList().GetListMutex(locker);

        size_t num_watchpoints = watchpoints.GetSize();

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

        Stream &output_stream = result.GetOutputStream();

        if (command.GetArgumentCount() == 0)
        {
            // No watchpoint selected; show info about all currently set watchpoints.
            result.AppendMessage ("Current watchpoints:");
            for (size_t i = 0; i < num_watchpoints; ++i)
            {
                Watchpoint *wp = watchpoints.GetByIndex(i).get();
                AddWatchpointDescription(&output_stream, wp, m_options.m_level);
            }
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; enable them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
            {
                Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
                if (wp)
                    AddWatchpointDescription(&output_stream, wp, m_options.m_level);
                result.SetStatus(eReturnStatusSuccessFinishNoResult);
            }
        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

//-------------------------------------------------------------------------
// CommandObjectWatchpointList::Options
//-------------------------------------------------------------------------
#pragma mark List::CommandOptions
OptionDefinition
CommandObjectWatchpointList::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_1, false, "brief",    'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
        "Give a brief description of the watchpoint (no location info)."},

    { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
        "Give a full description of the watchpoint and its locations."},

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

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

//-------------------------------------------------------------------------
// CommandObjectWatchpointEnable
//-------------------------------------------------------------------------
#pragma mark Enable

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

    virtual
    ~CommandObjectWatchpointEnable () {}

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

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

        const WatchpointList &watchpoints = target->GetWatchpointList();

        size_t num_watchpoints = watchpoints.GetSize();

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

        if (command.GetArgumentCount() == 0)
        {
            // No watchpoint selected; enable all currently set watchpoints.
            target->EnableAllWatchpoints();
            result.AppendMessageWithFormat("All watchpoints enabled. (%zu watchpoints)\n", num_watchpoints);
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; enable them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            int count = 0;
            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
                if (target->EnableWatchpointByID(wp_ids[i]))
                    ++count;
            result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }

        return result.Succeeded();
    }

private:
};

//-------------------------------------------------------------------------
// CommandObjectWatchpointDisable
//-------------------------------------------------------------------------
#pragma mark Disable

class CommandObjectWatchpointDisable : public CommandObjectParsed
{
public:
    CommandObjectWatchpointDisable (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "watchpoint disable",
                             "Disable the specified watchpoint(s) without removing it/them.  If no watchpoints are specified, disable them all.",
                             NULL)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back(arg);
    }


    virtual
    ~CommandObjectWatchpointDisable () {}

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

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

        const WatchpointList &watchpoints = target->GetWatchpointList();
        size_t num_watchpoints = watchpoints.GetSize();

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

        if (command.GetArgumentCount() == 0)
        {
            // No watchpoint selected; disable all currently set watchpoints.
            if (target->DisableAllWatchpoints())
            {
                result.AppendMessageWithFormat("All watchpoints disabled. (%zu watchpoints)\n", num_watchpoints);
                result.SetStatus(eReturnStatusSuccessFinishNoResult);
            }
            else
            {
                result.AppendError("Disable all watchpoints failed\n");
                result.SetStatus(eReturnStatusFailed);
            }
        }
        else
        {
            // Particular watchpoints selected; disable them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            int count = 0;
            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
                if (target->DisableWatchpointByID(wp_ids[i]))
                    ++count;
            result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }

        return result.Succeeded();
    }

};

//-------------------------------------------------------------------------
// CommandObjectWatchpointDelete
//-------------------------------------------------------------------------
#pragma mark Delete

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

    virtual
    ~CommandObjectWatchpointDelete () {}

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

        Mutex::Locker locker;
        target->GetWatchpointList().GetListMutex(locker);
        
        const WatchpointList &watchpoints = target->GetWatchpointList();

        size_t num_watchpoints = watchpoints.GetSize();

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

        if (command.GetArgumentCount() == 0)
        {
            if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true))
            {
                result.AppendMessage("Operation cancelled...");
            }
            else
            {
                target->RemoveAllWatchpoints();
                result.AppendMessageWithFormat("All watchpoints removed. (%zu watchpoints)\n", num_watchpoints);
            }
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; delete them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            int count = 0;
            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
                if (target->RemoveWatchpointByID(wp_ids[i]))
                    ++count;
            result.AppendMessageWithFormat("%d watchpoints deleted.\n",count);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }

        return result.Succeeded();
    }

};

//-------------------------------------------------------------------------
// CommandObjectWatchpointIgnore
//-------------------------------------------------------------------------

class CommandObjectWatchpointIgnore : public CommandObjectParsed
{
public:
    CommandObjectWatchpointIgnore (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "watchpoint ignore",
                             "Set ignore count on the specified watchpoint(s).  If no watchpoints are specified, set them all.",
                             NULL),
        m_options (interpreter)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back(arg);
    }

    virtual
    ~CommandObjectWatchpointIgnore () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_ignore_count (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 'i':
                {
                    m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
                    if (m_ignore_count == UINT32_MAX)
                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
                }
                break;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_ignore_count = 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.

        uint32_t m_ignore_count;
    };

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

        Mutex::Locker locker;
        target->GetWatchpointList().GetListMutex(locker);
        
        const WatchpointList &watchpoints = target->GetWatchpointList();

        size_t num_watchpoints = watchpoints.GetSize();

        if (num_watchpoints == 0)
        {
            result.AppendError("No watchpoints exist to be ignored.");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (command.GetArgumentCount() == 0)
        {
            target->IgnoreAllWatchpoints(m_options.m_ignore_count);
            result.AppendMessageWithFormat("All watchpoints ignored. (%zu watchpoints)\n", num_watchpoints);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; ignore them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            int count = 0;
            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
                if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
                    ++count;
            result.AppendMessageWithFormat("%d watchpoints ignored.\n",count);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

#pragma mark Ignore::CommandOptions
OptionDefinition
CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
{
    { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
    { 0,                false, NULL,            0 , 0,                 NULL, 0,    eArgTypeNone, NULL }
};


//-------------------------------------------------------------------------
// CommandObjectWatchpointModify
//-------------------------------------------------------------------------
#pragma mark Modify

class CommandObjectWatchpointModify : public CommandObjectParsed
{
public:

    CommandObjectWatchpointModify (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "watchpoint modify", 
                             "Modify the options on a watchpoint or set of watchpoints in the executable.  "
                             "If no watchpoint is specified, act on the last created watchpoint.  "
                             "Passing an empty argument clears the modification.", 
                             NULL),
        m_options (interpreter)
    {
        CommandArgumentEntry arg;
        CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
        // Add the entry for the first argument for this command to the object's arguments vector.
        m_arguments.push_back (arg);   
    }

    virtual
    ~CommandObjectWatchpointModify () {}

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

    class CommandOptions : public Options
    {
    public:

        CommandOptions (CommandInterpreter &interpreter) :
            Options (interpreter),
            m_condition (),
            m_condition_passed (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;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting ()
        {
            m_condition.clear();
            m_condition_passed = 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;
        bool m_condition_passed;
    };

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

        Mutex::Locker locker;
        target->GetWatchpointList().GetListMutex(locker);
        
        const WatchpointList &watchpoints = target->GetWatchpointList();

        size_t num_watchpoints = watchpoints.GetSize();

        if (num_watchpoints == 0)
        {
            result.AppendError("No watchpoints exist to be modified.");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (command.GetArgumentCount() == 0)
        {
            WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
            wp_sp->SetCondition(m_options.m_condition.c_str());
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; set condition on them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            int count = 0;
            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
            {
                WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
                if (wp_sp)
                {
                    wp_sp->SetCondition(m_options.m_condition.c_str());
                    ++count;
                }
            }
            result.AppendMessageWithFormat("%d watchpoints modified.\n",count);
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }

        return result.Succeeded();
    }

private:
    CommandOptions m_options;
};

#pragma mark Modify::CommandOptions
OptionDefinition
CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
{ 0,                false, NULL,            0 , 0,                 NULL, 0,    eArgTypeNone, NULL }
};

//-------------------------------------------------------------------------
// CommandObjectWatchpointSetVariable
//-------------------------------------------------------------------------
#pragma mark SetVariable

class CommandObjectWatchpointSetVariable : public CommandObjectParsed
{
public:

    CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "watchpoint set variable",
                             "Set a watchpoint on a variable. "
                             "Use the '-w' option to specify the type of watchpoint and "
                             "the '-x' option to specify the byte size to watch for. "
                             "If no '-w' option is specified, it defaults to write. "
                             "If no '-x' option is specified, it defaults to the variable's "
                             "byte size. "
                             "Note that there are limited hardware resources for watchpoints. "
                             "If watchpoint setting fails, consider disable/delete existing ones "
                             "to free up resources.",
                             NULL,
                             eFlagRequiresFrame         |
                             eFlagTryTargetAPILock      |
                             eFlagProcessMustBeLaunched |
                             eFlagProcessMustBePaused   ),
        m_option_group (interpreter),
        m_option_watchpoint ()
    {
        SetHelpLong(
    "Examples: \n\
    \n\
        watchpoint set variable -w read_write my_global_var \n\
        # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");

        CommandArgumentEntry arg;
        CommandArgumentData var_name_arg;
            
        // Define the only variant of this arg.
        var_name_arg.arg_type = eArgTypeVarName;
        var_name_arg.arg_repetition = eArgRepeatPlain;

        // Push the variant into the argument entry.
        arg.push_back (var_name_arg);
            
        // Push the data for the only argument into the m_arguments vector.
        m_arguments.push_back (arg);

        // Absorb the '-w' and '-x' options into our option group.
        m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Finalize();
    }

    virtual
    ~CommandObjectWatchpointSetVariable () {}

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

protected:
    static size_t GetVariableCallback (void *baton,
                                       const char *name,
                                       VariableList &variable_list)
    {
        Target *target = static_cast<Target *>(baton);
        if (target)
        {
            return target->GetImages().FindGlobalVariables (ConstString(name),
                                                            true,
                                                            UINT32_MAX,
                                                            variable_list);
        }
        return 0;
    }
    
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        StackFrame *frame = m_exe_ctx.GetFramePtr();

        // If no argument is present, issue an error message.  There's no way to set a watchpoint.
        if (command.GetArgumentCount() <= 0)
        {
            result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        // If no '-w' is specified, default to '-w write'.
        if (!m_option_watchpoint.watch_type_specified)
        {
            m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
        }

        // We passed the sanity check for the command.
        // Proceed to set the watchpoint now.
        lldb::addr_t addr = 0;
        size_t size = 0;

        VariableSP var_sp;
        ValueObjectSP valobj_sp;
        Stream &output_stream = result.GetOutputStream();

        // A simple watch variable gesture allows only one argument.
        if (command.GetArgumentCount() != 1)
        {
            result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        // Things have checked out ok...
        Error error;
        uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
                                     StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
        valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 
                                                              eNoDynamicValues, 
                                                              expr_path_options,
                                                              var_sp,
                                                              error);
        
        if (!valobj_sp)
        {
            // Not in the frame; let's check the globals.
            
            VariableList variable_list;
            ValueObjectList valobj_list;
            
            Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0),
                                                                       m_exe_ctx.GetBestExecutionContextScope(),
                                                                       GetVariableCallback,
                                                                       target,
                                                                       variable_list,
                                                                       valobj_list));
            
            if (valobj_list.GetSize())
                valobj_sp = valobj_list.GetValueObjectAtIndex(0);
        }
        
        ClangASTType clang_type;
        
        if (valobj_sp)
        {
            AddressType addr_type;
            addr = valobj_sp->GetAddressOf(false, &addr_type);
            if (addr_type == eAddressTypeLoad)
            {
                // We're in business.
                // Find out the size of this variable.
                size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
                                                           : m_option_watchpoint.watch_size;
            }
            clang_type = valobj_sp->GetClangType();
        }
        else
        {
            const char *error_cstr = error.AsCString(NULL);
            if (error_cstr)
                result.GetErrorStream().Printf("error: %s\n", error_cstr);
            else
                result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n",
                                                command.GetArgumentAtIndex(0));
            return false;
        }

        // Now it's time to create the watchpoint.
        uint32_t watch_type = m_option_watchpoint.watch_type;
        
        error.Clear();
        Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get();
        if (wp)
        {
            wp->SetWatchSpec(command.GetArgumentAtIndex(0));
            wp->SetWatchVariable(true);
            if (var_sp && var_sp->GetDeclaration().GetFile())
            {
                StreamString ss;
                // True to show fullpath for declaration file.
                var_sp->GetDeclaration().DumpStopContext(&ss, true);
                wp->SetDeclInfo(ss.GetString());
            }
            output_stream.Printf("Watchpoint created: ");
            wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
            output_stream.EOL();
            result.SetStatus(eReturnStatusSuccessFinishResult);
        }
        else
        {
            result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu, variable expression='%s').\n",
                                         addr, size, command.GetArgumentAtIndex(0));
            if (error.AsCString(NULL))
                result.AppendError(error.AsCString());
            result.SetStatus(eReturnStatusFailed);
        }

        return result.Succeeded();
    }

private:
    OptionGroupOptions m_option_group;
    OptionGroupWatchpoint m_option_watchpoint;
};

//-------------------------------------------------------------------------
// CommandObjectWatchpointSetExpression
//-------------------------------------------------------------------------
#pragma mark Set

class CommandObjectWatchpointSetExpression : public CommandObjectRaw
{
public:

    CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) :
        CommandObjectRaw (interpreter,
                          "watchpoint set expression",
                          "Set a watchpoint on an address by supplying an expression. "
                          "Use the '-w' option to specify the type of watchpoint and "
                          "the '-x' option to specify the byte size to watch for. "
                          "If no '-w' option is specified, it defaults to write. "
                          "If no '-x' option is specified, it defaults to the target's "
                          "pointer byte size. "
                          "Note that there are limited hardware resources for watchpoints. "
                          "If watchpoint setting fails, consider disable/delete existing ones "
                          "to free up resources.",
                          NULL,
                          eFlagRequiresFrame         |
                          eFlagTryTargetAPILock      |
                          eFlagProcessMustBeLaunched |
                          eFlagProcessMustBePaused   ),
        m_option_group (interpreter),
        m_option_watchpoint ()
    {
        SetHelpLong(
    "Examples: \n\
    \n\
        watchpoint set expression -w write -x 1 -- foo + 32\n\
        # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");

        CommandArgumentEntry arg;
        CommandArgumentData expression_arg;
            
        // Define the only variant of this arg.
        expression_arg.arg_type = eArgTypeExpression;
        expression_arg.arg_repetition = eArgRepeatPlain;

        // Push the only variant into the argument entry.
        arg.push_back (expression_arg);
            
        // Push the data for the only argument into the m_arguments vector.
        m_arguments.push_back (arg);

        // Absorb the '-w' and '-x' options into our option group.
        m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Finalize();
    }


    virtual
    ~CommandObjectWatchpointSetExpression () {}

    // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
    virtual bool
    WantsCompletion() { return true; }

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

protected:
    virtual bool
    DoExecute (const char *raw_command, CommandReturnObject &result)
    {
        m_option_group.NotifyOptionParsingStarting(); // This is a raw command, so notify the option group
        
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        StackFrame *frame = m_exe_ctx.GetFramePtr();

        Args command(raw_command);
        const char *expr = NULL;
        if (raw_command[0] == '-')
        {
            // We have some options and these options MUST end with --.
            const char *end_options = NULL;
            const char *s = raw_command;
            while (s && s[0])
            {
                end_options = ::strstr (s, "--");
                if (end_options)
                {
                    end_options += 2; // Get past the "--"
                    if (::isspace (end_options[0]))
                    {
                        expr = end_options;
                        while (::isspace (*expr))
                            ++expr;
                        break;
                    }
                }
                s = end_options;
            }
            
            if (end_options)
            {
                Args args (raw_command, end_options - raw_command);
                if (!ParseOptions (args, result))
                    return false;
                
                Error error (m_option_group.NotifyOptionParsingFinished());
                if (error.Fail())
                {
                    result.AppendError (error.AsCString());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
        }

        if (expr == NULL)
            expr = raw_command;

        // If no argument is present, issue an error message.  There's no way to set a watchpoint.
        if (command.GetArgumentCount() == 0)
        {
            result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the address to watch for\n");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        // If no '-w' is specified, default to '-w write'.
        if (!m_option_watchpoint.watch_type_specified)
        {
            m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
        }

        // We passed the sanity check for the command.
        // Proceed to set the watchpoint now.
        lldb::addr_t addr = 0;
        size_t size = 0;

        ValueObjectSP valobj_sp;

        // Use expression evaluation to arrive at the address to watch.
        EvaluateExpressionOptions options;
        options.SetCoerceToId(false);
        options.SetUnwindOnError(true);
        options.SetKeepInMemory(false);
        options.SetTryAllThreads(true);
        options.SetTimeoutUsec(0);
        
        ExecutionResults expr_result = target->EvaluateExpression (expr, 
                                                                   frame, 
                                                                   valobj_sp,
                                                                   options);
        if (expr_result != eExecutionCompleted)
        {
            result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
            result.GetErrorStream().Printf("expression evaluated: %s\n", expr);
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        // Get the address to watch.
        bool success = false;
        addr = valobj_sp->GetValueAsUnsigned(0, &success);
        if (!success)
        {
            result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        
        if (m_option_watchpoint.watch_size != 0)
            size = m_option_watchpoint.watch_size;
        else
            size = target->GetArchitecture().GetAddressByteSize();

        // Now it's time to create the watchpoint.
        uint32_t watch_type = m_option_watchpoint.watch_type;
        
        // Fetch the type from the value object, the type of the watched object is the pointee type
        /// of the expression, so convert to that if we  found a valid type.
        ClangASTType clang_type(valobj_sp->GetClangType());
        
        Error error;
        Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get();
        if (wp)
        {
            Stream &output_stream = result.GetOutputStream();
            output_stream.Printf("Watchpoint created: ");
            wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
            output_stream.EOL();
            result.SetStatus(eReturnStatusSuccessFinishResult);
        }
        else
        {
            result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%zu).\n",
                                         addr, size);
            if (error.AsCString(NULL))
                result.AppendError(error.AsCString());
            result.SetStatus(eReturnStatusFailed);
        }

        return result.Succeeded();
    }

private:
    OptionGroupOptions m_option_group;
    OptionGroupWatchpoint m_option_watchpoint;
};

//-------------------------------------------------------------------------
// CommandObjectWatchpointSet
//-------------------------------------------------------------------------
#pragma mark Set

class CommandObjectWatchpointSet : public CommandObjectMultiword
{
public:

    CommandObjectWatchpointSet (CommandInterpreter &interpreter) :
        CommandObjectMultiword (interpreter,
                                "watchpoint set",
                                "A set of commands for setting a watchpoint.",
                                "watchpoint set <subcommand> [<subcommand-options>]")
    {
        
        LoadSubCommand ("variable",   CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter)));
        LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter)));
    }


    virtual
    ~CommandObjectWatchpointSet () {}

};

//-------------------------------------------------------------------------
// CommandObjectMultiwordWatchpoint
//-------------------------------------------------------------------------
#pragma mark MultiwordWatchpoint

CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) :
    CommandObjectMultiword (interpreter, 
                            "watchpoint",
                            "A set of commands for operating on watchpoints.",
                            "watchpoint <command> [<command-options>]")
{
    CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter));
    CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
    CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
    CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
    CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter));
    CommandObjectSP command_command_object (new CommandObjectWatchpointCommand (interpreter));
    CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter));
    CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter));

    list_command_object->SetCommandName ("watchpoint list");
    enable_command_object->SetCommandName("watchpoint enable");
    disable_command_object->SetCommandName("watchpoint disable");
    delete_command_object->SetCommandName("watchpoint delete");
    ignore_command_object->SetCommandName("watchpoint ignore");
    command_command_object->SetCommandName ("watchpoint command");
    modify_command_object->SetCommandName("watchpoint modify");
    set_command_object->SetCommandName("watchpoint set");

    LoadSubCommand ("list",       list_command_object);
    LoadSubCommand ("enable",     enable_command_object);
    LoadSubCommand ("disable",    disable_command_object);
    LoadSubCommand ("delete",     delete_command_object);
    LoadSubCommand ("ignore",     ignore_command_object);
    LoadSubCommand ("command",    command_command_object);
    LoadSubCommand ("modify",     modify_command_object);
    LoadSubCommand ("set",        set_command_object);
}

CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
{
}

