|
@@ -21,8 +21,10 @@
|
|
|
#include <list>
|
|
#include <list>
|
|
|
#include <cmsys/RegularExpression.hxx>
|
|
#include <cmsys/RegularExpression.hxx>
|
|
|
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
bool cmIfFunctionBlocker::
|
|
bool cmIfFunctionBlocker::
|
|
|
-IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
|
|
|
|
|
|
|
+IsFunctionBlocked(const cmListFileFunction& lff,
|
|
|
|
|
+ cmMakefile &mf,
|
|
|
cmExecutionStatus &inStatus)
|
|
cmExecutionStatus &inStatus)
|
|
|
{
|
|
{
|
|
|
// Prevent recusion and don't let this blocker block its own
|
|
// Prevent recusion and don't let this blocker block its own
|
|
@@ -140,6 +142,7 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|
|
cmMakefile&)
|
|
cmMakefile&)
|
|
|
{
|
|
{
|
|
@@ -157,8 +160,8 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void cmIfFunctionBlocker::
|
|
|
|
|
-ScopeEnded(cmMakefile &mf)
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
|
|
+void cmIfFunctionBlocker::ScopeEnded(cmMakefile &mf)
|
|
|
{
|
|
{
|
|
|
std::string errmsg = "The end of a CMakeLists file was reached with an "
|
|
std::string errmsg = "The end of a CMakeLists file was reached with an "
|
|
|
"IF statement that was not closed properly.\nWithin the directory: ";
|
|
"IF statement that was not closed properly.\nWithin the directory: ";
|
|
@@ -175,6 +178,7 @@ ScopeEnded(cmMakefile &mf)
|
|
|
cmSystemTools::Message(errmsg.c_str(), "Warning");
|
|
cmSystemTools::Message(errmsg.c_str(), "Warning");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
bool cmIfCommand
|
|
bool cmIfCommand
|
|
|
::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
|
|
::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
|
|
|
cmExecutionStatus &)
|
|
cmExecutionStatus &)
|
|
@@ -221,6 +225,7 @@ bool cmIfCommand
|
|
|
|
|
|
|
|
namespace
|
|
namespace
|
|
|
{
|
|
{
|
|
|
|
|
+//=========================================================================
|
|
|
void IncrementArguments(std::list<std::string> &newArgs,
|
|
void IncrementArguments(std::list<std::string> &newArgs,
|
|
|
std::list<std::string>::iterator &argP1,
|
|
std::list<std::string>::iterator &argP1,
|
|
|
std::list<std::string>::iterator &argP2)
|
|
std::list<std::string>::iterator &argP2)
|
|
@@ -235,68 +240,108 @@ namespace
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// order of operations,
|
|
|
|
|
-// IS_DIRECTORY EXISTS COMMAND DEFINED
|
|
|
|
|
-// MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL
|
|
|
|
|
-// 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 cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
|
|
- char **errorString, cmMakefile *makefile)
|
|
|
|
|
-{
|
|
|
|
|
- // check for the different signatures
|
|
|
|
|
- const char *def;
|
|
|
|
|
- const char *def2;
|
|
|
|
|
- const char* msg = "Unknown arguments specified";
|
|
|
|
|
- *errorString = new char[strlen(msg) + 1];
|
|
|
|
|
- strcpy(*errorString, msg);
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // helper function to reduce code duplication
|
|
|
|
|
+ void HandlePredicate(bool value, int &reducible,
|
|
|
|
|
+ std::list<std::string>::iterator &arg,
|
|
|
|
|
+ std::list<std::string> &newArgs,
|
|
|
|
|
+ std::list<std::string>::iterator &argP1,
|
|
|
|
|
+ std::list<std::string>::iterator &argP2)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(value)
|
|
|
|
|
+ {
|
|
|
|
|
+ *arg = "1";
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ *arg = "0";
|
|
|
|
|
+ }
|
|
|
|
|
+ newArgs.erase(argP1);
|
|
|
|
|
+ argP1 = arg;
|
|
|
|
|
+ IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
+ reducible = 1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // handle empty invocation
|
|
|
|
|
- if (args.size() < 1)
|
|
|
|
|
- {
|
|
|
|
|
- delete [] *errorString;
|
|
|
|
|
- *errorString = 0;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // helper function to reduce code duplication
|
|
|
|
|
+ void HandleBinaryOp(bool value, int &reducible,
|
|
|
|
|
+ std::list<std::string>::iterator &arg,
|
|
|
|
|
+ std::list<std::string> &newArgs,
|
|
|
|
|
+ std::list<std::string>::iterator &argP1,
|
|
|
|
|
+ std::list<std::string>::iterator &argP2)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(value)
|
|
|
|
|
+ {
|
|
|
|
|
+ *arg = "1";
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ *arg = "0";
|
|
|
|
|
+ }
|
|
|
|
|
+ newArgs.erase(argP2);
|
|
|
|
|
+ newArgs.erase(argP1);
|
|
|
|
|
+ argP1 = arg;
|
|
|
|
|
+ IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
+ reducible = 1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // store the reduced args in this vector
|
|
|
|
|
- std::list<std::string> newArgs;
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // level 0 processes parenthetical expressions
|
|
|
|
|
+ bool HandleLevel0(std::list<std::string> &newArgs,
|
|
|
|
|
+ cmMakefile *makefile,
|
|
|
|
|
+ char **errorString)
|
|
|
|
|
+ {
|
|
|
int reducible;
|
|
int reducible;
|
|
|
- unsigned int i;
|
|
|
|
|
-
|
|
|
|
|
- // copy to the list structure
|
|
|
|
|
- for(i = 0; i < args.size(); ++i)
|
|
|
|
|
- {
|
|
|
|
|
- newArgs.push_back(args[i]);
|
|
|
|
|
- }
|
|
|
|
|
- std::list<std::string>::iterator argP1;
|
|
|
|
|
- std::list<std::string>::iterator argP2;
|
|
|
|
|
-
|
|
|
|
|
- // 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
|
|
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
reducible = 0;
|
|
reducible = 0;
|
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
|
while (arg != newArgs.end())
|
|
while (arg != newArgs.end())
|
|
|
{
|
|
{
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- // does a file exist
|
|
|
|
|
- if (*arg == "EXISTS" && argP1 != newArgs.end())
|
|
|
|
|
|
|
+ if (*arg == "(")
|
|
|
{
|
|
{
|
|
|
- if(cmSystemTools::FileExists((argP1)->c_str()))
|
|
|
|
|
|
|
+ // search for the closing paren for this opening one
|
|
|
|
|
+ std::list<std::string>::iterator argClose;
|
|
|
|
|
+ argClose = arg;
|
|
|
|
|
+ argClose++;
|
|
|
|
|
+ unsigned int depth = 1;
|
|
|
|
|
+ while (argClose != newArgs.end() && depth)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (*argClose == "(")
|
|
|
|
|
+ {
|
|
|
|
|
+ depth++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (*argClose == ")")
|
|
|
|
|
+ {
|
|
|
|
|
+ depth--;
|
|
|
|
|
+ }
|
|
|
|
|
+ argClose++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (depth)
|
|
|
|
|
+ {
|
|
|
|
|
+ cmOStringStream error;
|
|
|
|
|
+ error << "mismatched parenthesis in condition";
|
|
|
|
|
+ delete [] *errorString;
|
|
|
|
|
+ *errorString = new char[error.str().size() + 1];
|
|
|
|
|
+ strcpy(*errorString, error.str().c_str());
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // store the reduced args in this vector
|
|
|
|
|
+ std::vector<std::string> newArgs2;
|
|
|
|
|
+
|
|
|
|
|
+ // copy to the list structure
|
|
|
|
|
+ std::list<std::string>::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 =
|
|
|
|
|
+ cmIfCommand::IsTrue(newArgs2, errorString, makefile);
|
|
|
|
|
+ if(value)
|
|
|
{
|
|
{
|
|
|
*arg = "1";
|
|
*arg = "1";
|
|
|
}
|
|
}
|
|
@@ -304,75 +349,70 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
{
|
|
{
|
|
|
*arg = "0";
|
|
*arg = "0";
|
|
|
}
|
|
}
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
argP1 = arg;
|
|
argP1 = arg;
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ 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 HandleLevel1(std::list<std::string> &newArgs,
|
|
|
|
|
+ cmMakefile *makefile,
|
|
|
|
|
+ char **)
|
|
|
|
|
+ {
|
|
|
|
|
+ int reducible;
|
|
|
|
|
+ do
|
|
|
|
|
+ {
|
|
|
|
|
+ reducible = 0;
|
|
|
|
|
+ std::list<std::string>::iterator arg = newArgs.begin();
|
|
|
|
|
+ std::list<std::string>::iterator argP1;
|
|
|
|
|
+ std::list<std::string>::iterator argP2;
|
|
|
|
|
+ while (arg != newArgs.end())
|
|
|
|
|
+ {
|
|
|
|
|
+ argP1 = arg;
|
|
|
|
|
+ IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
+ // does a file exist
|
|
|
|
|
+ if (*arg == "EXISTS" && argP1 != newArgs.end())
|
|
|
|
|
+ {
|
|
|
|
|
+ HandlePredicate(
|
|
|
|
|
+ cmSystemTools::FileExists((argP1)->c_str()),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
// does a directory with this name exist
|
|
// does a directory with this name exist
|
|
|
if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end())
|
|
if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end())
|
|
|
{
|
|
{
|
|
|
- if(cmSystemTools::FileIsDirectory((argP1)->c_str()))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(
|
|
|
|
|
+ cmSystemTools::FileIsDirectory((argP1)->c_str()),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
// is the given path an absolute path ?
|
|
// is the given path an absolute path ?
|
|
|
if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end())
|
|
if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end())
|
|
|
{
|
|
{
|
|
|
- if(cmSystemTools::FileIsFullPath((argP1)->c_str()))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(
|
|
|
|
|
+ cmSystemTools::FileIsFullPath((argP1)->c_str()),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
// does a command exist
|
|
// does a command exist
|
|
|
if (*arg == "COMMAND" && argP1 != newArgs.end())
|
|
if (*arg == "COMMAND" && argP1 != newArgs.end())
|
|
|
{
|
|
{
|
|
|
- if(makefile->CommandExists((argP1)->c_str()))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(
|
|
|
|
|
+ makefile->CommandExists((argP1)->c_str()),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
// does a policy exist
|
|
// does a policy exist
|
|
|
if (*arg == "POLICY" && argP1 != newArgs.end())
|
|
if (*arg == "POLICY" && argP1 != newArgs.end())
|
|
|
{
|
|
{
|
|
|
cmPolicies::PolicyID pid;
|
|
cmPolicies::PolicyID pid;
|
|
|
- if(makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(
|
|
|
|
|
+ makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
// is a variable defined
|
|
// is a variable defined
|
|
|
if (*arg == "DEFINED" && argP1 != newArgs.end())
|
|
if (*arg == "DEFINED" && argP1 != newArgs.end())
|
|
@@ -389,32 +429,30 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
{
|
|
{
|
|
|
bdef = makefile->IsDefinitionSet((argP1)->c_str());
|
|
bdef = makefile->IsDefinitionSet((argP1)->c_str());
|
|
|
}
|
|
}
|
|
|
- if(bdef)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
++arg;
|
|
++arg;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
while (reducible);
|
|
while (reducible);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- // 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
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // level two handles most binary operations except for AND OR
|
|
|
|
|
+ bool HandleLevel2(std::list<std::string> &newArgs,
|
|
|
|
|
+ cmMakefile *makefile,
|
|
|
|
|
+ char **errorString)
|
|
|
|
|
+ {
|
|
|
|
|
+ int reducible;
|
|
|
|
|
+ const char *def;
|
|
|
|
|
+ const char *def2;
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
reducible = 0;
|
|
reducible = 0;
|
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
|
-
|
|
|
|
|
|
|
+ std::list<std::string>::iterator argP1;
|
|
|
|
|
+ std::list<std::string>::iterator argP2;
|
|
|
while (arg != newArgs.end())
|
|
while (arg != newArgs.end())
|
|
|
{
|
|
{
|
|
|
argP1 = arg;
|
|
argP1 = arg;
|
|
@@ -468,49 +506,26 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
|
|
def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
|
|
|
double lhs;
|
|
double lhs;
|
|
|
double rhs;
|
|
double rhs;
|
|
|
|
|
+ bool result;
|
|
|
if(sscanf(def, "%lg", &lhs) != 1 ||
|
|
if(sscanf(def, "%lg", &lhs) != 1 ||
|
|
|
sscanf(def2, "%lg", &rhs) != 1)
|
|
sscanf(def2, "%lg", &rhs) != 1)
|
|
|
{
|
|
{
|
|
|
- *arg = "0";
|
|
|
|
|
|
|
+ result = false;
|
|
|
}
|
|
}
|
|
|
else if (*(argP1) == "LESS")
|
|
else if (*(argP1) == "LESS")
|
|
|
{
|
|
{
|
|
|
- if(lhs < rhs)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = (lhs < rhs);
|
|
|
}
|
|
}
|
|
|
else if (*(argP1) == "GREATER")
|
|
else if (*(argP1) == "GREATER")
|
|
|
{
|
|
{
|
|
|
- if(lhs > rhs)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = (lhs > rhs);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- if(lhs == rhs)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result = (lhs == rhs);
|
|
|
}
|
|
}
|
|
|
- newArgs.erase(argP2);
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandleBinaryOp(result,
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
|
|
if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
|
|
@@ -521,7 +536,7 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
|
|
def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
|
|
|
def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
|
|
def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
|
|
|
int val = strcmp(def,def2);
|
|
int val = strcmp(def,def2);
|
|
|
- int result;
|
|
|
|
|
|
|
+ bool result;
|
|
|
if (*(argP1) == "STRLESS")
|
|
if (*(argP1) == "STRLESS")
|
|
|
{
|
|
{
|
|
|
result = (val < 0);
|
|
result = (val < 0);
|
|
@@ -534,19 +549,8 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
{
|
|
{
|
|
|
result = (val == 0);
|
|
result = (val == 0);
|
|
|
}
|
|
}
|
|
|
- if(result)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP2);
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandleBinaryOp(result,
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// is file A newer than file B
|
|
// is file A newer than file B
|
|
@@ -557,33 +561,32 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
bool success=cmSystemTools::FileTimeCompare(arg->c_str(),
|
|
bool success=cmSystemTools::FileTimeCompare(arg->c_str(),
|
|
|
(argP2)->c_str(),
|
|
(argP2)->c_str(),
|
|
|
&fileIsNewer);
|
|
&fileIsNewer);
|
|
|
- if(success==false || fileIsNewer==1 || fileIsNewer==0)
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP2);
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandleBinaryOp(
|
|
|
|
|
+ (success==false || fileIsNewer==1 || fileIsNewer==0),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
++arg;
|
|
++arg;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
while (reducible);
|
|
while (reducible);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- // 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
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // level 3 handles NOT
|
|
|
|
|
+ bool HandleLevel3(std::list<std::string> &newArgs,
|
|
|
|
|
+ cmMakefile *makefile,
|
|
|
|
|
+ char **)
|
|
|
|
|
+ {
|
|
|
|
|
+ int reducible;
|
|
|
|
|
+ const char *def;
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
reducible = 0;
|
|
reducible = 0;
|
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
|
|
|
+ std::list<std::string>::iterator argP1;
|
|
|
|
|
+ std::list<std::string>::iterator argP2;
|
|
|
while (arg != newArgs.end())
|
|
while (arg != newArgs.end())
|
|
|
{
|
|
{
|
|
|
argP1 = arg;
|
|
argP1 = arg;
|
|
@@ -591,30 +594,31 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
if (argP1 != newArgs.end() && *arg == "NOT")
|
|
if (argP1 != newArgs.end() && *arg == "NOT")
|
|
|
{
|
|
{
|
|
|
def = cmIfCommand::GetVariableOrNumber((argP1)->c_str(), makefile);
|
|
def = cmIfCommand::GetVariableOrNumber((argP1)->c_str(), makefile);
|
|
|
- if(!cmSystemTools::IsOff(def))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandlePredicate(cmSystemTools::IsOff(def),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
++arg;
|
|
++arg;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
while (reducible);
|
|
while (reducible);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 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
|
|
|
|
|
|
|
+ //=========================================================================
|
|
|
|
|
+ // level 4 handles AND OR
|
|
|
|
|
+ bool HandleLevel4(std::list<std::string> &newArgs,
|
|
|
|
|
+ cmMakefile *makefile,
|
|
|
|
|
+ char **)
|
|
|
|
|
+ {
|
|
|
|
|
+ int reducible;
|
|
|
|
|
+ const char *def;
|
|
|
|
|
+ const char *def2;
|
|
|
do
|
|
do
|
|
|
{
|
|
{
|
|
|
reducible = 0;
|
|
reducible = 0;
|
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
std::list<std::string>::iterator arg = newArgs.begin();
|
|
|
|
|
+ std::list<std::string>::iterator argP1;
|
|
|
|
|
+ std::list<std::string>::iterator argP2;
|
|
|
while (arg != newArgs.end())
|
|
while (arg != newArgs.end())
|
|
|
{
|
|
{
|
|
|
argP1 = arg;
|
|
argP1 = arg;
|
|
@@ -624,19 +628,9 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
{
|
|
{
|
|
|
def = cmIfCommand::GetVariableOrNumber(arg->c_str(), makefile);
|
|
def = cmIfCommand::GetVariableOrNumber(arg->c_str(), makefile);
|
|
|
def2 = cmIfCommand::GetVariableOrNumber((argP2)->c_str(), makefile);
|
|
def2 = cmIfCommand::GetVariableOrNumber((argP2)->c_str(), makefile);
|
|
|
- if(cmSystemTools::IsOff(def) || cmSystemTools::IsOff(def2))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP2);
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandleBinaryOp(
|
|
|
|
|
+ !(cmSystemTools::IsOff(def) || cmSystemTools::IsOff(def2)),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (argP1 != newArgs.end() && *(argP1) == "OR" &&
|
|
if (argP1 != newArgs.end() && *(argP1) == "OR" &&
|
|
@@ -644,25 +638,84 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
{
|
|
{
|
|
|
def = cmIfCommand::GetVariableOrNumber(arg->c_str(), makefile);
|
|
def = cmIfCommand::GetVariableOrNumber(arg->c_str(), makefile);
|
|
|
def2 = cmIfCommand::GetVariableOrNumber((argP2)->c_str(), makefile);
|
|
def2 = cmIfCommand::GetVariableOrNumber((argP2)->c_str(), makefile);
|
|
|
- if(cmSystemTools::IsOff(def) && cmSystemTools::IsOff(def2))
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "0";
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- *arg = "1";
|
|
|
|
|
- }
|
|
|
|
|
- newArgs.erase(argP2);
|
|
|
|
|
- newArgs.erase(argP1);
|
|
|
|
|
- argP1 = arg;
|
|
|
|
|
- IncrementArguments(newArgs,argP1,argP2);
|
|
|
|
|
- reducible = 1;
|
|
|
|
|
|
|
+ HandleBinaryOp(
|
|
|
|
|
+ !(cmSystemTools::IsOff(def) && cmSystemTools::IsOff(def2)),
|
|
|
|
|
+ reducible, arg, newArgs, argP1, argP2);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
++arg;
|
|
++arg;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
while (reducible);
|
|
while (reducible);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+//=========================================================================
|
|
|
|
|
+// 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 cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
|
|
+ char **errorString, cmMakefile *makefile)
|
|
|
|
|
+{
|
|
|
|
|
+ // check for the different signatures
|
|
|
|
|
+ const char *def;
|
|
|
|
|
+ const char* msg = "Unknown arguments specified";
|
|
|
|
|
+ *errorString = new char[strlen(msg) + 1];
|
|
|
|
|
+ strcpy(*errorString, msg);
|
|
|
|
|
+
|
|
|
|
|
+ // handle empty invocation
|
|
|
|
|
+ if (args.size() < 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ delete [] *errorString;
|
|
|
|
|
+ *errorString = 0;
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // store the reduced args in this vector
|
|
|
|
|
+ std::list<std::string> 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
|
|
|
|
|
+ if (!HandleLevel0(newArgs, makefile, errorString)) // parens
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!HandleLevel1(newArgs, makefile, errorString)) //predicates
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!HandleLevel2(newArgs, makefile, errorString)) // binary ops
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!HandleLevel3(newArgs, makefile, errorString)) // NOT
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!HandleLevel4(newArgs, makefile, errorString)) // AND OR
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// now at the end there should only be one argument left
|
|
// now at the end there should only be one argument left
|
|
|
if (newArgs.size() == 1)
|
|
if (newArgs.size() == 1)
|
|
@@ -687,6 +740,7 @@ bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
const char* cmIfCommand::GetVariableOrString(const char* str,
|
|
const char* cmIfCommand::GetVariableOrString(const char* str,
|
|
|
const cmMakefile* mf)
|
|
const cmMakefile* mf)
|
|
|
{
|
|
{
|
|
@@ -698,6 +752,7 @@ const char* cmIfCommand::GetVariableOrString(const char* str,
|
|
|
return def;
|
|
return def;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=========================================================================
|
|
|
const char* cmIfCommand::GetVariableOrNumber(const char* str,
|
|
const char* cmIfCommand::GetVariableOrNumber(const char* str,
|
|
|
const cmMakefile* mf)
|
|
const cmMakefile* mf)
|
|
|
{
|
|
{
|