diff options
Diffstat (limited to 'Source/cmIfCommand.cxx')
-rw-r--r-- | Source/cmIfCommand.cxx | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx new file mode 100644 index 0000000..56d7170 --- /dev/null +++ b/Source/cmIfCommand.cxx @@ -0,0 +1,951 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 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 "cmIfCommand.h" +#include "cmStringCommand.h" + +#include <stdlib.h> // required for atof +#include <list> +#include <cmsys/RegularExpression.hxx> + + +static std::string cmIfCommandError( + cmMakefile* mf, std::vector<std::string> const& args) +{ + cmLocalGenerator* lg = mf->GetLocalGenerator(); + std::string err = "given arguments:\n "; + for(std::vector<std::string>::const_iterator i = args.begin(); + i != args.end(); ++i) + { + err += " "; + err += lg->EscapeForCMake(i->c_str()); + } + err += "\n"; + return err; +} + +//========================================================================= +bool cmIfFunctionBlocker:: +IsFunctionBlocked(const cmListFileFunction& lff, + cmMakefile &mf, + cmExecutionStatus &inStatus) +{ + // we start by recording all the functions + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"if")) + { + this->ScopeDepth++; + } + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif")) + { + this->ScopeDepth--; + // if this is the endif for this if statement, then start executing + if (!this->ScopeDepth) + { + // Remove the function blocker for this scope or bail. + cmsys::auto_ptr<cmFunctionBlocker> + fb(mf.RemoveFunctionBlocker(this, lff)); + if(!fb.get()) { return false; } + + // execute the functions for the true parts of the if statement + cmExecutionStatus status; + int scopeDepth = 0; + for(unsigned int c = 0; c < this->Functions.size(); ++c) + { + // keep track of scope depth + if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"if")) + { + scopeDepth++; + } + if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"endif")) + { + scopeDepth--; + } + // watch for our state change + if (scopeDepth == 0 && + !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"else")) + { + this->IsBlocking = this->HasRun; + this->HasRun = true; + + // if trace is enabled, print a (trivially) evaluated "else" + // statement + if(!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) + { + mf.PrintCommandTrace(this->Functions[c]); + } + } + else if (scopeDepth == 0 && !cmSystemTools::Strucmp + (this->Functions[c].Name.c_str(),"elseif")) + { + if (this->HasRun) + { + this->IsBlocking = true; + } + else + { + // Place this call on the call stack. + cmMakefileCall stack_manager(&mf, this->Functions[c], status); + static_cast<void>(stack_manager); + + // if trace is enabled, print the evaluated "elseif" statement + if(mf.GetCMakeInstance()->GetTrace()) + { + mf.PrintCommandTrace(this->Functions[c]); + } + + std::string errorString; + + std::vector<std::string> expandedArguments; + mf.ExpandArguments(this->Functions[c].Arguments, + expandedArguments); + + cmake::MessageType messType; + bool isTrue = + cmIfCommand::IsTrue(expandedArguments, errorString, + &mf, messType); + + if (errorString.size()) + { + std::string err = cmIfCommandError(&mf, expandedArguments); + err += errorString; + mf.IssueMessage(messType, err); + if (messType == cmake::FATAL_ERROR) + { + cmSystemTools::SetFatalErrorOccured(); + return true; + } + } + + if (isTrue) + { + this->IsBlocking = false; + this->HasRun = true; + } + } + } + + // should we execute? + else if (!this->IsBlocking) + { + status.Clear(); + mf.ExecuteCommand(this->Functions[c],status); + if (status.GetReturnInvoked()) + { + inStatus.SetReturnInvoked(true); + return true; + } + if (status.GetBreakInvoked()) + { + inStatus.SetBreakInvoked(true); + return true; + } + } + } + return true; + } + } + + // record the command + this->Functions.push_back(lff); + + // always return true + return true; +} + +//========================================================================= +bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, + cmMakefile&) +{ + if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif")) + { + // if the endif has arguments, then make sure + // they match the arguments of the matching if + if (lff.Arguments.size() == 0 || + lff.Arguments == this->Args) + { + return true; + } + } + + return false; +} + +//========================================================================= +bool cmIfCommand +::InvokeInitialPass(const std::vector<cmListFileArgument>& args, + cmExecutionStatus &) +{ + std::string errorString; + + std::vector<std::string> expandedArguments; + this->Makefile->ExpandArguments(args, expandedArguments); + + cmake::MessageType status; + bool isTrue = + cmIfCommand::IsTrue(expandedArguments,errorString, + this->Makefile, status); + + if (errorString.size()) + { + std::string err = cmIfCommandError(this->Makefile, expandedArguments); + err += errorString; + if (status == cmake::FATAL_ERROR) + { + this->SetError(err.c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + else + { + this->Makefile->IssueMessage(status, err); + } + } + + cmIfFunctionBlocker *f = new cmIfFunctionBlocker(); + // if is isn't true block the commands + f->ScopeDepth = 1; + f->IsBlocking = !isTrue; + if (isTrue) + { + f->HasRun = true; + } + f->Args = args; + this->Makefile->AddFunctionBlocker(f); + + return true; +} + +namespace +{ + //========================================================================= + bool GetBooleanValue(std::string& arg, cmMakefile* mf) + { + // 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 = mf->GetDefinition(arg.c_str()); + return !cmSystemTools::IsOff(def); + } + + //========================================================================= + // Boolean value behavior from CMake 2.6.4 and below. + bool GetBooleanValueOld(std::string const& arg, cmMakefile* mf, bool one) + { + if(one) + { + // Old IsTrue behavior for single argument. + if(arg == "0") + { return false; } + else if(arg == "1") + { return true; } + else + { return !cmSystemTools::IsOff(mf->GetDefinition(arg.c_str())); } + } + else + { + // Old GetVariableOrNumber behavior. + const char* def = mf->GetDefinition(arg.c_str()); + if(!def && atoi(arg.c_str())) + { + def = arg.c_str(); + } + return !cmSystemTools::IsOff(def); + } + } + + //========================================================================= + // returns the resulting boolean value + bool GetBooleanValueWithAutoDereference( + std::string &newArg, + cmMakefile *makefile, + std::string &errorString, + cmPolicies::PolicyStatus Policy12Status, + cmake::MessageType &status, + bool oneArg = false) + { + // Use the policy if it is set. + if (Policy12Status == cmPolicies::NEW) + { + return GetBooleanValue(newArg, makefile); + } + else if (Policy12Status == cmPolicies::OLD) + { + return GetBooleanValueOld(newArg, makefile, oneArg); + } + + // Check policy only if old and new results differ. + bool newResult = GetBooleanValue(newArg, makefile); + bool oldResult = GetBooleanValueOld(newArg, makefile, oneArg); + if(newResult != oldResult) + { + switch(Policy12Status) + { + case cmPolicies::WARN: + { + cmPolicies* policies = makefile->GetPolicies(); + errorString = "An argument named \"" + newArg + + "\" 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 = makefile->GetPolicies(); + errorString = "An argument named \"" + newArg + + "\" appears in a conditional statement. " + + policies->GetRequiredPolicyError(cmPolicies::CMP0012); + status = cmake::FATAL_ERROR; + } + case cmPolicies::NEW: + break; + } + } + return newResult; + } + + //========================================================================= + void IncrementArguments(std::list<std::string> &newArgs, + std::list<std::string>::iterator &argP1, + std::list<std::string>::iterator &argP2) + { + if (argP1 != newArgs.end()) + { + argP1++; + argP2 = argP1; + if (argP1 != newArgs.end()) + { + argP2++; + } + } + } + + //========================================================================= + // 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; + } + + //========================================================================= + // 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; + } + + //========================================================================= + enum Op { OpLess, OpEqual, OpGreater }; + bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str) + { + // Parse out up to 8 components. + unsigned int lhs[8] = {0,0,0,0,0,0,0,0}; + unsigned int rhs[8] = {0,0,0,0,0,0,0,0}; + sscanf(lhs_str, "%u.%u.%u.%u.%u.%u.%u.%u", + &lhs[0], &lhs[1], &lhs[2], &lhs[3], + &lhs[4], &lhs[5], &lhs[6], &lhs[7]); + sscanf(rhs_str, "%u.%u.%u.%u.%u.%u.%u.%u", + &rhs[0], &rhs[1], &rhs[2], &rhs[3], + &rhs[4], &rhs[5], &rhs[6], &rhs[7]); + + // Do component-wise comparison. + for(unsigned int i=0; i < 8; ++i) + { + if(lhs[i] < rhs[i]) + { + // lhs < rhs, so true if operation is LESS + return op == OpLess; + } + else if(lhs[i] > rhs[i]) + { + // lhs > rhs, so true if operation is GREATER + return op == OpGreater; + } + } + // lhs == rhs, so true if operation is EQUAL + return op == OpEqual; + } + + //========================================================================= + // level 0 processes parenthetical expressions + bool HandleLevel0(std::list<std::string> &newArgs, + cmMakefile *makefile, + std::string &errorString, + cmake::MessageType &status) + { + int reducible; + do + { + reducible = 0; + std::list<std::string>::iterator arg = newArgs.begin(); + while (arg != newArgs.end()) + { + if (*arg == "(") + { + // 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) + { + errorString = "mismatched parenthesis in condition"; + status = cmake::FATAL_ERROR; + 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, status); + if(value) + { + *arg = "1"; + } + else + { + *arg = "0"; + } + 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 HandleLevel1(std::list<std::string> &newArgs, + cmMakefile *makefile, + std::string &, cmake::MessageType &) + { + 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 + if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end()) + { + HandlePredicate( + cmSystemTools::FileIsDirectory((argP1)->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a symlink with this name exist + if (*arg == "IS_SYMLINK" && argP1 != newArgs.end()) + { + HandlePredicate( + cmSystemTools::FileIsSymlink((argP1)->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // is the given path an absolute path ? + if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end()) + { + HandlePredicate( + cmSystemTools::FileIsFullPath((argP1)->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a command exist + if (*arg == "COMMAND" && argP1 != newArgs.end()) + { + HandlePredicate( + makefile->CommandExists((argP1)->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a policy exist + if (*arg == "POLICY" && argP1 != newArgs.end()) + { + cmPolicies::PolicyID pid; + HandlePredicate( + makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid), + reducible, arg, newArgs, argP1, argP2); + } + // does a target exist + if (*arg == "TARGET" && argP1 != newArgs.end()) + { + HandlePredicate( + makefile->FindTargetToUse((argP1)->c_str())? true:false, + reducible, arg, newArgs, argP1, argP2); + } + // is a variable defined + if (*arg == "DEFINED" && argP1 != newArgs.end()) + { + size_t argP1len = argP1->size(); + bool bdef = false; + if(argP1len > 4 && argP1->substr(0, 4) == "ENV{" && + argP1->operator[](argP1len-1) == '}') + { + std::string env = argP1->substr(4, argP1len-5); + bdef = cmSystemTools::GetEnv(env.c_str())?true:false; + } + else + { + bdef = makefile->IsDefinitionSet((argP1)->c_str()); + } + HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + while (reducible); + return true; + } + + //========================================================================= + // level two handles most binary operations except for AND OR + bool HandleLevel2(std::list<std::string> &newArgs, + cmMakefile *makefile, + std::string &errorString, + cmake::MessageType &status) + { + int reducible; + const char *def; + const char *def2; + 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); + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + *(argP1) == "MATCHES") + { + def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); + const char* rex = (argP2)->c_str(); + cmStringCommand::ClearMatches(makefile); + 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)) + { + cmStringCommand::StoreMatches(makefile, regEntry); + *arg = "1"; + } + else + { + *arg = "0"; + } + newArgs.erase(argP2); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs,argP1,argP2); + reducible = 1; + } + + if (argP1 != newArgs.end() && *arg == "MATCHES") + { + *arg = "0"; + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs,argP1,argP2); + reducible = 1; + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (*(argP1) == "LESS" || *(argP1) == "GREATER" || + *(argP1) == "EQUAL")) + { + def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); + def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile); + 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); + } + HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (*(argP1) == "STRLESS" || + *(argP1) == "STREQUAL" || + *(argP1) == "STRGREATER")) + { + def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); + def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile); + 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); + } + HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (*(argP1) == "VERSION_LESS" || *(argP1) == "VERSION_GREATER" || + *(argP1) == "VERSION_EQUAL")) + { + def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); + def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile); + Op op = OpEqual; + if(*argP1 == "VERSION_LESS") + { + op = OpLess; + } + else if(*argP1 == "VERSION_GREATER") + { + op = OpGreater; + } + bool result = HandleVersionCompare(op, def, def2); + HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + // is file A newer than file B + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + *(argP1) == "IS_NEWER_THAN") + { + int fileIsNewer=0; + bool success=cmSystemTools::FileTimeCompare(arg->c_str(), + (argP2)->c_str(), + &fileIsNewer); + HandleBinaryOp( + (success==false || fileIsNewer==1 || fileIsNewer==0), + reducible, arg, newArgs, argP1, argP2); + } + + ++arg; + } + } + while (reducible); + return true; + } + + //========================================================================= + // level 3 handles NOT + bool HandleLevel3(std::list<std::string> &newArgs, + cmMakefile *makefile, + std::string &errorString, + cmPolicies::PolicyStatus Policy12Status, + cmake::MessageType &status) + { + 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); + if (argP1 != newArgs.end() && *arg == "NOT") + { + bool rhs = GetBooleanValueWithAutoDereference(*argP1, makefile, + errorString, + Policy12Status, + status); + HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + while (reducible); + return true; + } + + //========================================================================= + // level 4 handles AND OR + bool HandleLevel4(std::list<std::string> &newArgs, + cmMakefile *makefile, + std::string &errorString, + cmPolicies::PolicyStatus Policy12Status, + cmake::MessageType &status) + { + int reducible; + bool lhs; + bool rhs; + 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); + if (argP1 != newArgs.end() && *(argP1) == "AND" && + argP2 != newArgs.end()) + { + lhs = GetBooleanValueWithAutoDereference(*arg, makefile, + errorString, + Policy12Status, + status); + rhs = GetBooleanValueWithAutoDereference(*argP2, makefile, + errorString, + Policy12Status, + status); + HandleBinaryOp((lhs && rhs), + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && *(argP1) == "OR" && + argP2 != newArgs.end()) + { + lhs = GetBooleanValueWithAutoDereference(*arg, makefile, + errorString, + Policy12Status, + status); + rhs = GetBooleanValueWithAutoDereference(*argP2, makefile, + errorString, + Policy12Status, + status); + HandleBinaryOp((lhs || rhs), + reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + 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, + std::string &errorString, cmMakefile *makefile, + cmake::MessageType &status) +{ + errorString = ""; + + // handle empty invocation + if (args.size() < 1) + { + 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 + // parens + if (!HandleLevel0(newArgs, makefile, errorString, status)) + { + return false; + } + //predicates + if (!HandleLevel1(newArgs, makefile, errorString, status)) + { + return false; + } + // binary ops + if (!HandleLevel2(newArgs, makefile, errorString, status)) + { + return false; + } + + // used to store the value of policy CMP0012 for performance + cmPolicies::PolicyStatus Policy12Status = + makefile->GetPolicyStatus(cmPolicies::CMP0012); + + // NOT + if (!HandleLevel3(newArgs, makefile, errorString, + Policy12Status, status)) + { + return false; + } + // AND OR + if (!HandleLevel4(newArgs, makefile, errorString, + Policy12Status, 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 GetBooleanValueWithAutoDereference(*(newArgs.begin()), + makefile, + errorString, + Policy12Status, + status, true); +} + +//========================================================================= +const char* cmIfCommand::GetVariableOrString(const char* str, + const cmMakefile* mf) +{ + const char* def = mf->GetDefinition(str); + if(!def) + { + def = str; + } + return def; +} |