/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmListCommand.h"

#include <cassert>
#include <cstdio>
#include <functional>
#include <set>
#include <sstream>
#include <stdexcept>
#include <utility>
#include <vector>

#include <cm/memory>
#include <cm/optional>
#include <cmext/algorithm>
#include <cmext/string_view>

#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSubcommandTable.h"
#include "cmValue.h"

namespace {

bool GetIndexArg(std::string const& arg, int* idx, cmMakefile& mf)
{
  long value;
  if (!cmStrToLong(arg, &value)) {
    switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) {
      case cmPolicies::WARN: {
        // Default is to warn and use old behavior OLD behavior is to allow
        // compatibility, so issue a warning and use the previous behavior.
        std::string warn =
          cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121),
                   " Invalid list index \"", arg, "\".");
        mf.IssueMessage(MessageType::AUTHOR_WARNING, warn);
        CM_FALLTHROUGH;
      }
      case cmPolicies::OLD:
        // OLD behavior is to allow compatibility, so just ignore the
        // situation.
        break;
      case cmPolicies::NEW:
        return false;
    }
  }

  // Truncation is happening here, but it had always been happening here.
  *idx = static_cast<int>(value);

  return true;
}

bool GetListString(std::string& listString, std::string const& var,
                   cmMakefile const& makefile)
{
  // get the old value
  cmValue cacheValue = makefile.GetDefinition(var);
  if (!cacheValue) {
    return false;
  }
  listString = *cacheValue;
  return true;
}

cm::optional<cmList> GetList(std::string const& var,
                             cmMakefile const& makefile)
{
  cm::optional<cmList> list;

  std::string listString;
  if (!GetListString(listString, var, makefile)) {
    return list;
  }
  // if the size of the list
  if (listString.empty()) {
    list.emplace();
    return list;
  }
  // expand the variable into a list
  list.emplace(listString, cmList::EmptyElements::Yes);
  // if no empty elements then just return
  if (!cm::contains(*list, std::string())) {
    return list;
  }
  return list;
}

bool HandleLengthCommand(std::vector<std::string> const& args,
                         cmExecutionStatus& status)
{
  if (args.size() != 3) {
    status.SetError("sub-command LENGTH requires two arguments.");
    return false;
  }

  std::string const& listName = args[1];
  std::string const& variableName = args.back();

  auto list = GetList(listName, status.GetMakefile());
  status.GetMakefile().AddDefinition(variableName,
                                     std::to_string(list ? list->size() : 0));

  return true;
}

bool HandleGetCommand(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  if (args.size() < 4) {
    status.SetError("sub-command GET requires at least three arguments.");
    return false;
  }

  std::string const& listName = args[1];
  std::string const& variableName = args.back();
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());
  if (!list) {
    status.GetMakefile().AddDefinition(variableName, "NOTFOUND");
    return true;
  }
  // FIXME: Add policy to make non-existing lists an error like empty lists.
  if (list->empty()) {
    status.SetError("GET given empty list");
    return false;
  }

  std::vector<int> indexes;
  for (std::size_t cc = 2; cc < args.size() - 1; cc++) {
    int index;
    if (!GetIndexArg(args[cc], &index, status.GetMakefile())) {
      status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
      return false;
    }
    indexes.push_back(index);
  }

  try {
    auto values = list->get_items(indexes.begin(), indexes.end());
    status.GetMakefile().AddDefinition(variableName, values.to_string());
    return true;
  } catch (std::out_of_range& e) {
    status.SetError(e.what());
    return false;
  }
}

bool HandleAppendCommand(std::vector<std::string> const& args,
                         cmExecutionStatus& status)
{
  assert(args.size() >= 2);

  // Skip if nothing to append.
  if (args.size() < 3) {
    return true;
  }

  cmMakefile& makefile = status.GetMakefile();
  std::string const& listName = args[1];
  // expand the variable
  std::string listString;
  GetListString(listString, listName, makefile);

  makefile.AddDefinition(
    listName, cmList::append(listString, args.begin() + 2, args.end()));
  return true;
}

bool HandlePrependCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  assert(args.size() >= 2);

  // Skip if nothing to prepend.
  if (args.size() < 3) {
    return true;
  }

  cmMakefile& makefile = status.GetMakefile();
  std::string const& listName = args[1];
  // expand the variable
  std::string listString;
  GetListString(listString, listName, makefile);

  makefile.AddDefinition(
    listName, cmList::prepend(listString, args.begin() + 2, args.end()));
  return true;
}

bool HandlePopBackCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  assert(args.size() >= 2);

  cmMakefile& makefile = status.GetMakefile();
  auto ai = args.cbegin();
  ++ai; // Skip subcommand name
  std::string const& listName = *ai++;
  auto list = GetList(listName, makefile);

  if (!list) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
    return true;
  }

  if (!list->empty()) {
    if (ai == args.cend()) {
      // No variables are given... Just remove one element.
      list->pop_back();
    } else {
      // Ok, assign elements to be removed to the given variables
      for (; !list->empty() && ai != args.cend(); ++ai) {
        assert(!ai->empty());
        makefile.AddDefinition(*ai, list->back());
        list->pop_back();
      }
      // Undefine the rest variables if the list gets empty earlier...
      for (; ai != args.cend(); ++ai) {
        makefile.RemoveDefinition(*ai);
      }
    }

    makefile.AddDefinition(listName, list->to_string());

  } else if (ai !=
             args.cend()) { // The list is empty, but some args were given
    // Need to *undefine* 'em all, cuz there are no items to assign...
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
  }

  return true;
}

bool HandlePopFrontCommand(std::vector<std::string> const& args,
                           cmExecutionStatus& status)
{
  assert(args.size() >= 2);

  cmMakefile& makefile = status.GetMakefile();
  auto ai = args.cbegin();
  ++ai; // Skip subcommand name
  std::string const& listName = *ai++;
  auto list = GetList(listName, makefile);

  if (!list) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
    return true;
  }

  if (!list->empty()) {
    if (ai == args.cend()) {
      // No variables are given... Just remove one element.
      list->pop_front();
    } else {
      // Ok, assign elements to be removed to the given variables
      auto vi = list->begin();
      for (; vi != list->end() && ai != args.cend(); ++ai, ++vi) {
        assert(!ai->empty());
        makefile.AddDefinition(*ai, *vi);
      }
      list->erase(list->begin(), vi);
      // Undefine the rest variables if the list gets empty earlier...
      for (; ai != args.cend(); ++ai) {
        makefile.RemoveDefinition(*ai);
      }
    }

    makefile.AddDefinition(listName, list->to_string());

  } else if (ai !=
             args.cend()) { // The list is empty, but some args were given
    // Need to *undefine* 'em all, cuz there are no items to assign...
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
  }

  return true;
}

bool HandleFindCommand(std::vector<std::string> const& args,
                       cmExecutionStatus& status)
{
  if (args.size() != 4) {
    status.SetError("sub-command FIND requires three arguments.");
    return false;
  }

  std::string const& listName = args[1];
  std::string const& variableName = args.back();
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    status.GetMakefile().AddDefinition(variableName, "-1");
    return true;
  }

  auto index = list->find(args[2]);
  status.GetMakefile().AddDefinition(
    variableName, index == cmList::npos ? "-1" : std::to_string(index));
  return true;
}

bool HandleInsertCommand(std::vector<std::string> const& args,
                         cmExecutionStatus& status)
{
  if (args.size() < 4) {
    status.SetError("sub-command INSERT requires at least three arguments.");
    return false;
  }

  std::string const& listName = args[1];

  // expand the variable
  int index;
  if (!GetIndexArg(args[2], &index, status.GetMakefile())) {
    status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
    return false;
  }
  auto list = GetList(listName, status.GetMakefile());
  if (!list) {
    list = cmList{};
  }

  try {
    list->insert_items(index, args.begin() + 3, args.end(),
                       cmList::ExpandElements::No, cmList::EmptyElements::Yes);
    status.GetMakefile().AddDefinition(listName, list->to_string());
    return true;
  } catch (std::out_of_range& e) {
    status.SetError(e.what());
    return false;
  }
}

bool HandleJoinCommand(std::vector<std::string> const& args,
                       cmExecutionStatus& status)
{
  if (args.size() != 4) {
    status.SetError(cmStrCat("sub-command JOIN requires three arguments (",
                             args.size() - 1, " found)."));
    return false;
  }

  std::string const& listName = args[1];
  std::string const& glue = args[2];
  std::string const& variableName = args[3];

  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    status.GetMakefile().AddDefinition(variableName, "");
    return true;
  }

  status.GetMakefile().AddDefinition(variableName, list->join(glue));
  return true;
}

bool HandleRemoveItemCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  assert(args.size() >= 2);

  if (args.size() == 2) {
    return true;
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    return true;
  }

  status.GetMakefile().AddDefinition(
    listName, list->remove_items(args.begin() + 2, args.end()).to_string());
  return true;
}

bool HandleReverseCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  assert(args.size() >= 2);
  if (args.size() > 2) {
    status.SetError("sub-command REVERSE only takes one argument.");
    return false;
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    return true;
  }

  status.GetMakefile().AddDefinition(listName, list->reverse().to_string());
  return true;
}

bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args,
                                   cmExecutionStatus& status)
{
  assert(args.size() >= 2);
  if (args.size() > 2) {
    status.SetError("sub-command REMOVE_DUPLICATES only takes one argument.");
    return false;
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    return true;
  }

  status.GetMakefile().AddDefinition(listName,
                                     list->remove_duplicates().to_string());
  return true;
}

bool HandleTransformCommand(std::vector<std::string> const& args,
                            cmExecutionStatus& status)
{
  if (args.size() < 3) {
    status.SetError(
      "sub-command TRANSFORM requires an action to be specified.");
    return false;
  }

  // Descriptor of action
  // Action: enum value identifying action
  // Arity: number of arguments required for the action
  struct ActionDescriptor
  {
    ActionDescriptor(std::string name)
      : Name(std::move(name))
    {
    }
    ActionDescriptor(std::string name, cmList::TransformAction action,
                     int arity)
      : Name(std::move(name))
      , Action(action)
      , Arity(arity)
    {
    }

    operator std::string const&() const { return this->Name; }

    std::string Name;
    cmList::TransformAction Action;
    int Arity = 0;
  };

  // Build a set of supported actions.
  std::set<ActionDescriptor,
           std::function<bool(std::string const&, std::string const&)>>
    descriptors{ { { "APPEND", cmList::TransformAction::APPEND, 1 },
                   { "PREPEND", cmList::TransformAction::PREPEND, 1 },
                   { "TOUPPER", cmList::TransformAction::TOUPPER, 0 },
                   { "TOLOWER", cmList::TransformAction::TOLOWER, 0 },
                   { "STRIP", cmList::TransformAction::STRIP, 0 },
                   { "GENEX_STRIP", cmList::TransformAction::GENEX_STRIP, 0 },
                   { "REPLACE", cmList::TransformAction::REPLACE, 2 } },
                 [](std::string const& x, std::string const& y) {
                   return x < y;
                 } };

  std::string const& listName = args[1];

  // Parse all possible function parameters
  using size_type = std::vector<std::string>::size_type;
  size_type index = 2;

  auto descriptor = descriptors.find(args[index]);

  if (descriptor == descriptors.end()) {
    status.SetError(
      cmStrCat(" sub-command TRANSFORM, ", args[index], " invalid action."));
    return false;
  }

  // Action arguments
  index += 1;
  if (args.size() < index + descriptor->Arity) {
    status.SetError(cmStrCat("sub-command TRANSFORM, action ",
                             descriptor->Name, " expects ", descriptor->Arity,
                             " argument(s)."));
    return false;
  }

  std::vector<std::string> arguments;
  index += descriptor->Arity;
  if (descriptor->Arity > 0) {
    arguments =
      std::vector<std::string>(args.begin() + 3, args.begin() + index);
  }

  std::string const REGEX{ "REGEX" };
  std::string const AT{ "AT" };
  std::string const FOR{ "FOR" };
  std::string const OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" };
  std::unique_ptr<cmList::TransformSelector> selector;
  std::string outputName = listName;

  try {
    // handle optional arguments
    while (args.size() > index) {
      if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) &&
          selector) {
        status.SetError(
          cmStrCat("sub-command TRANSFORM, selector already specified (",
                   selector->GetTag(), ")."));

        return false;
      }

      // REGEX selector
      if (args[index] == REGEX) {
        if (args.size() == ++index) {
          status.SetError("sub-command TRANSFORM, selector REGEX expects "
                          "'regular expression' argument.");
          return false;
        }

        selector =
          cmList::TransformSelector::New<cmList::TransformSelector::REGEX>(
            args[index]);

        index += 1;
        continue;
      }

      // AT selector
      if (args[index] == AT) {
        // get all specified indexes
        std::vector<cmList::index_type> indexes;
        while (args.size() > ++index) {
          std::size_t pos;
          int value;

          try {
            value = std::stoi(args[index], &pos);
            if (pos != args[index].length()) {
              // this is not a number, stop processing
              break;
            }
            indexes.push_back(value);
          } catch (std::invalid_argument const&) {
            // this is not a number, stop processing
            break;
          }
        }

        if (indexes.empty()) {
          status.SetError(
            "sub-command TRANSFORM, selector AT expects at least one "
            "numeric value.");
          return false;
        }

        selector =
          cmList::TransformSelector::New<cmList::TransformSelector::AT>(
            std::move(indexes));

        continue;
      }

      // FOR selector
      if (args[index] == FOR) {
        if (args.size() <= ++index + 1) {
          status.SetError(
            "sub-command TRANSFORM, selector FOR expects, at least,"
            " two arguments.");
          return false;
        }

        cmList::index_type start = 0;
        cmList::index_type stop = 0;
        cmList::index_type step = 1;
        bool valid = true;
        try {
          std::size_t pos;

          start = std::stoi(args[index], &pos);
          if (pos != args[index].length()) {
            // this is not a number
            valid = false;
          } else {
            stop = std::stoi(args[++index], &pos);
            if (pos != args[index].length()) {
              // this is not a number
              valid = false;
            }
          }
        } catch (std::invalid_argument const&) {
          // this is not numbers
          valid = false;
        }
        if (!valid) {
          status.SetError("sub-command TRANSFORM, selector FOR expects, "
                          "at least, two numeric values.");
          return false;
        }
        // try to read a third numeric value for step
        if (args.size() > ++index) {
          try {
            std::size_t pos;

            step = std::stoi(args[index], &pos);
            if (pos != args[index].length()) {
              // this is not a number
              step = 1;
            } else {
              index += 1;
            }
          } catch (std::invalid_argument const&) {
            // this is not number, ignore exception
          }
        }

        if (step <= 0) {
          status.SetError("sub-command TRANSFORM, selector FOR expects "
                          "positive numeric value for <step>.");
          return false;
        }

        selector =
          cmList::TransformSelector::New<cmList::TransformSelector::FOR>(
            { start, stop, step });

        continue;
      }

      // output variable
      if (args[index] == OUTPUT_VARIABLE) {
        if (args.size() == ++index) {
          status.SetError("sub-command TRANSFORM, OUTPUT_VARIABLE "
                          "expects variable name argument.");
          return false;
        }

        outputName = args[index++];
        continue;
      }

      status.SetError(cmStrCat("sub-command TRANSFORM, '",
                               cmJoin(cmMakeRange(args).advance(index), " "),
                               "': unexpected argument(s)."));
      return false;
    }

    // expand the list variable
    auto list = GetList(listName, status.GetMakefile());

    if (!list) {
      status.GetMakefile().AddDefinition(outputName, "");
      return true;
    }

    if (!selector) {
      selector = cmList::TransformSelector::New();
    }
    selector->Makefile = &status.GetMakefile();

    list->transform(descriptor->Action, arguments, std::move(selector));
    status.GetMakefile().AddDefinition(outputName, list->to_string());
    return true;
  } catch (cmList::transform_error& e) {
    status.SetError(e.what());
    return false;
  }
}

bool HandleSortCommand(std::vector<std::string> const& args,
                       cmExecutionStatus& status)
{
  assert(args.size() >= 2);
  if (args.size() > 8) {
    status.SetError("sub-command SORT only takes up to six arguments.");
    return false;
  }

  using SortConfig = cmList::SortConfiguration;
  SortConfig sortConfig;

  size_t argumentIndex = 2;
  std::string const messageHint = "sub-command SORT ";

  while (argumentIndex < args.size()) {
    std::string const& option = args[argumentIndex++];
    if (option == "COMPARE") {
      if (sortConfig.Compare != SortConfig::CompareMethod::DEFAULT) {
        std::string error = cmStrCat(messageHint, "option \"", option,
                                     "\" has been specified multiple times.");
        status.SetError(error);
        return false;
      }
      if (argumentIndex < args.size()) {
        std::string const& argument = args[argumentIndex++];
        if (argument == "STRING") {
          sortConfig.Compare = SortConfig::CompareMethod::STRING;
        } else if (argument == "FILE_BASENAME") {
          sortConfig.Compare = SortConfig::CompareMethod::FILE_BASENAME;
        } else if (argument == "NATURAL") {
          sortConfig.Compare = SortConfig::CompareMethod::NATURAL;
        } else {
          std::string error =
            cmStrCat(messageHint, "value \"", argument, "\" for option \"",
                     option, "\" is invalid.");
          status.SetError(error);
          return false;
        }
      } else {
        status.SetError(cmStrCat(messageHint, "missing argument for option \"",
                                 option, "\"."));
        return false;
      }
    } else if (option == "CASE") {
      if (sortConfig.Case != SortConfig::CaseSensitivity::DEFAULT) {
        status.SetError(cmStrCat(messageHint, "option \"", option,
                                 "\" has been specified multiple times."));
        return false;
      }
      if (argumentIndex < args.size()) {
        std::string const& argument = args[argumentIndex++];
        if (argument == "SENSITIVE") {
          sortConfig.Case = SortConfig::CaseSensitivity::SENSITIVE;
        } else if (argument == "INSENSITIVE") {
          sortConfig.Case = SortConfig::CaseSensitivity::INSENSITIVE;
        } else {
          status.SetError(cmStrCat(messageHint, "value \"", argument,
                                   "\" for option \"", option,
                                   "\" is invalid."));
          return false;
        }
      } else {
        status.SetError(cmStrCat(messageHint, "missing argument for option \"",
                                 option, "\"."));
        return false;
      }
    } else if (option == "ORDER") {

      if (sortConfig.Order != SortConfig::OrderMode::DEFAULT) {
        status.SetError(cmStrCat(messageHint, "option \"", option,
                                 "\" has been specified multiple times."));
        return false;
      }
      if (argumentIndex < args.size()) {
        std::string const& argument = args[argumentIndex++];
        if (argument == "ASCENDING") {
          sortConfig.Order = SortConfig::OrderMode::ASCENDING;
        } else if (argument == "DESCENDING") {
          sortConfig.Order = SortConfig::OrderMode::DESCENDING;
        } else {
          status.SetError(cmStrCat(messageHint, "value \"", argument,
                                   "\" for option \"", option,
                                   "\" is invalid."));
          return false;
        }
      } else {
        status.SetError(cmStrCat(messageHint, "missing argument for option \"",
                                 option, "\"."));
        return false;
      }
    } else {
      status.SetError(
        cmStrCat(messageHint, "option \"", option, "\" is unknown."));
      return false;
    }
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    return true;
  }

  status.GetMakefile().AddDefinition(listName,
                                     list->sort(sortConfig).to_string());
  return true;
}

bool HandleSublistCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  if (args.size() != 5) {
    status.SetError(cmStrCat("sub-command SUBLIST requires four arguments (",
                             args.size() - 1, " found)."));
    return false;
  }

  std::string const& listName = args[1];
  std::string const& variableName = args.back();

  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list || list->empty()) {
    status.GetMakefile().AddDefinition(variableName, "");
    return true;
  }

  int start;
  int length;
  if (!GetIndexArg(args[2], &start, status.GetMakefile())) {
    status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
    return false;
  }
  if (!GetIndexArg(args[3], &length, status.GetMakefile())) {
    status.SetError(cmStrCat("index: ", args[3], " is not a valid index"));
    return false;
  }

  if (start < 0) {
    status.SetError(cmStrCat("begin index: ", start, " is out of range 0 - ",
                             list->size() - 1));
    return false;
  }
  if (length < -1) {
    status.SetError(cmStrCat("length: ", length, " should be -1 or greater"));
    return false;
  }

  using size_type = cmList::size_type;

  try {
    auto sublist = list->sublist(static_cast<size_type>(start),
                                 static_cast<size_type>(length));
    status.GetMakefile().AddDefinition(variableName, sublist.to_string());
    return true;
  } catch (std::out_of_range& e) {
    status.SetError(e.what());
    return false;
  }
}

bool HandleRemoveAtCommand(std::vector<std::string> const& args,
                           cmExecutionStatus& status)
{
  if (args.size() < 3) {
    status.SetError("sub-command REMOVE_AT requires at least "
                    "two arguments.");
    return false;
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list || list->empty()) {
    std::ostringstream str;
    str << "index: ";
    for (size_t i = 1; i < args.size(); ++i) {
      str << args[i];
      if (i != args.size() - 1) {
        str << ", ";
      }
    }
    str << " out of range (0, 0)";
    status.SetError(str.str());
    return false;
  }

  size_t cc;
  std::vector<cmList::index_type> removed;
  for (cc = 2; cc < args.size(); ++cc) {
    int index;
    if (!GetIndexArg(args[cc], &index, status.GetMakefile())) {
      status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
      return false;
    }
    removed.push_back(index);
  }

  try {
    status.GetMakefile().AddDefinition(
      listName,
      list->remove_items(removed.begin(), removed.end()).to_string());
    return true;
  } catch (std::out_of_range& e) {
    status.SetError(e.what());
    return false;
  }
}

bool HandleFilterCommand(std::vector<std::string> const& args,
                         cmExecutionStatus& status)
{
  if (args.size() < 2) {
    status.SetError("sub-command FILTER requires a list to be specified.");
    return false;
  }

  if (args.size() < 3) {
    status.SetError(
      "sub-command FILTER requires an operator to be specified.");
    return false;
  }

  if (args.size() < 4) {
    status.SetError("sub-command FILTER requires a mode to be specified.");
    return false;
  }

  std::string const& op = args[2];
  cmList::FilterMode filterMode;
  if (op == "INCLUDE") {
    filterMode = cmList::FilterMode::INCLUDE;
  } else if (op == "EXCLUDE") {
    filterMode = cmList::FilterMode::EXCLUDE;
  } else {
    status.SetError("sub-command FILTER does not recognize operator " + op);
    return false;
  }

  std::string const& listName = args[1];
  // expand the variable
  auto list = GetList(listName, status.GetMakefile());

  if (!list) {
    return true;
  }

  std::string const& mode = args[3];
  if (mode != "REGEX") {
    status.SetError("sub-command FILTER does not recognize mode " + mode);
    return false;
  }
  if (args.size() != 5) {
    status.SetError("sub-command FILTER, mode REGEX "
                    "requires five arguments.");
    return false;
  }
  std::string const& pattern = args[4];

  try {
    status.GetMakefile().AddDefinition(
      listName, list->filter(pattern, filterMode).to_string());
    return true;
  } catch (std::invalid_argument& e) {
    status.SetError(e.what());
    return false;
  }
}
} // namespace

bool cmListCommand(std::vector<std::string> const& args,
                   cmExecutionStatus& status)
{
  if (args.size() < 2) {
    status.SetError("must be called with at least two arguments.");
    return false;
  }

  static cmSubcommandTable const subcommand{
    { "LENGTH"_s, HandleLengthCommand },
    { "GET"_s, HandleGetCommand },
    { "APPEND"_s, HandleAppendCommand },
    { "PREPEND"_s, HandlePrependCommand },
    { "POP_BACK"_s, HandlePopBackCommand },
    { "POP_FRONT"_s, HandlePopFrontCommand },
    { "FIND"_s, HandleFindCommand },
    { "INSERT"_s, HandleInsertCommand },
    { "JOIN"_s, HandleJoinCommand },
    { "REMOVE_AT"_s, HandleRemoveAtCommand },
    { "REMOVE_ITEM"_s, HandleRemoveItemCommand },
    { "REMOVE_DUPLICATES"_s, HandleRemoveDuplicatesCommand },
    { "TRANSFORM"_s, HandleTransformCommand },
    { "SORT"_s, HandleSortCommand },
    { "SUBLIST"_s, HandleSublistCommand },
    { "REVERSE"_s, HandleReverseCommand },
    { "FILTER"_s, HandleFilterCommand },
  };

  return subcommand(args[0], args, status);
}
