/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2014 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "cmConditionEvaluator.h"

cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile):
  Makefile(makefile),
  Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)),
  Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))
{

}

//=========================================================================
// 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,
  cmake::MessageType &status)
{
  errorString = "";

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

  // store the reduced args in this vector
  cmArgumentList newArgs;

  // copy to the list structure
  for(unsigned int i = 0; i < args.size(); ++i)
    {
    newArgs.push_back(args[i]);
    }

  // 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
  if (!this->HandleLevel0(newArgs, errorString, status))
    {
    return false;
    }
  //predicates
  if (!this->HandleLevel1(newArgs, errorString, status))
    {
    return false;
    }
  // binary ops
  if (!this->HandleLevel2(newArgs, errorString, status))
    {
    return false;
    }

  // NOT
  if (!this->HandleLevel3(newArgs, errorString, status))
    {
    return false;
    }
  // AND OR
  if (!this->HandleLevel4(newArgs, errorString, status))
    {
    return false;
    }

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

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

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

  const char* def = this->Makefile.GetDefinition(argument.GetValue());

  if(def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN)
    {
    bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported(
      this->Makefile.GetBacktrace()[0]);

    if(!hasBeenReported)
      {
      cmOStringStream e;
      e << (this->Makefile.GetPolicies()->GetPolicyWarning(
        cmPolicies::CMP0054)) << "\n";
      e << "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.";

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

  return def;
}

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

  if(!def)
    {
    def = argument.c_str();
    }

  return def;
}

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

  bool isKeyword = argument.GetValue() == keyword;

  if(isKeyword && argument.WasQuoted() &&
    this->Policy54Status == cmPolicies::WARN)
    {
    bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported(
      this->Makefile.GetBacktrace()[0]);

    if(!hasBeenReported)
      {
      cmOStringStream e;
      e << (this->Makefile.GetPolicies()->GetPolicyWarning(
        cmPolicies::CMP0054)) << "\n";
      e << "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.";

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

  return isKeyword;
}

//=========================================================================
bool cmConditionEvaluator::GetBooleanValue(
  cmExpandedCommandArgument& arg) const
{
  // Check basic constants.
  if (arg == "0")
    {
    return false;
    }
  if (arg == "1")
    {
    return true;
    }

  // Check named constants.
  if (cmSystemTools::IsOn(arg.c_str()))
    {
    return true;
    }
  if (cmSystemTools::IsOff(arg.c_str()))
    {
    return false;
    }

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

  // Check definition.
  const char* def = this->GetDefinitionIfUnquoted(arg);
  return !cmSystemTools::IsOff(def);
}

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

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

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

//=========================================================================
void cmConditionEvaluator::IncrementArguments(cmArgumentList &newArgs,
                        cmArgumentList::iterator &argP1,
                        cmArgumentList::iterator &argP2) const
{
  if (argP1  != newArgs.end())
    {
    argP1++;
    argP2 = argP1;
    if (argP1  != newArgs.end())
      {
      argP2++;
      }
    }
}

//=========================================================================
// helper function to reduce code duplication
void cmConditionEvaluator::HandlePredicate(bool value, int &reducible,
                     cmArgumentList::iterator &arg,
                     cmArgumentList &newArgs,
                     cmArgumentList::iterator &argP1,
                     cmArgumentList::iterator &argP2) const
{
  if(value)
    {
    *arg = cmExpandedCommandArgument("1", true);
    }
  else
    {
    *arg = cmExpandedCommandArgument("0", true);
    }
  newArgs.erase(argP1);
  argP1 = arg;
  this->IncrementArguments(newArgs,argP1,argP2);
  reducible = 1;
}

//=========================================================================
// helper function to reduce code duplication
void cmConditionEvaluator::HandleBinaryOp(bool value, int &reducible,
                     cmArgumentList::iterator &arg,
                     cmArgumentList &newArgs,
                     cmArgumentList::iterator &argP1,
                     cmArgumentList::iterator &argP2)
{
  if(value)
    {
    *arg = cmExpandedCommandArgument("1", true);
    }
  else
    {
    *arg = cmExpandedCommandArgument("0", true);
    }
  newArgs.erase(argP2);
  newArgs.erase(argP1);
  argP1 = arg;
  this->IncrementArguments(newArgs,argP1,argP2);
  reducible = 1;
}

//=========================================================================
// level 0 processes parenthetical expressions
bool cmConditionEvaluator::HandleLevel0(cmArgumentList &newArgs,
                  std::string &errorString,
                  cmake::MessageType &status)
{
  int reducible;
  do
    {
    reducible = 0;
    cmArgumentList::iterator arg = newArgs.begin();
    while (arg != newArgs.end())
      {
      if (IsKeyword("(", *arg))
        {
        // search for the closing paren for this opening one
        cmArgumentList::iterator argClose;
        argClose = arg;
        argClose++;
        unsigned int depth = 1;
        while (argClose != newArgs.end() && depth)
          {
          if (this->IsKeyword("(", *argClose))
            {
              depth++;
            }
          if (this->IsKeyword(")", *argClose))
            {
              depth--;
            }
          argClose++;
          }
        if (depth)
          {
          errorString = "mismatched parenthesis in condition";
          status = cmake::FATAL_ERROR;
          return false;
          }
        // store the reduced args in this vector
        std::vector<cmExpandedCommandArgument> newArgs2;

        // copy to the list structure
        cmArgumentList::iterator argP1 = arg;
        argP1++;
        for(; argP1 != argClose; argP1++)
          {
          newArgs2.push_back(*argP1);
          }
        newArgs2.pop_back();
        // now recursively invoke IsTrue to handle the values inside the
        // parenthetical expression
        bool value =
          this->IsTrue(newArgs2, errorString, status);
        if(value)
          {
          *arg = cmExpandedCommandArgument("1", true);
          }
        else
          {
          *arg = cmExpandedCommandArgument("0", true);
          }
        argP1 = arg;
        argP1++;
        // remove the now evaluated parenthetical expression
        newArgs.erase(argP1,argClose);
        }
      ++arg;
      }
    }
  while (reducible);
  return true;
}

//=========================================================================
// level one handles most predicates except for NOT
bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs,
                  std::string &, cmake::MessageType &)
{
  int reducible;
  do
    {
    reducible = 0;
    cmArgumentList::iterator arg = newArgs.begin();
    cmArgumentList::iterator argP1;
    cmArgumentList::iterator argP2;
    while (arg != newArgs.end())
      {
      argP1 = arg;
      this->IncrementArguments(newArgs,argP1,argP2);
      // does a file exist
      if (this->IsKeyword("EXISTS", *arg) && argP1  != newArgs.end())
        {
        this->HandlePredicate(
          cmSystemTools::FileExists(argP1->c_str()),
          reducible, arg, newArgs, argP1, argP2);
        }
      // does a directory with this name exist
      if (this->IsKeyword("IS_DIRECTORY", *arg) && argP1  != newArgs.end())
        {
        this->HandlePredicate(
          cmSystemTools::FileIsDirectory(argP1->c_str()),
          reducible, arg, newArgs, argP1, argP2);
        }
      // does a symlink with this name exist
      if (this->IsKeyword("IS_SYMLINK", *arg) && argP1  != newArgs.end())
        {
        this->HandlePredicate(
          cmSystemTools::FileIsSymlink(argP1->c_str()),
          reducible, arg, newArgs, argP1, argP2);
        }
      // is the given path an absolute path ?
      if (this->IsKeyword("IS_ABSOLUTE", *arg) && argP1  != newArgs.end())
        {
        this->HandlePredicate(
          cmSystemTools::FileIsFullPath(argP1->c_str()),
          reducible, arg, newArgs, argP1, argP2);
        }
      // does a command exist
      if (this->IsKeyword("COMMAND", *arg) && argP1  != newArgs.end())
        {
        this->HandlePredicate(
          this->Makefile.CommandExists(argP1->c_str()),
          reducible, arg, newArgs, argP1, argP2);
        }
      // does a policy exist
      if (this->IsKeyword("POLICY", *arg) && argP1 != newArgs.end())
        {
        cmPolicies::PolicyID pid;
        this->HandlePredicate(
          this->Makefile.GetPolicies()->GetPolicyID(
            argP1->c_str(), pid),
            reducible, arg, newArgs, argP1, argP2);
        }
      // does a target exist
      if (this->IsKeyword("TARGET", *arg) && argP1 != newArgs.end())
        {
        this->HandlePredicate(
          this->Makefile.FindTargetToUse(argP1->GetValue())?true:false,
          reducible, arg, newArgs, argP1, argP2);
        }
      // is a variable defined
      if (this->IsKeyword("DEFINED", *arg) && argP1  != newArgs.end())
        {
        size_t argP1len = argP1->GetValue().size();
        bool bdef = false;
        if(argP1len > 4 && argP1->GetValue().substr(0, 4) == "ENV{" &&
           argP1->GetValue().operator[](argP1len-1) == '}')
          {
          std::string env = argP1->GetValue().substr(4, argP1len-5);
          bdef = cmSystemTools::GetEnv(env.c_str())?true:false;
          }
        else
          {
          bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
          }
        this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
        }
      ++arg;
      }
    }
  while (reducible);
  return true;
}

//=========================================================================
// level two handles most binary operations except for AND  OR
bool cmConditionEvaluator::HandleLevel2(cmArgumentList &newArgs,
                  std::string &errorString,
                  cmake::MessageType &status)
{
  int reducible;
  const char *def;
  const char *def2;
  do
    {
    reducible = 0;
    cmArgumentList::iterator arg = newArgs.begin();
    cmArgumentList::iterator argP1;
    cmArgumentList::iterator argP2;
    while (arg != newArgs.end())
      {
      argP1 = arg;
      this->IncrementArguments(newArgs,argP1,argP2);
      if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
        IsKeyword("MATCHES", *argP1))
        {
        def = this->GetVariableOrString(*arg);
        const char* rex = argP2->c_str();
        this->Makefile.ClearMatches();
        cmsys::RegularExpression regEntry;
        if ( !regEntry.compile(rex) )
          {
          cmOStringStream error;
          error << "Regular expression \"" << rex << "\" cannot compile";
          errorString = error.str();
          status = cmake::FATAL_ERROR;
          return false;
          }
        if (regEntry.find(def))
          {
          this->Makefile.StoreMatches(regEntry);
          *arg = cmExpandedCommandArgument("1", true);
          }
        else
          {
          *arg = cmExpandedCommandArgument("0", true);
          }
        newArgs.erase(argP2);
        newArgs.erase(argP1);
        argP1 = arg;
        this->IncrementArguments(newArgs,argP1,argP2);
        reducible = 1;
        }

      if (argP1 != newArgs.end() && this->IsKeyword("MATCHES", *arg))
        {
        *arg = cmExpandedCommandArgument("0", true);
        newArgs.erase(argP1);
        argP1 = arg;
        this->IncrementArguments(newArgs,argP1,argP2);
        reducible = 1;
        }

      if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
        (this->IsKeyword("LESS", *argP1) ||
         this->IsKeyword("GREATER", *argP1) ||
         this->IsKeyword("EQUAL", *argP1)))
        {
        def = this->GetVariableOrString(*arg);
        def2 = this->GetVariableOrString(*argP2);
        double lhs;
        double rhs;
        bool result;
        if(sscanf(def, "%lg", &lhs) != 1 ||
           sscanf(def2, "%lg", &rhs) != 1)
          {
          result = false;
          }
        else if (*(argP1) == "LESS")
          {
          result = (lhs < rhs);
          }
        else if (*(argP1) == "GREATER")
          {
          result = (lhs > rhs);
          }
        else
          {
          result = (lhs == rhs);
          }
        this->HandleBinaryOp(result,
          reducible, arg, newArgs, argP1, argP2);
        }

      if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
        (this->IsKeyword("STRLESS", *argP1) ||
         this->IsKeyword("STREQUAL", *argP1) ||
         this->IsKeyword("STRGREATER", *argP1)))
        {
        def = this->GetVariableOrString(*arg);
        def2 = this->GetVariableOrString(*argP2);
        int val = strcmp(def,def2);
        bool result;
        if (*(argP1) == "STRLESS")
          {
          result = (val < 0);
          }
        else if (*(argP1) == "STRGREATER")
          {
          result = (val > 0);
          }
        else // strequal
          {
          result = (val == 0);
          }
        this->HandleBinaryOp(result,
          reducible, arg, newArgs, argP1, argP2);
        }

      if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
        (this->IsKeyword("VERSION_LESS", *argP1) ||
         this->IsKeyword("VERSION_GREATER", *argP1) ||
         this->IsKeyword("VERSION_EQUAL", *argP1)))
        {
        def = this->GetVariableOrString(*arg);
        def2 = this->GetVariableOrString(*argP2);
        cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL;
        if(*argP1 == "VERSION_LESS")
          {
          op = cmSystemTools::OP_LESS;
          }
        else if(*argP1 == "VERSION_GREATER")
          {
          op = cmSystemTools::OP_GREATER;
          }
        bool result = cmSystemTools::VersionCompare(op, def, def2);
        this->HandleBinaryOp(result,
          reducible, arg, newArgs, argP1, argP2);
        }

      // is file A newer than file B
      if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
          this->IsKeyword("IS_NEWER_THAN", *argP1))
        {
        int fileIsNewer=0;
        bool success=cmSystemTools::FileTimeCompare(arg->GetValue(),
            (argP2)->GetValue(),
            &fileIsNewer);
        this->HandleBinaryOp(
          (success==false || fileIsNewer==1 || fileIsNewer==0),
          reducible, arg, newArgs, argP1, argP2);
        }

      ++arg;
      }
    }
  while (reducible);
  return true;
}

//=========================================================================
// level 3 handles NOT
bool cmConditionEvaluator::HandleLevel3(cmArgumentList &newArgs,
                  std::string &errorString,
                  cmake::MessageType &status)
{
  int reducible;
  do
    {
    reducible = 0;
    cmArgumentList::iterator arg = newArgs.begin();
    cmArgumentList::iterator argP1;
    cmArgumentList::iterator argP2;
    while (arg != newArgs.end())
      {
      argP1 = arg;
      IncrementArguments(newArgs,argP1,argP2);
      if (argP1 != newArgs.end() && IsKeyword("NOT", *arg))
        {
        bool rhs = this->GetBooleanValueWithAutoDereference(*argP1,
                                                      errorString,
                                                      status);
        this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
        }
      ++arg;
      }
    }
  while (reducible);
  return true;
}

//=========================================================================
// level 4 handles AND OR
bool cmConditionEvaluator::HandleLevel4(cmArgumentList &newArgs,
                  std::string &errorString,
                  cmake::MessageType &status)
{
  int reducible;
  bool lhs;
  bool rhs;
  do
    {
    reducible = 0;
    cmArgumentList::iterator arg = newArgs.begin();
    cmArgumentList::iterator argP1;
    cmArgumentList::iterator argP2;
    while (arg != newArgs.end())
      {
      argP1 = arg;
      IncrementArguments(newArgs,argP1,argP2);
      if (argP1 != newArgs.end() && IsKeyword("AND", *argP1) &&
        argP2 != newArgs.end())
        {
        lhs = this->GetBooleanValueWithAutoDereference(*arg,
                                                 errorString,
                                                 status);
        rhs = this->GetBooleanValueWithAutoDereference(*argP2,
                                                 errorString,
                                                 status);
        this->HandleBinaryOp((lhs && rhs),
          reducible, arg, newArgs, argP1, argP2);
        }

      if (argP1 != newArgs.end() && this->IsKeyword("OR", *argP1) &&
        argP2 != newArgs.end())
        {
        lhs = this->GetBooleanValueWithAutoDereference(*arg,
                                                 errorString,
                                                 status);
        rhs = this->GetBooleanValueWithAutoDereference(*argP2,
                                                 errorString,
                                                 status);
        this->HandleBinaryOp((lhs || rhs),
          reducible, arg, newArgs, argP1, argP2);
        }
      ++arg;
      }
    }
  while (reducible);
  return true;
}
