//===-- 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
#include <vector>

// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"

// 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"

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 == nullptr)
    {
        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 == nullptr)
            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.",
                            nullptr),
        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 = default;

    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 = default;

        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 == nullptr)
        {
            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();

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

        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, nullptr, nullptr, 0, eArgTypeNone,
        "Give a brief description of the watchpoint (no location info)."},

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

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

    { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
};

//-------------------------------------------------------------------------
// 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.",
                            nullptr)
    {
        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 = default;

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

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

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

//-------------------------------------------------------------------------
// 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.",
                            nullptr)
    {
        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 = default;

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

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

        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.",
                            nullptr)
    {
        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 = default;

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

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

        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.",
                            nullptr),
        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 = default;

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

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

        ~CommandOptions() override = default;

        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;

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

        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, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
    { 0,                false, nullptr,            0 , 0,                 nullptr, nullptr, 0,    eArgTypeNone, nullptr }
};

//-------------------------------------------------------------------------
// 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.",
                            nullptr),
        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 = default;

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

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

        ~CommandOptions() override = default;

        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 != nullptr)
                        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;

        std::unique_lock<std::recursive_mutex> lock;
        target->GetWatchpointList().GetListMutex(lock);

        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, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
{ 0,                false, nullptr,            0 , 0,                 nullptr, nullptr, 0,    eArgTypeNone, nullptr }
};

//-------------------------------------------------------------------------
// 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 '-s' option to specify the byte size to watch for. "
                            "If no '-w' option is specified, it defaults to write. "
                            "If no '-s' 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.",
                            nullptr,
                            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 '-s' 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 = default;

    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(nullptr);
            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(nullptr))
                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 '-s' option to specify the byte size to watch for. "
                         "If no '-w' option is specified, it defaults to write. "
                         "If no '-s' 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.",
                         nullptr,
                         eCommandRequiresFrame         |
                         eCommandTryTargetAPILock      |
                         eCommandProcessMustBeLaunched |
                         eCommandProcessMustBePaused   ),
        m_option_group (interpreter),
        m_option_watchpoint ()
    {
        SetHelpLong(
R"(
Examples:

(lldb) watchpoint set expression -w write -s 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 '-s' 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 = default;

    // 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 = nullptr;
        if (raw_command[0] == '-')
        {
            // We have some options and these options MUST end with --.
            const char *end_options = nullptr;
            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 == nullptr)
            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(nullptr))
                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", "Commands for setting a watchpoint.",
                                 "watchpoint set <subcommand> [<subcommand-options>]")
    {
        
        LoadSubCommand ("variable",   CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter)));
        LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter)));
    }

    ~CommandObjectWatchpointSet() override = default;
};

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

CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "watchpoint", "Commands for operating on watchpoints.",
                             "watchpoint <subcommand> [<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() = default;
