//===-- 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 "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/Host/StringConvert.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/StackFrame.h"
#include "lldb/Target/Target.h"

#include "llvm/ADT/StringRef.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;
}

// 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 arguments 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);
    }

    ~CommandObjectWatchpointList () override {}

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

    class CommandOptions : public Options
    {
    public:

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

        ~CommandOptions () override {}

        Error
        SetOptionValue (uint32_t option_idx, const char *option_arg) override
        {
            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 () override
        {
            m_level = lldb::eDescriptionLevelFull;
        }

        const OptionDefinition *
        GetDefinitions () override
        {
            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:
    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        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, NULL, 0, eArgTypeNone,
        "Give a brief description of the watchpoint (no location info)."},

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

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

    { 0, false, NULL, 0, 0, NULL, 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);
    }

    ~CommandObjectWatchpointEnable () override {}

protected:
    bool
    DoExecute (Args& command,
             CommandReturnObject &result) override
    {
        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. (%" PRIu64 " watchpoints)\n", (uint64_t)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);
    }


    ~CommandObjectWatchpointDisable () override {}

protected:
    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        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. (%" PRIu64 " watchpoints)\n", (uint64_t)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);
    }

    ~CommandObjectWatchpointDelete () override {}

protected:
    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        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. (%" PRIu64 " watchpoints)\n", (uint64_t)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);
    }

    ~CommandObjectWatchpointIgnore () override {}

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

    class CommandOptions : public Options
    {
    public:

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

        ~CommandOptions () override {}

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

            switch (short_option)
            {
                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;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }

        void
        OptionParsingStarting () override
        {
            m_ignore_count = 0;
        }

        const OptionDefinition *
        GetDefinitions () override
        {
            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:
    bool
    DoExecute (Args& command,
             CommandReturnObject &result) override
    {
        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. (%" PRIu64 " watchpoints)\n", (uint64_t)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, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
    { 0,                false, NULL,            0 , 0,                 NULL, 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);   
    }

    ~CommandObjectWatchpointModify () override {}

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

    class CommandOptions : public Options
    {
    public:

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

        ~CommandOptions () override {}

        Error
        SetOptionValue (uint32_t option_idx, const char *option_arg) override
        {
            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 () override
        {
            m_condition.clear();
            m_condition_passed = false;
        }
        
        const OptionDefinition*
        GetDefinitions () override
        {
            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:
    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        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, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
{ 0,                false, NULL,            0 , 0,                 NULL, 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,
                             eCommandRequiresFrame         |
                             eCommandTryTargetAPILock      |
                             eCommandProcessMustBeLaunched |
                             eCommandProcessMustBePaused   ),
        m_option_group (interpreter),
        m_option_watchpoint ()
    {
        SetHelpLong(
R"(
Examples:

(lldb) watchpoint set variable -w read_write my_global_var

)" "    Watches my_global_var for read/write access, with the region to watch \
corresponding to the byte size of the data type."
        );

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

    ~CommandObjectWatchpointSetVariable () override {}

    Options *
    GetOptions () override
    {
        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;
    }
    
    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        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);
        }
        
        CompilerType compiler_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;
            }
            compiler_type = valobj_sp->GetCompilerType();
        }
        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, &compiler_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=%" PRIu64 ", variable expression='%s').\n",
                                         addr, (uint64_t)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,
                          eCommandRequiresFrame         |
                          eCommandTryTargetAPILock      |
                          eCommandProcessMustBeLaunched |
                          eCommandProcessMustBePaused   ),
        m_option_group (interpreter),
        m_option_watchpoint ()
    {
        SetHelpLong(
R"(
Examples:

(lldb) watchpoint set expression -w write -x 1 -- foo + 32

    Watches write access for the 1-byte region pointed to by the address 'foo + 32')"
        );

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


    ~CommandObjectWatchpointSetExpression () override {}

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

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

protected:
    bool
    DoExecute (const char *raw_command, CommandReturnObject &result) override
    {
        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 (llvm::StringRef(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);
        
        ExpressionResults expr_result = target->EvaluateExpression (expr, 
                                                                   frame, 
                                                                   valobj_sp,
                                                                   options);
        if (expr_result != eExpressionCompleted)
        {
            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.
        CompilerType compiler_type(valobj_sp->GetCompilerType());
        
        Error error;
        Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_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=%" PRIu64 ").\n",
                                         addr, (uint64_t)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)));
    }


    ~CommandObjectWatchpointSet () override {}

};

//-------------------------------------------------------------------------
// 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()
{
}

