/* 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 "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
#include <functional>
#include <iterator>
#include <set>
#include <sstream>
#include <stdexcept>
#include <stdio.h>
#include <stdlib.h> // required for atoi
#include <utility>
#include <vector>

#include "cm_memory.hxx"

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

class cmExecutionStatus;

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

  const std::string& subCommand = args[0];
  if (subCommand == "LENGTH") {
    return this->HandleLengthCommand(args);
  }
  if (subCommand == "GET") {
    return this->HandleGetCommand(args);
  }
  if (subCommand == "APPEND") {
    return this->HandleAppendCommand(args);
  }
  if (subCommand == "PREPEND") {
    return this->HandlePrependCommand(args);
  }
  if (subCommand == "POP_BACK") {
    return this->HandlePopBackCommand(args);
  }
  if (subCommand == "POP_FRONT") {
    return this->HandlePopFrontCommand(args);
  }
  if (subCommand == "FIND") {
    return this->HandleFindCommand(args);
  }
  if (subCommand == "INSERT") {
    return this->HandleInsertCommand(args);
  }
  if (subCommand == "JOIN") {
    return this->HandleJoinCommand(args);
  }
  if (subCommand == "REMOVE_AT") {
    return this->HandleRemoveAtCommand(args);
  }
  if (subCommand == "REMOVE_ITEM") {
    return this->HandleRemoveItemCommand(args);
  }
  if (subCommand == "REMOVE_DUPLICATES") {
    return this->HandleRemoveDuplicatesCommand(args);
  }
  if (subCommand == "TRANSFORM") {
    return this->HandleTransformCommand(args);
  }
  if (subCommand == "SORT") {
    return this->HandleSortCommand(args);
  }
  if (subCommand == "SUBLIST") {
    return this->HandleSublistCommand(args);
  }
  if (subCommand == "REVERSE") {
    return this->HandleReverseCommand(args);
  }
  if (subCommand == "FILTER") {
    return this->HandleFilterCommand(args);
  }

  std::string e = "does not recognize sub-command " + subCommand;
  this->SetError(e);
  return false;
}

bool cmListCommand::GetListString(std::string& listString,
                                  const std::string& var)
{
  // get the old value
  const char* cacheValue = this->Makefile->GetDefinition(var);
  if (!cacheValue) {
    return false;
  }
  listString = cacheValue;
  return true;
}

bool cmListCommand::GetList(std::vector<std::string>& list,
                            const std::string& var)
{
  std::string listString;
  if (!this->GetListString(listString, var)) {
    return false;
  }
  // if the size of the list
  if (listString.empty()) {
    return true;
  }
  // expand the variable into a list
  cmSystemTools::ExpandListArgument(listString, list, true);
  // if no empty elements then just return
  if (std::find(list.begin(), list.end(), std::string()) == list.end()) {
    return true;
  }
  // if we have empty elements we need to check policy CMP0007
  switch (this->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();
      cmSystemTools::ExpandListArgument(listString, list);
      std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007);
      warn += " List has value = [";
      warn += listString;
      warn += "].";
      this->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();
      cmSystemTools::ExpandListArgument(listString, list);
      return true;
    case cmPolicies::NEW:
      return true;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      this->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007));
      return false;
  }
  return true;
}

bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
{
  if (args.size() != 3) {
    this->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
  this->GetList(varArgsExpanded, listName);
  size_t length = varArgsExpanded.size();
  char buffer[1024];
  sprintf(buffer, "%d", static_cast<int>(length));

  this->Makefile->AddDefinition(variableName, buffer);
  return true;
}

bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
{
  if (args.size() < 4) {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    this->Makefile->AddDefinition(variableName, "NOTFOUND");
    return true;
  }
  // FIXME: Add policy to make non-existing lists an error like empty lists.
  if (varArgsExpanded.empty()) {
    this->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)) {
      std::ostringstream str;
      str << "index: " << item << " out of range (-" << nitem << ", "
          << nitem - 1 << ")";
      this->SetError(str.str());
      return false;
    }
    value += varArgsExpanded[item];
  }

  this->Makefile->AddDefinition(variableName, value);
  return true;
}

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

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

  std::string const& listName = args[1];
  // expand the variable
  std::string listString;
  this->GetListString(listString, listName);

  // 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), ";");

  this->Makefile->AddDefinition(listName, listString);
  return true;
}

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

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

  std::string const& listName = args[1];
  // expand the variable
  std::string listString;
  this->GetListString(listString, listName);

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

  this->Makefile->AddDefinition(listName, listString);
  return true;
}

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

  auto ai = args.cbegin();
  ++ai; // Skip subcommand name
  std::string const& listName = *ai++;
  std::vector<std::string> varArgsExpanded;
  if (!this->GetList(varArgsExpanded, listName)) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      this->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());
        this->Makefile->AddDefinition(*ai, varArgsExpanded.back());
        varArgsExpanded.pop_back();
      }
      // Undefine the rest variables if the list gets empty earlier...
      for (; ai != args.cend(); ++ai) {
        this->Makefile->RemoveDefinition(*ai);
      }
    }

    this->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) {
      this->Makefile->RemoveDefinition(*ai);
    }
  }

  return true;
}

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

  auto ai = args.cbegin();
  ++ai; // Skip subcommand name
  std::string const& listName = *ai++;
  std::vector<std::string> varArgsExpanded;
  if (!this->GetList(varArgsExpanded, listName)) {
    // Can't get the list definition... undefine any vars given after.
    for (; ai != args.cend(); ++ai) {
      this->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());
        this->Makefile->AddDefinition(*ai, *vi);
      }
      varArgsExpanded.erase(varArgsExpanded.begin(), vi);
      // Undefine the rest variables if the list gets empty earlier...
      for (; ai != args.cend(); ++ai) {
        this->Makefile->RemoveDefinition(*ai);
      }
    }

    this->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) {
      this->Makefile->RemoveDefinition(*ai);
    }
  }

  return true;
}

bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args)
{
  if (args.size() != 4) {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    this->Makefile->AddDefinition(variableName, "-1");
    return true;
  }

  std::vector<std::string>::iterator it =
    std::find(varArgsExpanded.begin(), varArgsExpanded.end(), args[2]);
  if (it != varArgsExpanded.end()) {
    std::ostringstream indexStream;
    indexStream << std::distance(varArgsExpanded.begin(), it);
    this->Makefile->AddDefinition(variableName, indexStream.str());
    return true;
  }

  this->Makefile->AddDefinition(variableName, "-1");
  return true;
}

bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
{
  if (args.size() < 4) {
    this->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 ((!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) &&
      item != 0) {
    std::ostringstream str;
    str << "index: " << item << " out of range (0, 0)";
    this->SetError(str.str());
    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)) {
      std::ostringstream str;
      str << "index: " << item << " out of range (-" << varArgsExpanded.size()
          << ", " << varArgsExpanded.size() << ")";
      this->SetError(str.str());
      return false;
    }
  }

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

  std::string value = cmJoin(varArgsExpanded, ";");
  this->Makefile->AddDefinition(listName, value);
  return true;
}

bool cmListCommand::HandleJoinCommand(std::vector<std::string> const& args)
{
  if (args.size() != 4) {
    std::ostringstream error;
    error << "sub-command JOIN requires three arguments (" << args.size() - 1
          << " found).";
    this->SetError(error.str());
    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 (!this->GetList(varArgsExpanded, listName)) {
    this->Makefile->AddDefinition(variableName, "");
    return true;
  }

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

  this->Makefile->AddDefinition(variableName, value);
  return true;
}

bool cmListCommand::HandleRemoveItemCommand(
  std::vector<std::string> const& args)
{
  if (args.size() < 3) {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    return true;
  }

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

  std::vector<std::string>::const_iterator argsEnd =
    cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd));
  std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
  this->Makefile->AddDefinition(listName, value);
  return true;
}

bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args)
{
  assert(args.size() >= 2);
  if (args.size() > 2) {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    return true;
  }

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

  this->Makefile->AddDefinition(listName, value);
  return true;
}

bool cmListCommand::HandleRemoveDuplicatesCommand(
  std::vector<std::string> const& args)
{
  assert(args.size() >= 2);
  if (args.size() > 2) {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    return true;
  }

  std::vector<std::string>::const_iterator argsEnd =
    cmRemoveDuplicates(varArgsExpanded);
  std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");

  this->Makefile->AddDefinition(listName, value);
  return true;
}

// Helpers for list(TRANSFORM <list> ...)
namespace {
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)) {
      std::ostringstream str;
      str << "sub-command TRANSFORM, selector " << this->Tag
          << ", index: " << index << " out of range (-" << count << ", "
          << count - 1 << ").";
      throw transform_error(str.str());
    }
    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, 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()) {
      std::ostringstream error;
      error
        << "sub-command TRANSFORM, action REPLACE: Failed to compile regex \""
        << arguments[0] << "\".";
      throw transform_error(error.str());
    }
    if (!this->ReplaceHelper.IsReplaceExpressionValid()) {
      std::ostringstream error;
      error << "sub-command TRANSFORM, action REPLACE: "
            << this->ReplaceHelper.GetError() << ".";
      throw transform_error(error.str());
    }
  }

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

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

    return output;
  }

private:
  cmStringReplaceHelper ReplaceHelper;
};
}

bool cmListCommand::HandleTransformCommand(
  std::vector<std::string> const& args)
{
  if (args.size() < 3) {
    this->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()) {
    std::ostringstream error;
    error << " sub-command TRANSFORM, " << args[index] << " invalid action.";
    this->SetError(error.str());
    return false;
  }

  // Action arguments
  index += 1;
  if (args.size() < index + descriptor->Arity) {
    std::ostringstream error;
    error << "sub-command TRANSFORM, action " << descriptor->Name
          << " expects " << descriptor->Arity << " argument(s).";
    this->SetError(error.str());
    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, this->Makefile);
    } catch (const transform_error& e) {
      this->SetError(e.what());
      return false;
    }
  }

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

  // handle optional arguments
  while (args.size() > index) {
    if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) &&
        command.Selector) {
      std::ostringstream error;
      error << "sub-command TRANSFORM, selector already specified ("
            << command.Selector->Tag << ").";
      this->SetError(error.str());
      return false;
    }

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

      command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]);
      if (!command.Selector->Validate()) {
        std::ostringstream error;
        error << "sub-command TRANSFORM, selector REGEX failed to compile "
                 "regex \"";
        error << args[index] << "\".";
        this->SetError(error.str());
        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()) {
        this->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) {
        this->SetError("sub-command TRANSFORM, selector FOR expects, at least,"
                       " two arguments.");
        return false;
      }

      int start = 0, stop = 0, 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) {
        this->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) {
        this->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) {
        this->SetError("sub-command TRANSFORM, OUTPUT_VARIABLE "
                       "expects variable name argument.");
        return false;
      }

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

    std::ostringstream error;
    error << "sub-command TRANSFORM, '"
          << cmJoin(cmMakeRange(args).advance(index), " ")
          << "': unexpected argument(s).";
    this->SetError(error.str());
    return false;
  }

  // expand the list variable
  std::vector<std::string> varArgsExpanded;
  if (!this->GetList(varArgsExpanded, command.ListName)) {
    this->Makefile->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) {
    this->SetError(e.what());
    return false;
  }

  this->Makefile->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:
  typedef std::string (*StringFilter)(const std::string& in);
  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 cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
{
  assert(args.size() >= 2);
  if (args.size() > 8) {
    this->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 = messageHint + "option \"" + option +
          "\" has been specified multiple times.";
        this->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 = messageHint + "value \"" + argument +
            "\" for option \"" + option + "\" is invalid.";
          this->SetError(error);
          return false;
        }
      } else {
        std::string error =
          messageHint + "missing argument for option \"" + option + "\".";
        this->SetError(error);
        return false;
      }
    } else if (option == "CASE") {
      if (sortCaseSensitivity !=
          cmStringSorter::CaseSensitivity::UNINITIALIZED) {
        std::string error = messageHint + "option \"" + option +
          "\" has been specified multiple times.";
        this->SetError(error);
        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 {
          std::string error = messageHint + "value \"" + argument +
            "\" for option \"" + option + "\" is invalid.";
          this->SetError(error);
          return false;
        }
      } else {
        std::string error =
          messageHint + "missing argument for option \"" + option + "\".";
        this->SetError(error);
        return false;
      }
    } else if (option == "ORDER") {

      if (sortOrder != cmStringSorter::Order::UNINITIALIZED) {
        std::string error = messageHint + "option \"" + option +
          "\" has been specified multiple times.";
        this->SetError(error);
        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 {
          std::string error = messageHint + "value \"" + argument +
            "\" for option \"" + option + "\" is invalid.";
          this->SetError(error);
          return false;
        }
      } else {
        std::string error =
          messageHint + "missing argument for option \"" + option + "\".";
        this->SetError(error);
        return false;
      }
    } else {
      std::string error =
        messageHint + "option \"" + option + "\" is unknown.";
      this->SetError(error);
      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 (!this->GetList(varArgsExpanded, listName)) {
    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, ";");
  this->Makefile->AddDefinition(listName, value);
  return true;
}

bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args)
{
  if (args.size() != 5) {
    std::ostringstream error;
    error << "sub-command SUBLIST requires four arguments (" << args.size() - 1
          << " found).";
    this->SetError(error.str());
    return false;
  }

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

  // expand the variable
  std::vector<std::string> varArgsExpanded;
  if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) {
    this->Makefile->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()) {
    std::ostringstream error;
    error << "begin index: " << start << " is out of range 0 - "
          << varArgsExpanded.size() - 1;
    this->SetError(error.str());
    return false;
  }
  if (length < -1) {
    std::ostringstream error;
    error << "length: " << length << " should be -1 or greater";
    this->SetError(error.str());
    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);
  this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";"));
  return true;
}

bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
{
  if (args.size() < 3) {
    this->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 (!this->GetList(varArgsExpanded, listName) || 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)";
    this->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)) {
      std::ostringstream str;
      str << "index: " << item << " out of range (-" << nitem << ", "
          << nitem - 1 << ")";
      this->SetError(str.str());
      return false;
    }
    removed.push_back(static_cast<size_t>(item));
  }

  std::sort(removed.begin(), removed.end());
  std::vector<size_t>::const_iterator remEnd =
    std::unique(removed.begin(), removed.end());
  std::vector<size_t>::const_iterator remBegin = removed.begin();

  std::vector<std::string>::const_iterator argsEnd =
    cmRemoveIndices(varArgsExpanded, cmMakeRange(remBegin, remEnd));
  std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
  std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");

  this->Makefile->AddDefinition(listName, value);
  return true;
}

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

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

  if (args.size() < 4) {
    this->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 {
    this->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 (!this->GetList(varArgsExpanded, listName)) {
    return true;
  }

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

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

  std::vector<std::string>::iterator argsBegin = varArgsExpanded.begin();
  std::vector<std::string>::iterator argsEnd = varArgsExpanded.end();
  std::vector<std::string>::iterator newArgsEnd =
    std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches));

  std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";");
  this->Makefile->AddDefinition(listName, value);
  return true;
}
