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

#include <array>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iterator>
#include <list>
#include <sstream>
#include <utility>

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

#include "cmsys/RegularExpression.hxx"

#include "cmExpandedCommandArgument.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"

namespace {
auto const keyAND = "AND"_s;
auto const keyCOMMAND = "COMMAND"_s;
auto const keyDEFINED = "DEFINED"_s;
auto const keyEQUAL = "EQUAL"_s;
auto const keyEXISTS = "EXISTS"_s;
auto const keyGREATER = "GREATER"_s;
auto const keyGREATER_EQUAL = "GREATER_EQUAL"_s;
auto const keyIN_LIST = "IN_LIST"_s;
auto const keyIS_ABSOLUTE = "IS_ABSOLUTE"_s;
auto const keyIS_DIRECTORY = "IS_DIRECTORY"_s;
auto const keyIS_NEWER_THAN = "IS_NEWER_THAN"_s;
auto const keyIS_SYMLINK = "IS_SYMLINK"_s;
auto const keyLESS = "LESS"_s;
auto const keyLESS_EQUAL = "LESS_EQUAL"_s;
auto const keyMATCHES = "MATCHES"_s;
auto const keyNOT = "NOT"_s;
auto const keyOR = "OR"_s;
auto const keyParenL = "("_s;
auto const keyParenR = ")"_s;
auto const keyPOLICY = "POLICY"_s;
auto const keySTREQUAL = "STREQUAL"_s;
auto const keySTRGREATER = "STRGREATER"_s;
auto const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"_s;
auto const keySTRLESS = "STRLESS"_s;
auto const keySTRLESS_EQUAL = "STRLESS_EQUAL"_s;
auto const keyTARGET = "TARGET"_s;
auto const keyTEST = "TEST"_s;
auto const keyVERSION_EQUAL = "VERSION_EQUAL"_s;
auto const keyVERSION_GREATER = "VERSION_GREATER"_s;
auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s;
auto const keyVERSION_LESS = "VERSION_LESS"_s;
auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s;

cmSystemTools::CompareOp const MATCH2CMPOP[5] = {
  cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL,
  cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL,
  cmSystemTools::OP_EQUAL
};

// Run-Time to Compile-Time template selector
template <template <typename> class Comp, template <typename> class... Ops>
struct cmRt2CtSelector
{
  template <typename T>
  static bool eval(int r, T lhs, T rhs)
  {
    switch (r) {
      case 0:
        return false;
      case 1:
        return Comp<T>()(lhs, rhs);
      default:
        return cmRt2CtSelector<Ops...>::eval(r - 1, lhs, rhs);
    }
  }
};

template <template <typename> class Comp>
struct cmRt2CtSelector<Comp>
{
  template <typename T>
  static bool eval(int r, T lhs, T rhs)
  {
    return r == 1 && Comp<T>()(lhs, rhs);
  }
};

std::string bool2string(bool const value)
{
  return std::string(std::size_t(1), static_cast<char>('0' + int(value)));
}

bool looksLikeSpecialVariable(const std::string& var,
                              cm::static_string_view prefix,
                              const std::size_t varNameLen)
{
  // NOTE Expecting a variable name at least 1 char length:
  // <prefix> + `{` + <varname> + `}`
  return ((prefix.size() + 3) <= varNameLen) &&
    cmHasPrefix(var, cmStrCat(prefix, '{')) && var[varNameLen - 1] == '}';
}
} // anonymous namespace

#if defined(__SUNPRO_CC)
#  define CM_INHERIT_CTOR(Class, Base, Tpl)                                   \
    template <typename... Args>                                               \
    Class(Args&&... args)                                                     \
      : Base Tpl(std::forward<Args>(args)...)                                 \
    {                                                                         \
    }
#else
#  define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base
#endif

// BEGIN cmConditionEvaluator::cmArgumentList
class cmConditionEvaluator::cmArgumentList
  : public std::list<cmExpandedCommandArgument>
{
  using base_t = std::list<cmExpandedCommandArgument>;

public:
  CM_INHERIT_CTOR(cmArgumentList, list, <cmExpandedCommandArgument>);

  class CurrentAndNextIter
  {
    friend class cmConditionEvaluator::cmArgumentList;

  public:
    base_t::iterator current;
    base_t::iterator next;

    CurrentAndNextIter advance(base_t& args)
    {
      this->current = std::next(this->current);
      this->next =
        std::next(this->current, difference_type(this->current != args.end()));
      return *this;
    }

  private:
    CurrentAndNextIter(base_t& args)
      : current(args.begin())
      , next(std::next(this->current,
                       difference_type(this->current != args.end())))
    {
    }
  };

  class CurrentAndTwoMoreIter
  {
    friend class cmConditionEvaluator::cmArgumentList;

  public:
    base_t::iterator current;
    base_t::iterator next;
    base_t::iterator nextnext;

    CurrentAndTwoMoreIter advance(base_t& args)
    {
      this->current = std::next(this->current);
      this->next =
        std::next(this->current, difference_type(this->current != args.end()));
      this->nextnext =
        std::next(this->next, difference_type(this->next != args.end()));
      return *this;
    }

  private:
    CurrentAndTwoMoreIter(base_t& args)
      : current(args.begin())
      , next(std::next(this->current,
                       difference_type(this->current != args.end())))
      , nextnext(
          std::next(this->next, difference_type(this->next != args.end())))
    {
    }
  };

  CurrentAndNextIter make2ArgsIterator() { return *this; }
  CurrentAndTwoMoreIter make3ArgsIterator() { return *this; }

  template <typename Iter>
  void ReduceOneArg(const bool value, Iter args)
  {
    *args.current = cmExpandedCommandArgument(bool2string(value), true);
    this->erase(args.next);
  }

  void ReduceTwoArgs(const bool value, CurrentAndTwoMoreIter args)
  {
    *args.current = cmExpandedCommandArgument(bool2string(value), true);
    this->erase(args.nextnext);
    this->erase(args.next);
  }
};

// END cmConditionEvaluator::cmArgumentList

cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
                                           cmListFileBacktrace bt)
  : Makefile(makefile)
  , Backtrace(std::move(bt))
  , Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012))
  , Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))
  , Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))
  , Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064))
{
}

//=========================================================================
// order of operations,
// 1.   ( )   -- parenthetical groups
// 2.  IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates
// 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops
// 4. NOT
// 5. AND OR
//
// There is an issue on whether the arguments should be values of references,
// for example IF (FOO AND BAR) should that compare the strings FOO and BAR
// or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY
// EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can
// take numeric values or variable names. STRLESS and STRGREATER take
// variable names but if the variable name is not found it will use the name
// directly. AND OR take variables or the values 0 or 1.

bool cmConditionEvaluator::IsTrue(
  const std::vector<cmExpandedCommandArgument>& args, std::string& errorString,
  MessageType& status)
{
  errorString.clear();

  // handle empty invocation
  if (args.empty()) {
    return false;
  }

  // store the reduced args in this vector
  cmArgumentList newArgs(args.begin(), args.end());

  // now loop through the arguments and see if we can reduce any of them
  // we do this multiple times. Once for each level of precedence
  // parens
  using handlerFn_t = bool (cmConditionEvaluator::*)(
    cmArgumentList&, std::string&, MessageType&);
  const std::array<handlerFn_t, 5> handlers = { {
    &cmConditionEvaluator::HandleLevel0, // parenthesis
    &cmConditionEvaluator::HandleLevel1, // predicates
    &cmConditionEvaluator::HandleLevel2, // binary ops
    &cmConditionEvaluator::HandleLevel3, // NOT
    &cmConditionEvaluator::HandleLevel4  // AND OR
  } };
  for (auto fn : handlers) {
    // Call the reducer 'till there is anything to reduce...
    // (i.e., if after an iteration the size becomes smaller)
    auto levelResult = true;
    for (auto beginSize = newArgs.size();
         (levelResult = (this->*fn)(newArgs, errorString, status)) &&
         newArgs.size() < beginSize;
         beginSize = newArgs.size()) {
    }

    if (!levelResult) {
      // NOTE `errorString` supposed to be set already
      return false;
    }
  }

  // now at the end there should only be one argument left
  if (newArgs.size() != 1) {
    errorString = "Unknown arguments specified";
    status = MessageType::FATAL_ERROR;
    return false;
  }

  return this->GetBooleanValueWithAutoDereference(newArgs.front(), errorString,
                                                  status, true);
}

//=========================================================================
cmValue cmConditionEvaluator::GetDefinitionIfUnquoted(
  cmExpandedCommandArgument const& argument) const
{
  if ((this->Policy54Status != cmPolicies::WARN &&
       this->Policy54Status != cmPolicies::OLD) &&
      argument.WasQuoted()) {
    return nullptr;
  }

  cmValue def = this->Makefile.GetDefinition(argument.GetValue());

  if (def && argument.WasQuoted() &&
      this->Policy54Status == cmPolicies::WARN) {
    if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
      std::ostringstream e;
      // clang-format off
      e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054))
        << "\n"
           "Quoted variables like \"" << argument.GetValue() << "\" "
           "will no longer be dereferenced when the policy is set to NEW.  "
           "Since the policy is not set the OLD behavior will be used.";
      // clang-format on

      this->Makefile.GetCMakeInstance()->IssueMessage(
        MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
    }
  }

  return def;
}

//=========================================================================
cmValue cmConditionEvaluator::GetVariableOrString(
  const cmExpandedCommandArgument& argument) const
{
  cmValue def = this->GetDefinitionIfUnquoted(argument);

  if (!def) {
    def = cmValue(argument.GetValue());
  }

  return def;
}

//=========================================================================
bool cmConditionEvaluator::IsKeyword(
  cm::static_string_view keyword,
  const cmExpandedCommandArgument& argument) const
{
  if ((this->Policy54Status != cmPolicies::WARN &&
       this->Policy54Status != cmPolicies::OLD) &&
      argument.WasQuoted()) {
    return false;
  }

  const auto isKeyword = argument.GetValue() == keyword;

  if (isKeyword && argument.WasQuoted() &&
      this->Policy54Status == cmPolicies::WARN) {
    if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
      std::ostringstream e;
      // clang-format off
      e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)
        << "\n"
           "Quoted keywords like \"" << argument.GetValue() << "\" "
           "will no longer be interpreted as keywords "
           "when the policy is set to NEW.  "
           "Since the policy is not set the OLD behavior will be used.";
      // clang-format on

      this->Makefile.GetCMakeInstance()->IssueMessage(
        MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
    }
  }

  return isKeyword;
}

//=========================================================================
bool cmConditionEvaluator::GetBooleanValue(
  cmExpandedCommandArgument& arg) const
{
  // Check basic and named constants.
  if (cmIsOn(arg.GetValue())) {
    return true;
  }
  if (cmIsOff(arg.GetValue())) {
    return false;
  }

  // Check for numbers.
  if (!arg.empty()) {
    char* end;
    const double d = std::strtod(arg.GetValue().c_str(), &end);
    if (*end == '\0') {
      // The whole string is a number.  Use C conversion to bool.
      return static_cast<bool>(d);
    }
  }

  // Check definition.
  cmValue def = this->GetDefinitionIfUnquoted(arg);
  return !cmIsOff(def);
}

//=========================================================================
// Boolean value behavior from CMake 2.6.4 and below.
bool cmConditionEvaluator::GetBooleanValueOld(
  cmExpandedCommandArgument const& arg, bool const one) const
{
  if (one) {
    // Old IsTrue behavior for single argument.
    if (arg == "0") {
      return false;
    }
    if (arg == "1") {
      return true;
    }
    cmValue def = this->GetDefinitionIfUnquoted(arg);
    return !cmIsOff(def);
  }
  // Old GetVariableOrNumber behavior.
  cmValue def = this->GetDefinitionIfUnquoted(arg);
  if (!def && std::atoi(arg.GetValue().c_str())) {
    def = cmValue(arg.GetValue());
  }
  return !cmIsOff(def);
}

//=========================================================================
// returns the resulting boolean value
bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
  cmExpandedCommandArgument& newArg, std::string& errorString,
  MessageType& status, bool const oneArg) const
{
  // Use the policy if it is set.
  if (this->Policy12Status == cmPolicies::NEW) {
    return this->GetBooleanValue(newArg);
  }
  if (this->Policy12Status == cmPolicies::OLD) {
    return this->GetBooleanValueOld(newArg, oneArg);
  }

  // Check policy only if old and new results differ.
  const auto newResult = this->GetBooleanValue(newArg);
  const auto oldResult = this->GetBooleanValueOld(newArg, oneArg);
  if (newResult != oldResult) {
    switch (this->Policy12Status) {
      case cmPolicies::WARN:
        errorString = "An argument named \"" + newArg.GetValue() +
          "\" appears in a conditional statement.  " +
          cmPolicies::GetPolicyWarning(cmPolicies::CMP0012);
        status = MessageType::AUTHOR_WARNING;
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        return oldResult;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS: {
        errorString = "An argument named \"" + newArg.GetValue() +
          "\" appears in a conditional statement.  " +
          cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012);
        status = MessageType::FATAL_ERROR;
        break;
      }
      case cmPolicies::NEW:
        break;
    }
  }
  return newResult;
}

template <int N>
inline int cmConditionEvaluator::matchKeysImpl(
  const cmExpandedCommandArgument&)
{
  // Zero means "not found"
  return 0;
}

template <int N, typename T, typename... Keys>
inline int cmConditionEvaluator::matchKeysImpl(
  const cmExpandedCommandArgument& arg, T current, Keys... key)
{
  if (this->IsKeyword(current, arg)) {
    // Stop searching as soon as smth has found
    return N;
  }
  return matchKeysImpl<N + 1>(arg, key...);
}

template <typename... Keys>
inline int cmConditionEvaluator::matchKeys(
  const cmExpandedCommandArgument& arg, Keys... key)
{
  // Get index of the matched key (1-based)
  return matchKeysImpl<1>(arg, key...);
}

//=========================================================================
// level 0 processes parenthetical expressions
bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
                                        std::string& errorString,
                                        MessageType& status)
{
  for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) {
    if (this->IsKeyword(keyParenL, *arg)) {
      // search for the closing paren for this opening one
      auto depth = 1;
      auto argClose = std::next(arg);
      for (; argClose != newArgs.end() && depth; ++argClose) {
        depth += int(this->IsKeyword(keyParenL, *argClose)) -
          int(this->IsKeyword(keyParenR, *argClose));
      }
      if (depth) {
        errorString = "mismatched parenthesis in condition";
        status = MessageType::FATAL_ERROR;
        return false;
      }

      // store the reduced args in this vector
      auto argOpen = std::next(arg);
      const std::vector<cmExpandedCommandArgument> subExpr(
        argOpen, std::prev(argClose));

      // now recursively invoke IsTrue to handle the values inside the
      // parenthetical expression
      const auto value = this->IsTrue(subExpr, errorString, status);
      *arg = cmExpandedCommandArgument(bool2string(value), true);
      argOpen = std::next(arg);
      // remove the now evaluated parenthetical expression
      newArgs.erase(argOpen, argClose);
    }
  }
  return true;
}

//=========================================================================
// level one handles most predicates except for NOT
bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
                                        MessageType&)
{
  const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD ||
    this->Policy64Status == cmPolicies::WARN;

  for (auto args = newArgs.make2ArgsIterator(); args.current != newArgs.end();
       args.advance(newArgs)) {

    auto policyCheck = [&, this](const cmPolicies::PolicyID id,
                                 const cmPolicies::PolicyStatus status,
                                 const cm::static_string_view kw) {
      if (status == cmPolicies::WARN && this->IsKeyword(kw, *args.current)) {
        std::ostringstream e;
        e << cmPolicies::GetPolicyWarning(id) << "\n"
          << kw
          << " will be interpreted as an operator "
             "when the policy is set to NEW.  "
             "Since the policy is not set the OLD behavior will be used.";

        this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
      }
    };

    // NOTE Checking policies for warnings are not require an access to the
    // next arg. Check them first!
    policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST);

    // NOTE Fail fast: All the predicates below require the next arg to be
    // valid
    if (args.next == newArgs.end()) {
      continue;
    }

    // does a file exist
    if (this->IsKeyword(keyEXISTS, *args.current)) {
      newArgs.ReduceOneArg(cmSystemTools::FileExists(args.next->GetValue()),
                           args);
    }
    // does a directory with this name exist
    else if (this->IsKeyword(keyIS_DIRECTORY, *args.current)) {
      newArgs.ReduceOneArg(
        cmSystemTools::FileIsDirectory(args.next->GetValue()), args);
    }
    // does a symlink with this name exist
    else if (this->IsKeyword(keyIS_SYMLINK, *args.current)) {
      newArgs.ReduceOneArg(cmSystemTools::FileIsSymlink(args.next->GetValue()),
                           args);
    }
    // is the given path an absolute path ?
    else if (this->IsKeyword(keyIS_ABSOLUTE, *args.current)) {
      newArgs.ReduceOneArg(
        cmSystemTools::FileIsFullPath(args.next->GetValue()), args);
    }
    // does a command exist
    else if (this->IsKeyword(keyCOMMAND, *args.current)) {
      newArgs.ReduceOneArg(
        bool(this->Makefile.GetState()->GetCommand(args.next->GetValue())),
        args);
    }
    // does a policy exist
    else if (this->IsKeyword(keyPOLICY, *args.current)) {
      cmPolicies::PolicyID pid;
      newArgs.ReduceOneArg(
        cmPolicies::GetPolicyID(args.next->GetValue().c_str(), pid), args);
    }
    // does a target exist
    else if (this->IsKeyword(keyTARGET, *args.current)) {
      newArgs.ReduceOneArg(
        bool(this->Makefile.FindTargetToUse(args.next->GetValue())), args);
    }
    // is a variable defined
    else if (this->IsKeyword(keyDEFINED, *args.current)) {
      const auto& var = args.next->GetValue();
      const auto varNameLen = var.size();

      auto result = false;
      if (looksLikeSpecialVariable(var, "ENV"_s, varNameLen)) {
        const auto env = args.next->GetValue().substr(4, varNameLen - 5);
        result = cmSystemTools::HasEnv(env);
      }

      else if (looksLikeSpecialVariable(var, "CACHE"_s, varNameLen)) {
        const auto cache = args.next->GetValue().substr(6, varNameLen - 7);
        result = bool(this->Makefile.GetState()->GetCacheEntryValue(cache));
      }

      else {
        result = this->Makefile.IsDefinitionSet(args.next->GetValue());
      }
      newArgs.ReduceOneArg(result, args);
    }
    // does a test exist
    else if (this->IsKeyword(keyTEST, *args.current)) {
      if (policy64IsOld) {
        continue;
      }
      newArgs.ReduceOneArg(bool(this->Makefile.GetTest(args.next->GetValue())),
                           args);
    }
  }
  return true;
}

//=========================================================================
// level two handles most binary operations except for AND  OR
bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
                                        std::string& errorString,
                                        MessageType& status)
{
  for (auto args = newArgs.make3ArgsIterator(); args.current != newArgs.end();
       args.advance(newArgs)) {

    int matchNo;

    // NOTE Handle special case `if(... BLAH_BLAH MATCHES)`
    // (i.e., w/o regex to match which is possibly result of
    // variable expansion to an empty string)
    if (args.next != newArgs.end() &&
        this->IsKeyword(keyMATCHES, *args.current)) {
      newArgs.ReduceOneArg(false, args);
    }

    // NOTE Fail fast: All the binary ops below require 2 arguments.
    else if (args.next == newArgs.end() || args.nextnext == newArgs.end()) {
      continue;
    }

    else if (this->IsKeyword(keyMATCHES, *args.next)) {
      cmValue def = this->GetDefinitionIfUnquoted(*args.current);

      std::string def_buf;
      if (!def) {
        def = cmValue(args.current->GetValue());
      } else if (cmHasLiteralPrefix(args.current->GetValue(),
                                    "CMAKE_MATCH_")) {
        // The string to match is owned by our match result variables.
        // Move it to our own buffer before clearing them.
        def_buf = *def;
        def = cmValue(def_buf);
      }

      this->Makefile.ClearMatches();

      const auto& rex = args.nextnext->GetValue();
      cmsys::RegularExpression regEntry;
      if (!regEntry.compile(rex)) {
        std::ostringstream error;
        error << "Regular expression \"" << rex << "\" cannot compile";
        errorString = error.str();
        status = MessageType::FATAL_ERROR;
        return false;
      }

      const auto match = regEntry.find(*def);
      if (match) {
        this->Makefile.StoreMatches(regEntry);
      }
      newArgs.ReduceTwoArgs(match, args);
    }

    else if ((matchNo =
                this->matchKeys(*args.next, keyLESS, keyLESS_EQUAL, keyGREATER,
                                keyGREATER_EQUAL, keyEQUAL))) {

      cmValue ldef = this->GetVariableOrString(*args.current);
      cmValue rdef = this->GetVariableOrString(*args.nextnext);

      double lhs;
      double rhs;
      auto parseDoubles = [&]() {
        return std::sscanf(ldef->c_str(), "%lg", &lhs) == 1 &&
          std::sscanf(rdef->c_str(), "%lg", &rhs) == 1;
      };
      // clang-format off
      const auto result = parseDoubles() &&
        cmRt2CtSelector<
            std::less, std::less_equal,
            std::greater, std::greater_equal,
            std::equal_to
          >::eval(matchNo, lhs, rhs);
      // clang-format on
      newArgs.ReduceTwoArgs(result, args);
    }

    else if ((matchNo = this->matchKeys(*args.next, keySTRLESS,
                                        keySTRLESS_EQUAL, keySTRGREATER,
                                        keySTRGREATER_EQUAL, keySTREQUAL))) {

      const cmValue lhs = this->GetVariableOrString(*args.current);
      const cmValue rhs = this->GetVariableOrString(*args.nextnext);
      const auto val = (*lhs).compare(*rhs);
      // clang-format off
      const auto result = cmRt2CtSelector<
            std::less, std::less_equal,
            std::greater, std::greater_equal,
            std::equal_to
          >::eval(matchNo, val, 0);
      // clang-format on
      newArgs.ReduceTwoArgs(result, args);
    }

    else if ((matchNo =
                this->matchKeys(*args.next, keyVERSION_LESS,
                                keyVERSION_LESS_EQUAL, keyVERSION_GREATER,
                                keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) {
      const auto op = MATCH2CMPOP[matchNo - 1];
      const std::string& lhs = this->GetVariableOrString(*args.current);
      const std::string& rhs = this->GetVariableOrString(*args.nextnext);
      const auto result = cmSystemTools::VersionCompare(op, lhs, rhs);
      newArgs.ReduceTwoArgs(result, args);
    }

    // is file A newer than file B
    else if (this->IsKeyword(keyIS_NEWER_THAN, *args.next)) {
      auto fileIsNewer = 0;
      cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
        args.current->GetValue(), args.nextnext->GetValue(), &fileIsNewer);
      newArgs.ReduceTwoArgs(
        (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), args);
    }

    else if (this->IsKeyword(keyIN_LIST, *args.next)) {

      if (this->Policy57Status != cmPolicies::OLD &&
          this->Policy57Status != cmPolicies::WARN) {

        cmValue lhs = this->GetVariableOrString(*args.current);
        cmValue rhs = this->Makefile.GetDefinition(args.nextnext->GetValue());

        newArgs.ReduceTwoArgs(
          rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args);
      }

      else if (this->Policy57Status == cmPolicies::WARN) {
        std::ostringstream e;
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057)
          << "\n"
             "IN_LIST will be interpreted as an operator "
             "when the policy is set to NEW.  "
             "Since the policy is not set the OLD behavior will be used.";

        this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
      }
    }
  }
  return true;
}

//=========================================================================
// level 3 handles NOT
bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
                                        std::string& errorString,
                                        MessageType& status)
{
  for (auto args = newArgs.make2ArgsIterator(); args.next != newArgs.end();
       args.advance(newArgs)) {
    if (this->IsKeyword(keyNOT, *args.current)) {
      const auto rhs = this->GetBooleanValueWithAutoDereference(
        *args.next, errorString, status);
      newArgs.ReduceOneArg(!rhs, args);
    }
  }
  return true;
}

//=========================================================================
// level 4 handles AND OR
bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
                                        std::string& errorString,
                                        MessageType& status)
{
  for (auto args = newArgs.make3ArgsIterator(); args.nextnext != newArgs.end();
       args.advance(newArgs)) {

    int matchNo;

    if ((matchNo = this->matchKeys(*args.next, keyAND, keyOR))) {
      const auto lhs = this->GetBooleanValueWithAutoDereference(
        *args.current, errorString, status);
      const auto rhs = this->GetBooleanValueWithAutoDereference(
        *args.nextnext, errorString, status);
      // clang-format off
      const auto result =
        cmRt2CtSelector<
            std::logical_and, std::logical_or
          >::eval(matchNo, lhs, rhs);
      // clang-format on
      newArgs.ReduceTwoArgs(result, args);
    }
  }
  return true;
}
