//===-- CommandObjectWatchpoint.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectWatchpoint.h"
#include "CommandObjectWatchpointCommand.h"

#include <vector>

#include "llvm/ADT/StringRef.h"

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/StreamString.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) {
  bool process_is_valid =
      target->GetProcessSP() && target->GetProcessSP()->IsAlive();
  if (!process_is_valid) {
    result.AppendError("There'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;
  llvm::StringRef first;
  llvm::StringRef second;
  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 (auto &entry : args.entries()) {
    if ((idx = WithRSAIndex(entry.ref())) == -1) {
      StrRefArgs.push_back(entry.ref());
      continue;
    }
    // The Arg contains the range specifier, split it, then.
    std::tie(first, second) = entry.ref().split(RSA[idx]);
    if (!first.empty())
      StrRefArgs.push_back(first);
    StrRefArgs.push_back(Minus);
    if (!second.empty())
      StrRefArgs.push_back(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.
  return !in_range;
}

// CommandObjectWatchpointList

// CommandObjectWatchpointList::Options
#pragma mark List::CommandOptions
#define LLDB_OPTIONS_watchpoint_list
#include "CommandOptions.inc"

#pragma mark List

class CommandObjectWatchpointList : public CommandObjectParsed {
public:
  CommandObjectWatchpointList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "watchpoint list",
            "List all watchpoints at configurable levels of detail.", nullptr,
            eCommandRequiresTarget),
        m_options() {
    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()
        : Options(),
          m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
                                                // brief descriptions
    {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status 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:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_level = lldb::eDescriptionLevelFull;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_watchpoint_list_options);
    }

    // Instance variables to hold the values for command options.

    lldb::DescriptionLevel m_level;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();

    if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
      uint32_t num_supported_hardware_watchpoints;
      Status 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;
};

// 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, eCommandRequiresTarget) {
    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 = &GetSelectedTarget();
    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, eCommandRequiresTarget) {
    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 = &GetSelectedTarget();
    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
#define LLDB_OPTIONS_watchpoint_delete
#include "CommandOptions.inc"

// 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, eCommandRequiresTarget),
        m_options() {
    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;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), m_force(false) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f':
        m_force = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return {};
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_force = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_watchpoint_delete_options);
    }

    // Instance variables to hold the values for command options.
    bool m_force;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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.empty()) {
      if (!m_options.m_force &&
          !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);
      return result.Succeeded();
    }

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

private:
  CommandOptions m_options;
};

// CommandObjectWatchpointIgnore

#pragma mark Ignore::CommandOptions
#define LLDB_OPTIONS_watchpoint_ignore
#include "CommandOptions.inc"

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, eCommandRequiresTarget),
        m_options() {
    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() : Options(), m_ignore_count(0) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'i':
        if (option_arg.getAsInteger(0, m_ignore_count))
          error.SetErrorStringWithFormat("invalid ignore count '%s'",
                                         option_arg.str().c_str());
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_ignore_count = 0;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_watchpoint_ignore_options);
    }

    // Instance variables to hold the values for command options.

    uint32_t m_ignore_count;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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;
};

// CommandObjectWatchpointModify

#pragma mark Modify::CommandOptions
#define LLDB_OPTIONS_watchpoint_modify
#include "CommandOptions.inc"

#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, eCommandRequiresTarget),
        m_options() {
    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() : Options(), m_condition(), m_condition_passed(false) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c':
        m_condition = std::string(option_arg);
        m_condition_passed = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_condition.clear();
      m_condition_passed = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_watchpoint_modify_options);
    }

    // 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 = &GetSelectedTarget();
    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;
};

// 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(), 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) {
    size_t old_size = variable_list.GetSize();
    Target *target = static_cast<Target *>(baton);
    if (target)
      target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
                                              variable_list);
    return variable_list.GetSize() - old_size;
  }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = 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...
    Status 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;

      Status 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(std::string(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.",
            "",
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
        m_option_group(), 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(llvm::StringRef raw_command,
                 CommandReturnObject &result) override {
    auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
    m_option_group.NotifyOptionParsingStarting(
        &exe_ctx); // This is a raw command, so notify the option group

    Target *target = GetDebugger().GetSelectedTarget().get();
    StackFrame *frame = m_exe_ctx.GetFramePtr();

    OptionsWithRaw args(raw_command);

    llvm::StringRef expr = args.GetRawPart();

    if (args.HasArgs())
      if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
                                 exe_ctx))
        return false;

    // If no argument is present, issue an error message.  There's no way to
    // set a watchpoint.
    if (raw_command.trim().empty()) {
      result.GetErrorStream().Printf("error: required argument missing; "
                                     "specify an expression to evaluate 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.SetTimeout(llvm::None);

    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() << "expression evaluated: \n" << expr << "\n";
      if (valobj_sp && !valobj_sp->GetError().Success())
        result.GetErrorStream() << valobj_sp->GetError().AsCString() << "\n";
      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());

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