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

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib> // required for atoi
#include <functional>
#include <iterator>
#include <set>
#include <sstream>
#include <stdexcept>
#include <utility>
#include <vector>

#include <cm/memory>

#include "cmsys/RegularExpression.hxx"

#include "cm_static_string_view.hxx"

#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmStringReplaceHelper.h"
#include "cmSubcommandTable.h"
#include "cmSystemTools.h"

namespace {

bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
                 std::string const& listName,
                 std::vector<std::string>& varArgsExpanded,
                 cmExecutionStatus& status);

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

bool GetList(std::vector<std::string>& list, const std::string& var,
             const cmMakefile& makefile)
{
  std::string listString;
  if (!GetListString(listString, var, makefile)) {
    return false;
  }
  // if the size of the list
  if (listString.empty()) {
    return true;
  }
  // expand the variable into a list
  cmExpandList(listString, list, true);
  // if no empty elements then just return
  if (!cmContains(list, std::string())) {
    return true;
  }
  // if we have empty elements we need to check policy CMP0007
  switch (makefile.GetPolicyStatus(cmPolicies::CMP0007)) {
    case cmPolicies::WARN: {
      // Default is to warn and use old behavior
      // OLD behavior is to allow compatibility, so recall
      // ExpandListArgument without the true which will remove
      // empty values
      list.clear();
      cmExpandList(listString, list);
      std::string warn =
        cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0007),
                 " List has value = [", listString, "].");
      makefile.IssueMessage(MessageType::AUTHOR_WARNING, warn);
      return true;
    }
    case cmPolicies::OLD:
      // OLD behavior is to allow compatibility, so recall
      // ExpandListArgument without the true which will remove
      // empty values
      list.clear();
      cmExpandList(listString, list);
      return true;
    case cmPolicies::NEW:
      return true;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      makefile.IssueMessage(
        MessageType::FATAL_ERROR,
        cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007));
      return false;
  }
  return true;
}

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

  const std::string& listName = args[1];
  const std::string& variableName = args.back();
  std::vector<std::string> varArgsExpanded;
  // do not check the return value here
  // if the list var is not found varArgsExpanded will have size 0
  // and we will return 0
  GetList(varArgsExpanded, listName, status.GetMakefile());
  size_t length = varArgsExpanded.size();
  char buffer[1024];
  sprintf(buffer, "%d", static_cast<int>(length));

  status.GetMakefile().AddDefinition(variableName, buffer);
  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;
  }

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

  std::string value;
  size_t cc;
  const char* sep = "";
  size_t nitem = varArgsExpanded.size();
  for (cc = 2; cc < args.size() - 1; cc++) {
    int item = atoi(args[cc].c_str());
    value += sep;
    sep = ";";
    if (item < 0) {
      item = static_cast<int>(nitem) + item;
    }
    if (item < 0 || nitem <= static_cast<size_t>(item)) {
      status.SetError(cmStrCat("index: ", item, " out of range (-", nitem,
                               ", ", nitem - 1, ")"));
      return false;
    }
    value += varArgsExpanded[item];
  }

  status.GetMakefile().AddDefinition(variableName, value);
  return true;
}

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

  // If `listString` or `args` is empty, no need to append `;`,
  // then index is going to be `1` and points to the end-of-string ";"
  auto const offset =
    std::string::size_type(listString.empty() || args.empty());
  listString += &";"[offset] + cmJoin(cmMakeRange(args).advance(2), ";");

  makefile.AddDefinition(listName, listString);
  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);

  // If `listString` or `args` is empty, no need to append `;`,
  // then `offset` is going to be `1` and points to the end-of-string ";"
  auto const offset =
    std::string::size_type(listString.empty() || args.empty());
  listString.insert(0,
                    cmJoin(cmMakeRange(args).advance(2), ";") + &";"[offset]);

  makefile.AddDefinition(listName, listString);
  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++;
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, makefile)) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
    return true;
  }

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

    makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";"));

  } 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++;
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, makefile)) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      makefile.RemoveDefinition(*ai);
    }
    return true;
  }

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

    makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";"));

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

  const std::string& listName = args[1];
  const std::string& variableName = args.back();
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    status.GetMakefile().AddDefinition(variableName, "-1");
    return true;
  }

  auto it = std::find(varArgsExpanded.begin(), varArgsExpanded.end(), args[2]);
  if (it != varArgsExpanded.end()) {
    status.GetMakefile().AddDefinition(
      variableName,
      std::to_string(std::distance(varArgsExpanded.begin(), it)));
    return true;
  }

  status.GetMakefile().AddDefinition(variableName, "-1");
  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;
  }

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

  // expand the variable
  int item = atoi(args[2].c_str());
  std::vector<std::string> varArgsExpanded;
  if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
       varArgsExpanded.empty()) &&
      item != 0) {
    status.SetError(cmStrCat("index: ", item, " out of range (0, 0)"));
    return false;
  }

  if (!varArgsExpanded.empty()) {
    size_t nitem = varArgsExpanded.size();
    if (item < 0) {
      item = static_cast<int>(nitem) + item;
    }
    if (item < 0 || nitem < static_cast<size_t>(item)) {
      status.SetError(cmStrCat("index: ", item, " out of range (-",
                               varArgsExpanded.size(), ", ",
                               varArgsExpanded.size(), ")"));
      return false;
    }
  }

  varArgsExpanded.insert(varArgsExpanded.begin() + item, args.begin() + 3,
                         args.end());

  std::string value = cmJoin(varArgsExpanded, ";");
  status.GetMakefile().AddDefinition(listName, value);
  return true;
}

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

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

  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    status.GetMakefile().AddDefinition(variableName, "");
    return true;
  }

  std::string value =
    cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue);

  status.GetMakefile().AddDefinition(variableName, value);
  return true;
}

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

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    return true;
  }

  std::vector<std::string> remove(args.begin() + 2, args.end());
  std::sort(remove.begin(), remove.end());
  auto remEnd = std::unique(remove.begin(), remove.end());
  auto remBegin = remove.begin();

  auto argsEnd =
    cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd));
  auto argsBegin = varArgsExpanded.cbegin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
  status.GetMakefile().AddDefinition(listName, value);
  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;
  }

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    return true;
  }

  std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";");

  status.GetMakefile().AddDefinition(listName, value);
  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;
  }

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    return true;
  }

  auto argsEnd = cmRemoveDuplicates(varArgsExpanded);
  auto argsBegin = varArgsExpanded.cbegin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");

  status.GetMakefile().AddDefinition(listName, value);
  return true;
}

// Helpers for list(TRANSFORM <list> ...)
using transform_type = std::function<std::string(const std::string&)>;

class transform_error : public std::runtime_error
{
public:
  transform_error(const std::string& error)
    : std::runtime_error(error)
  {
  }
};

class TransformSelector
{
public:
  virtual ~TransformSelector() = default;

  std::string Tag;

  virtual bool Validate(std::size_t count = 0) = 0;

  virtual bool InSelection(const std::string&) = 0;

  virtual void Transform(std::vector<std::string>& list,
                         const transform_type& transform)
  {
    std::transform(list.begin(), list.end(), list.begin(), transform);
  }

protected:
  TransformSelector(std::string&& tag)
    : Tag(std::move(tag))
  {
  }
};
class TransformNoSelector : public TransformSelector
{
public:
  TransformNoSelector()
    : TransformSelector("NO SELECTOR")
  {
  }

  bool Validate(std::size_t) override { return true; }

  bool InSelection(const std::string&) override { return true; }
};
class TransformSelectorRegex : public TransformSelector
{
public:
  TransformSelectorRegex(const std::string& regex)
    : TransformSelector("REGEX")
    , Regex(regex)
  {
  }

  bool Validate(std::size_t) override { return this->Regex.is_valid(); }

  bool InSelection(const std::string& value) override
  {
    return this->Regex.find(value);
  }

  cmsys::RegularExpression Regex;
};
class TransformSelectorIndexes : public TransformSelector
{
public:
  std::vector<int> Indexes;

  bool InSelection(const std::string&) override { return true; }

  void Transform(std::vector<std::string>& list,
                 const transform_type& transform) override
  {
    this->Validate(list.size());

    for (auto index : this->Indexes) {
      list[index] = transform(list[index]);
    }
  }

protected:
  TransformSelectorIndexes(std::string&& tag)
    : TransformSelector(std::move(tag))
  {
  }
  TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes)
    : TransformSelector(std::move(tag))
    , Indexes(indexes)
  {
  }

  int NormalizeIndex(int index, std::size_t count)
  {
    if (index < 0) {
      index = static_cast<int>(count) + index;
    }
    if (index < 0 || count <= static_cast<std::size_t>(index)) {
      throw transform_error(cmStrCat(
        "sub-command TRANSFORM, selector ", this->Tag, ", index: ", index,
        " out of range (-", count, ", ", count - 1, ")."));
    }
    return index;
  }
};
class TransformSelectorAt : public TransformSelectorIndexes
{
public:
  TransformSelectorAt(std::vector<int>&& indexes)
    : TransformSelectorIndexes("AT", std::move(indexes))
  {
  }

  bool Validate(std::size_t count) override
  {
    decltype(Indexes) indexes;

    for (auto index : Indexes) {
      indexes.push_back(this->NormalizeIndex(index, count));
    }
    this->Indexes = std::move(indexes);

    return true;
  }
};
class TransformSelectorFor : public TransformSelectorIndexes
{
public:
  TransformSelectorFor(int start, int stop, int step)
    : TransformSelectorIndexes("FOR")
    , Start(start)
    , Stop(stop)
    , Step(step)
  {
  }

  bool Validate(std::size_t count) override
  {
    this->Start = this->NormalizeIndex(this->Start, count);
    this->Stop = this->NormalizeIndex(this->Stop, count);

    // compute indexes
    auto size = (this->Stop - this->Start + 1) / this->Step;
    if ((this->Stop - this->Start + 1) % this->Step != 0) {
      size += 1;
    }

    this->Indexes.resize(size);
    auto start = this->Start;
    auto step = this->Step;
    std::generate(this->Indexes.begin(), this->Indexes.end(),
                  [&start, step]() -> int {
                    auto r = start;
                    start += step;
                    return r;
                  });

    return true;
  }

private:
  int Start, Stop, Step;
};

class TransformAction
{
public:
  virtual ~TransformAction() = default;

  virtual std::string Transform(const std::string& input) = 0;
};
class TransformReplace : public TransformAction
{
public:
  TransformReplace(const std::vector<std::string>& arguments,
                   cmMakefile* makefile)
    : ReplaceHelper(arguments[0], arguments[1], makefile)
  {
    makefile->ClearMatches();

    if (!this->ReplaceHelper.IsRegularExpressionValid()) {
      throw transform_error(
        cmStrCat("sub-command TRANSFORM, action REPLACE: Failed to compile "
                 "regex \"",
                 arguments[0], "\"."));
    }
    if (!this->ReplaceHelper.IsReplaceExpressionValid()) {
      throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ",
                                     this->ReplaceHelper.GetError(), "."));
    }
  }

  std::string Transform(const std::string& input) override
  {
    // Scan through the input for all matches.
    std::string output;

    if (!this->ReplaceHelper.Replace(input, output)) {
      throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ",
                                     this->ReplaceHelper.GetError(), "."));
    }

    return output;
  }

private:
  cmStringReplaceHelper ReplaceHelper;
};

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

  // Structure collecting all elements of the command
  struct Command
  {
    Command(const std::string& listName)
      : ListName(listName)
      , OutputName(listName)
    {
    }

    std::string Name;
    std::string ListName;
    std::vector<std::string> Arguments;
    std::unique_ptr<TransformAction> Action;
    std::unique_ptr<TransformSelector> Selector;
    std::string OutputName;
  } command(args[1]);

  // Descriptor of action
  // Arity: number of arguments required for the action
  // Transform: lambda function implementing the action
  struct ActionDescriptor
  {
    ActionDescriptor(std::string name)
      : Name(std::move(name))
    {
    }
    ActionDescriptor(std::string name, int arity, transform_type transform)
      : Name(std::move(name))
      , Arity(arity)
#if defined(__GNUC__) && __GNUC__ == 6 && defined(__aarch64__)
      // std::function move constructor miscompiles on this architecture
      , Transform(transform)
#else
      , Transform(std::move(transform))
#endif
    {
    }

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

    std::string Name;
    int Arity = 0;
    transform_type Transform;
  };

  // Build a set of supported actions.
  std::set<ActionDescriptor,
           std::function<bool(const std::string&, const std::string&)>>
    descriptors(
      [](const std::string& x, const std::string& y) { return x < y; });
  descriptors = { { "APPEND", 1,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return s + command.Arguments[0];
                      }

                      return s;
                    } },
                  { "PREPEND", 1,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return command.Arguments[0] + s;
                      }

                      return s;
                    } },
                  { "TOUPPER", 0,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return cmSystemTools::UpperCase(s);
                      }

                      return s;
                    } },
                  { "TOLOWER", 0,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return cmSystemTools::LowerCase(s);
                      }

                      return s;
                    } },
                  { "STRIP", 0,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return cmTrimWhitespace(s);
                      }

                      return s;
                    } },
                  { "GENEX_STRIP", 0,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return cmGeneratorExpression::Preprocess(
                          s,
                          cmGeneratorExpression::StripAllGeneratorExpressions);
                      }

                      return s;
                    } },
                  { "REPLACE", 2,
                    [&command](const std::string& s) -> std::string {
                      if (command.Selector->InSelection(s)) {
                        return command.Action->Transform(s);
                      }

                      return s;
                    } } };

  using size_type = std::vector<std::string>::size_type;
  size_type index = 2;

  // Parse all possible function parameters
  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;
  }

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

  if (command.Name == "REPLACE") {
    try {
      command.Action = cm::make_unique<TransformReplace>(
        command.Arguments, &status.GetMakefile());
    } catch (const transform_error& e) {
      status.SetError(e.what());
      return false;
    }
  }

  const std::string REGEX{ "REGEX" };
  const std::string AT{ "AT" };
  const std::string FOR{ "FOR" };
  const std::string OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" };

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

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

      command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]);
      if (!command.Selector->Validate()) {
        status.SetError(
          cmStrCat("sub-command TRANSFORM, selector REGEX failed to compile "
                   "regex \"",
                   args[index], "\"."));
        return false;
      }

      index += 1;
      continue;
    }

    // AT selector
    if (args[index] == AT) {
      // get all specified indexes
      std::vector<int> 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 (const std::invalid_argument&) {
          // 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;
      }

      command.Selector =
        cm::make_unique<TransformSelectorAt>(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;
      }

      int start = 0;
      int stop = 0;
      int 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 (const std::invalid_argument&) {
        // 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 (const std::invalid_argument&) {
          // this is not number, ignore exception
        }
      }

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

      command.Selector =
        cm::make_unique<TransformSelectorFor>(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;
      }

      command.OutputName = args[index++];
      continue;
    }

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

  // expand the list variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, command.ListName, status.GetMakefile())) {
    status.GetMakefile().AddDefinition(command.OutputName, "");
    return true;
  }

  if (!command.Selector) {
    // no selector specified, apply transformation to all elements
    command.Selector = cm::make_unique<TransformNoSelector>();
  }

  try {
    command.Selector->Transform(varArgsExpanded, descriptor->Transform);
  } catch (const transform_error& e) {
    status.SetError(e.what());
    return false;
  }

  status.GetMakefile().AddDefinition(command.OutputName,
                                     cmJoin(varArgsExpanded, ";"));

  return true;
}

class cmStringSorter
{
public:
  enum class Order
  {
    UNINITIALIZED,
    ASCENDING,
    DESCENDING,
  };

  enum class Compare
  {
    UNINITIALIZED,
    STRING,
    FILE_BASENAME,
  };
  enum class CaseSensitivity
  {
    UNINITIALIZED,
    SENSITIVE,
    INSENSITIVE,
  };

protected:
  using StringFilter = std::string (*)(const std::string&);
  StringFilter GetCompareFilter(Compare compare)
  {
    return (compare == Compare::FILE_BASENAME) ? cmSystemTools::GetFilenameName
                                               : nullptr;
  }

  StringFilter GetCaseFilter(CaseSensitivity sensitivity)
  {
    return (sensitivity == CaseSensitivity::INSENSITIVE)
      ? cmSystemTools::LowerCase
      : nullptr;
  }

public:
  cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
                 Order desc = Order::ASCENDING)
    : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
    , descending(desc == Order::DESCENDING)
  {
  }

  std::string ApplyFilter(const std::string& argument)
  {
    std::string result = argument;
    for (auto filter : filters) {
      if (filter != nullptr) {
        result = filter(result);
      }
    }
    return result;
  }

  bool operator()(const std::string& a, const std::string& b)
  {
    std::string af = ApplyFilter(a);
    std::string bf = ApplyFilter(b);
    bool result;
    if (descending) {
      result = bf < af;
    } else {
      result = af < bf;
    }
    return result;
  }

protected:
  StringFilter filters[2] = { nullptr, nullptr };
  bool descending;
};

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

  auto sortCompare = cmStringSorter::Compare::UNINITIALIZED;
  auto sortCaseSensitivity = cmStringSorter::CaseSensitivity::UNINITIALIZED;
  auto sortOrder = cmStringSorter::Order::UNINITIALIZED;

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

  while (argumentIndex < args.size()) {
    const std::string option = args[argumentIndex++];
    if (option == "COMPARE") {
      if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) {
        std::string error = cmStrCat(messageHint, "option \"", option,
                                     "\" has been specified multiple times.");
        status.SetError(error);
        return false;
      }
      if (argumentIndex < args.size()) {
        const std::string argument = args[argumentIndex++];
        if (argument == "STRING") {
          sortCompare = cmStringSorter::Compare::STRING;
        } else if (argument == "FILE_BASENAME") {
          sortCompare = cmStringSorter::Compare::FILE_BASENAME;
        } 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 (sortCaseSensitivity !=
          cmStringSorter::CaseSensitivity::UNINITIALIZED) {
        status.SetError(cmStrCat(messageHint, "option \"", option,
                                 "\" has been specified multiple times."));
        return false;
      }
      if (argumentIndex < args.size()) {
        const std::string argument = args[argumentIndex++];
        if (argument == "SENSITIVE") {
          sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
        } else if (argument == "INSENSITIVE") {
          sortCaseSensitivity = cmStringSorter::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 (sortOrder != cmStringSorter::Order::UNINITIALIZED) {
        status.SetError(cmStrCat(messageHint, "option \"", option,
                                 "\" has been specified multiple times."));
        return false;
      }
      if (argumentIndex < args.size()) {
        const std::string argument = args[argumentIndex++];
        if (argument == "ASCENDING") {
          sortOrder = cmStringSorter::Order::ASCENDING;
        } else if (argument == "DESCENDING") {
          sortOrder = cmStringSorter::Order::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;
    }
  }
  // set Default Values if Option is not given
  if (sortCompare == cmStringSorter::Compare::UNINITIALIZED) {
    sortCompare = cmStringSorter::Compare::STRING;
  }
  if (sortCaseSensitivity == cmStringSorter::CaseSensitivity::UNINITIALIZED) {
    sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
  }
  if (sortOrder == cmStringSorter::Order::UNINITIALIZED) {
    sortOrder = cmStringSorter::Order::ASCENDING;
  }

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    return true;
  }

  if ((sortCompare == cmStringSorter::Compare::STRING) &&
      (sortCaseSensitivity == cmStringSorter::CaseSensitivity::SENSITIVE) &&
      (sortOrder == cmStringSorter::Order::ASCENDING)) {
    std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
  } else {
    cmStringSorter sorter(sortCompare, sortCaseSensitivity, sortOrder);
    std::sort(varArgsExpanded.begin(), varArgsExpanded.end(), sorter);
  }

  std::string value = cmJoin(varArgsExpanded, ";");
  status.GetMakefile().AddDefinition(listName, value);
  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;
  }

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

  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
      varArgsExpanded.empty()) {
    status.GetMakefile().AddDefinition(variableName, "");
    return true;
  }

  const int start = atoi(args[2].c_str());
  const int length = atoi(args[3].c_str());

  using size_type = decltype(varArgsExpanded)::size_type;

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

  const size_type end =
    (length == -1 || size_type(start + length) > varArgsExpanded.size())
    ? varArgsExpanded.size()
    : size_type(start + length);
  std::vector<std::string> sublist(varArgsExpanded.begin() + start,
                                   varArgsExpanded.begin() + end);
  status.GetMakefile().AddDefinition(variableName, cmJoin(sublist, ";"));
  return true;
}

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

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
      varArgsExpanded.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<size_t> removed;
  size_t nitem = varArgsExpanded.size();
  for (cc = 2; cc < args.size(); ++cc) {
    int item = atoi(args[cc].c_str());
    if (item < 0) {
      item = static_cast<int>(nitem) + item;
    }
    if (item < 0 || nitem <= static_cast<size_t>(item)) {
      status.SetError(cmStrCat("index: ", item, " out of range (-", nitem,
                               ", ", nitem - 1, ")"));
      return false;
    }
    removed.push_back(static_cast<size_t>(item));
  }

  std::sort(removed.begin(), removed.end());
  auto remEnd = std::unique(removed.begin(), removed.end());
  auto remBegin = removed.begin();

  auto argsEnd =
    cmRemoveIndices(varArgsExpanded, cmMakeRange(remBegin, remEnd));
  auto argsBegin = varArgsExpanded.cbegin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");

  status.GetMakefile().AddDefinition(listName, value);
  return true;
}

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

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

  const std::string& listName = args[1];
  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
    return true;
  }

  const std::string& mode = args[3];
  if (mode == "REGEX") {
    if (args.size() != 5) {
      status.SetError("sub-command FILTER, mode REGEX "
                      "requires five arguments.");
      return false;
    }
    return FilterRegex(args, includeMatches, listName, varArgsExpanded,
                       status);
  }

  status.SetError("sub-command FILTER does not recognize mode " + mode);
  return false;
}

class MatchesRegex
{
public:
  MatchesRegex(cmsys::RegularExpression& in_regex, bool in_includeMatches)
    : regex(in_regex)
    , includeMatches(in_includeMatches)
  {
  }

  bool operator()(const std::string& target)
  {
    return regex.find(target) ^ includeMatches;
  }

private:
  cmsys::RegularExpression& regex;
  const bool includeMatches;
};

bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
                 std::string const& listName,
                 std::vector<std::string>& varArgsExpanded,
                 cmExecutionStatus& status)
{
  const std::string& pattern = args[4];
  cmsys::RegularExpression regex(pattern);
  if (!regex.is_valid()) {
    std::string error =
      cmStrCat("sub-command FILTER, mode REGEX failed to compile regex \"",
               pattern, "\".");
    status.SetError(error);
    return false;
  }

  auto argsBegin = varArgsExpanded.begin();
  auto argsEnd = varArgsExpanded.end();
  auto newArgsEnd =
    std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches));

  std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";");
  status.GetMakefile().AddDefinition(listName, value);
  return true;
}

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