Clarify documentation for if.
[cmake.git] / Source / cmIfCommand.cxx
blob9d0c16308a742d22f0184e6c02a2dbf609ed8e77
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmIfCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2009-06-17 18:18:08 $
7 Version: $Revision: 1.97 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmIfCommand.h"
18 #include "cmStringCommand.h"
20 #include <stdlib.h> // required for atof
21 #include <list>
22 #include <cmsys/RegularExpression.hxx>
24 //=========================================================================
25 bool cmIfFunctionBlocker::
26 IsFunctionBlocked(const cmListFileFunction& lff,
27 cmMakefile &mf,
28 cmExecutionStatus &inStatus)
30 // we start by recording all the functions
31 if (!cmSystemTools::Strucmp(lff.Name.c_str(),"if"))
33 this->ScopeDepth++;
35 if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif"))
37 this->ScopeDepth--;
38 // if this is the endif for this if statement, then start executing
39 if (!this->ScopeDepth)
41 // Remove the function blocker for this scope or bail.
42 cmsys::auto_ptr<cmFunctionBlocker>
43 fb(mf.RemoveFunctionBlocker(this, lff));
44 if(!fb.get()) { return false; }
46 // execute the functions for the true parts of the if statement
47 cmExecutionStatus status;
48 int scopeDepth = 0;
49 for(unsigned int c = 0; c < this->Functions.size(); ++c)
51 // keep track of scope depth
52 if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"if"))
54 scopeDepth++;
56 if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"endif"))
58 scopeDepth--;
60 // watch for our state change
61 if (scopeDepth == 0 &&
62 !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),"else"))
64 this->IsBlocking = this->HasRun;
65 this->HasRun = true;
67 else if (scopeDepth == 0 && !cmSystemTools::Strucmp
68 (this->Functions[c].Name.c_str(),"elseif"))
70 if (this->HasRun)
72 this->IsBlocking = true;
74 else
76 // Place this call on the call stack.
77 cmMakefileCall stack_manager(&mf, this->Functions[c], status);
78 static_cast<void>(stack_manager);
80 std::string errorString;
82 std::vector<std::string> expandedArguments;
83 mf.ExpandArguments(this->Functions[c].Arguments,
84 expandedArguments);
86 cmake::MessageType messType;
87 bool isTrue =
88 cmIfCommand::IsTrue(expandedArguments, errorString,
89 &mf, messType);
91 if (errorString.size())
93 std::string err = "given arguments\n ";
94 unsigned int i;
95 for(i =0; i < this->Functions[c].Arguments.size(); ++i)
97 err += (this->Functions[c].Arguments[i].Quoted?"\"":"");
98 err += this->Functions[c].Arguments[i].Value;
99 err += (this->Functions[c].Arguments[i].Quoted?"\"":"");
100 err += " ";
102 err += "\n";
103 err += errorString;
104 mf.IssueMessage(messType, err);
105 if (messType == cmake::FATAL_ERROR)
107 cmSystemTools::SetFatalErrorOccured();
108 return true;
112 if (isTrue)
114 this->IsBlocking = false;
115 this->HasRun = true;
120 // should we execute?
121 else if (!this->IsBlocking)
123 status.Clear();
124 mf.ExecuteCommand(this->Functions[c],status);
125 if (status.GetReturnInvoked())
127 inStatus.SetReturnInvoked(true);
128 return true;
130 if (status.GetBreakInvoked())
132 inStatus.SetBreakInvoked(true);
133 return true;
137 return true;
141 // record the command
142 this->Functions.push_back(lff);
144 // always return true
145 return true;
148 //=========================================================================
149 bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
150 cmMakefile&)
152 if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif"))
154 // if the endif has arguments, then make sure
155 // they match the arguments of the matching if
156 if (lff.Arguments.size() == 0 ||
157 lff.Arguments == this->Args)
159 return true;
163 return false;
166 //=========================================================================
167 bool cmIfCommand
168 ::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
169 cmExecutionStatus &)
171 std::string errorString;
173 std::vector<std::string> expandedArguments;
174 this->Makefile->ExpandArguments(args, expandedArguments);
176 cmake::MessageType status;
177 bool isTrue =
178 cmIfCommand::IsTrue(expandedArguments,errorString,
179 this->Makefile, status);
181 if (errorString.size())
183 std::string err = "given arguments\n ";
184 unsigned int i;
185 for(i =0; i < args.size(); ++i)
187 err += (args[i].Quoted?"\"":"");
188 err += args[i].Value;
189 err += (args[i].Quoted?"\"":"");
190 err += " ";
192 err += "\n";
193 err += errorString;
194 if (status == cmake::FATAL_ERROR)
196 this->SetError(err.c_str());
197 cmSystemTools::SetFatalErrorOccured();
198 return false;
200 else
202 this->Makefile->IssueMessage(status, err);
206 cmIfFunctionBlocker *f = new cmIfFunctionBlocker();
207 // if is isn't true block the commands
208 f->ScopeDepth = 1;
209 f->IsBlocking = !isTrue;
210 if (isTrue)
212 f->HasRun = true;
214 f->Args = args;
215 this->Makefile->AddFunctionBlocker(f);
217 return true;
220 namespace
222 //=========================================================================
223 // returns true if succesfull, the resulting bool parsed is stored in result
224 bool GetBooleanValue(std::string &newArg,
225 cmMakefile *makefile,
226 bool &result,
227 std::string &errorString,
228 cmPolicies::PolicyStatus Policy12Status,
229 cmake::MessageType &status)
231 if (Policy12Status != cmPolicies::OLD &&
232 Policy12Status != cmPolicies::WARN)
234 // please note IsOn(var) does not always equal !IsOff(var)
235 // that is why each is called
236 if (cmSystemTools::IsOn(newArg.c_str()))
238 result = true;
239 return true;
241 if (cmSystemTools::IsOff(newArg.c_str()))
243 result = false;
244 return true;
246 return false;
249 // Old policy is more complex...
250 // 0 and 1 are very common, test for them first quickly
251 if (newArg == "0")
253 result = false;
254 return true;
256 if (newArg == "1")
258 result = true;
259 return true;
262 // old behavior is to dereference the var
263 if (Policy12Status == cmPolicies::OLD)
265 return false;
268 // now test for values that may be the name of a variable
269 // warn if used
270 if (cmSystemTools::IsOn(newArg.c_str()))
272 // only warn if the value would change
273 const char *def = makefile->GetDefinition(newArg.c_str());
274 if (cmSystemTools::IsOff(def))
276 cmPolicies* policies = makefile->GetPolicies();
277 errorString = "You have used a variable or argument named \""
278 + newArg
279 + "\" in a conditional statement. Please be aware of issues "
280 + "related to policy CMP0012. "
281 + policies->GetPolicyWarning(cmPolicies::CMP0012);
282 status = cmake::AUTHOR_WARNING;
284 return false;
286 if (cmSystemTools::IsOff(newArg.c_str()))
288 // only warn if the value would change
289 const char *def = makefile->GetDefinition(newArg.c_str());
290 if (!cmSystemTools::IsOff(def))
292 cmPolicies* policies = makefile->GetPolicies();
293 errorString = "You have used a variable or argument named \""
294 + newArg
295 + "\" in a conditional statement. Please be aware of issues "
296 + "related to policy CMP0012. "
297 + policies->GetPolicyWarning(cmPolicies::CMP0012);
298 status = cmake::AUTHOR_WARNING;
300 return false;
302 return false;
305 //=========================================================================
306 // returns the resulting boolean value
307 bool GetBooleanValueWithAutoDereference(
308 std::string &newArg,
309 cmMakefile *makefile,
310 std::string &errorString,
311 cmPolicies::PolicyStatus Policy12Status,
312 cmake::MessageType &status)
314 bool result = false;
315 if (GetBooleanValue(newArg, makefile, result,
316 errorString, Policy12Status, status))
318 return result;
320 const char *def = makefile->GetDefinition(newArg.c_str());
321 return !cmSystemTools::IsOff(def);
324 //=========================================================================
325 void IncrementArguments(std::list<std::string> &newArgs,
326 std::list<std::string>::iterator &argP1,
327 std::list<std::string>::iterator &argP2)
329 if (argP1 != newArgs.end())
331 argP1++;
332 argP2 = argP1;
333 if (argP1 != newArgs.end())
335 argP2++;
340 //=========================================================================
341 // helper function to reduce code duplication
342 void HandlePredicate(bool value, int &reducible,
343 std::list<std::string>::iterator &arg,
344 std::list<std::string> &newArgs,
345 std::list<std::string>::iterator &argP1,
346 std::list<std::string>::iterator &argP2)
348 if(value)
350 *arg = "1";
352 else
354 *arg = "0";
356 newArgs.erase(argP1);
357 argP1 = arg;
358 IncrementArguments(newArgs,argP1,argP2);
359 reducible = 1;
362 //=========================================================================
363 // helper function to reduce code duplication
364 void HandleBinaryOp(bool value, int &reducible,
365 std::list<std::string>::iterator &arg,
366 std::list<std::string> &newArgs,
367 std::list<std::string>::iterator &argP1,
368 std::list<std::string>::iterator &argP2)
370 if(value)
372 *arg = "1";
374 else
376 *arg = "0";
378 newArgs.erase(argP2);
379 newArgs.erase(argP1);
380 argP1 = arg;
381 IncrementArguments(newArgs,argP1,argP2);
382 reducible = 1;
385 //=========================================================================
386 enum Op { OpLess, OpEqual, OpGreater };
387 bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str)
389 // Parse out up to 4 components.
390 unsigned int lhs[4] = {0,0,0,0};
391 unsigned int rhs[4] = {0,0,0,0};
392 sscanf(lhs_str, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]);
393 sscanf(rhs_str, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]);
395 // Do component-wise comparison.
396 for(unsigned int i=0; i < 4; ++i)
398 if(lhs[i] < rhs[i])
400 // lhs < rhs, so true if operation is LESS
401 return op == OpLess;
403 else if(lhs[i] > rhs[i])
405 // lhs > rhs, so true if operation is GREATER
406 return op == OpGreater;
409 // lhs == rhs, so true if operation is EQUAL
410 return op == OpEqual;
413 //=========================================================================
414 // level 0 processes parenthetical expressions
415 bool HandleLevel0(std::list<std::string> &newArgs,
416 cmMakefile *makefile,
417 std::string &errorString,
418 cmake::MessageType &status)
420 int reducible;
423 reducible = 0;
424 std::list<std::string>::iterator arg = newArgs.begin();
425 while (arg != newArgs.end())
427 if (*arg == "(")
429 // search for the closing paren for this opening one
430 std::list<std::string>::iterator argClose;
431 argClose = arg;
432 argClose++;
433 unsigned int depth = 1;
434 while (argClose != newArgs.end() && depth)
436 if (*argClose == "(")
438 depth++;
440 if (*argClose == ")")
442 depth--;
444 argClose++;
446 if (depth)
448 errorString = "mismatched parenthesis in condition";
449 status = cmake::FATAL_ERROR;
450 return false;
452 // store the reduced args in this vector
453 std::vector<std::string> newArgs2;
455 // copy to the list structure
456 std::list<std::string>::iterator argP1 = arg;
457 argP1++;
458 for(; argP1 != argClose; argP1++)
460 newArgs2.push_back(*argP1);
462 newArgs2.pop_back();
463 // now recursively invoke IsTrue to handle the values inside the
464 // parenthetical expression
465 bool value =
466 cmIfCommand::IsTrue(newArgs2, errorString, makefile, status);
467 if(value)
469 *arg = "1";
471 else
473 *arg = "0";
475 argP1 = arg;
476 argP1++;
477 // remove the now evaluated parenthetical expression
478 newArgs.erase(argP1,argClose);
480 ++arg;
483 while (reducible);
484 return true;
487 //=========================================================================
488 // level one handles most predicates except for NOT
489 bool HandleLevel1(std::list<std::string> &newArgs,
490 cmMakefile *makefile,
491 std::string &, cmake::MessageType &)
493 int reducible;
496 reducible = 0;
497 std::list<std::string>::iterator arg = newArgs.begin();
498 std::list<std::string>::iterator argP1;
499 std::list<std::string>::iterator argP2;
500 while (arg != newArgs.end())
502 argP1 = arg;
503 IncrementArguments(newArgs,argP1,argP2);
504 // does a file exist
505 if (*arg == "EXISTS" && argP1 != newArgs.end())
507 HandlePredicate(
508 cmSystemTools::FileExists((argP1)->c_str()),
509 reducible, arg, newArgs, argP1, argP2);
511 // does a directory with this name exist
512 if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end())
514 HandlePredicate(
515 cmSystemTools::FileIsDirectory((argP1)->c_str()),
516 reducible, arg, newArgs, argP1, argP2);
518 // is the given path an absolute path ?
519 if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end())
521 HandlePredicate(
522 cmSystemTools::FileIsFullPath((argP1)->c_str()),
523 reducible, arg, newArgs, argP1, argP2);
525 // does a command exist
526 if (*arg == "COMMAND" && argP1 != newArgs.end())
528 HandlePredicate(
529 makefile->CommandExists((argP1)->c_str()),
530 reducible, arg, newArgs, argP1, argP2);
532 // does a policy exist
533 if (*arg == "POLICY" && argP1 != newArgs.end())
535 cmPolicies::PolicyID pid;
536 HandlePredicate(
537 makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid),
538 reducible, arg, newArgs, argP1, argP2);
540 // does a target exist
541 if (*arg == "TARGET" && argP1 != newArgs.end())
543 HandlePredicate(
544 makefile->FindTargetToUse((argP1)->c_str())? true:false,
545 reducible, arg, newArgs, argP1, argP2);
547 // is a variable defined
548 if (*arg == "DEFINED" && argP1 != newArgs.end())
550 size_t argP1len = argP1->size();
551 bool bdef = false;
552 if(argP1len > 4 && argP1->substr(0, 4) == "ENV{" &&
553 argP1->operator[](argP1len-1) == '}')
555 std::string env = argP1->substr(4, argP1len-5);
556 bdef = cmSystemTools::GetEnv(env.c_str())?true:false;
558 else
560 bdef = makefile->IsDefinitionSet((argP1)->c_str());
562 HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
564 ++arg;
567 while (reducible);
568 return true;
571 //=========================================================================
572 // level two handles most binary operations except for AND OR
573 bool HandleLevel2(std::list<std::string> &newArgs,
574 cmMakefile *makefile,
575 std::string &errorString,
576 cmake::MessageType &status)
578 int reducible;
579 const char *def;
580 const char *def2;
583 reducible = 0;
584 std::list<std::string>::iterator arg = newArgs.begin();
585 std::list<std::string>::iterator argP1;
586 std::list<std::string>::iterator argP2;
587 while (arg != newArgs.end())
589 argP1 = arg;
590 IncrementArguments(newArgs,argP1,argP2);
591 if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
592 *(argP1) == "MATCHES")
594 def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
595 const char* rex = (argP2)->c_str();
596 cmStringCommand::ClearMatches(makefile);
597 cmsys::RegularExpression regEntry;
598 if ( !regEntry.compile(rex) )
600 cmOStringStream error;
601 error << "Regular expression \"" << rex << "\" cannot compile";
602 errorString = error.str();
603 status = cmake::FATAL_ERROR;
604 return false;
606 if (regEntry.find(def))
608 cmStringCommand::StoreMatches(makefile, regEntry);
609 *arg = "1";
611 else
613 *arg = "0";
615 newArgs.erase(argP2);
616 newArgs.erase(argP1);
617 argP1 = arg;
618 IncrementArguments(newArgs,argP1,argP2);
619 reducible = 1;
622 if (argP1 != newArgs.end() && *arg == "MATCHES")
624 *arg = "0";
625 newArgs.erase(argP1);
626 argP1 = arg;
627 IncrementArguments(newArgs,argP1,argP2);
628 reducible = 1;
631 if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
632 (*(argP1) == "LESS" || *(argP1) == "GREATER" ||
633 *(argP1) == "EQUAL"))
635 def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
636 def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
637 double lhs;
638 double rhs;
639 bool result;
640 if(sscanf(def, "%lg", &lhs) != 1 ||
641 sscanf(def2, "%lg", &rhs) != 1)
643 result = false;
645 else if (*(argP1) == "LESS")
647 result = (lhs < rhs);
649 else if (*(argP1) == "GREATER")
651 result = (lhs > rhs);
653 else
655 result = (lhs == rhs);
657 HandleBinaryOp(result,
658 reducible, arg, newArgs, argP1, argP2);
661 if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
662 (*(argP1) == "STRLESS" ||
663 *(argP1) == "STREQUAL" ||
664 *(argP1) == "STRGREATER"))
666 def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
667 def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
668 int val = strcmp(def,def2);
669 bool result;
670 if (*(argP1) == "STRLESS")
672 result = (val < 0);
674 else if (*(argP1) == "STRGREATER")
676 result = (val > 0);
678 else // strequal
680 result = (val == 0);
682 HandleBinaryOp(result,
683 reducible, arg, newArgs, argP1, argP2);
686 if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
687 (*(argP1) == "VERSION_LESS" || *(argP1) == "VERSION_GREATER" ||
688 *(argP1) == "VERSION_EQUAL"))
690 def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
691 def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
692 Op op = OpEqual;
693 if(*argP1 == "VERSION_LESS")
695 op = OpLess;
697 else if(*argP1 == "VERSION_GREATER")
699 op = OpGreater;
701 bool result = HandleVersionCompare(op, def, def2);
702 HandleBinaryOp(result,
703 reducible, arg, newArgs, argP1, argP2);
706 // is file A newer than file B
707 if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
708 *(argP1) == "IS_NEWER_THAN")
710 int fileIsNewer=0;
711 bool success=cmSystemTools::FileTimeCompare(arg->c_str(),
712 (argP2)->c_str(),
713 &fileIsNewer);
714 HandleBinaryOp(
715 (success==false || fileIsNewer==1 || fileIsNewer==0),
716 reducible, arg, newArgs, argP1, argP2);
719 ++arg;
722 while (reducible);
723 return true;
726 //=========================================================================
727 // level 3 handles NOT
728 bool HandleLevel3(std::list<std::string> &newArgs,
729 cmMakefile *makefile,
730 std::string &errorString,
731 cmPolicies::PolicyStatus Policy12Status,
732 cmake::MessageType &status)
734 int reducible;
737 reducible = 0;
738 std::list<std::string>::iterator arg = newArgs.begin();
739 std::list<std::string>::iterator argP1;
740 std::list<std::string>::iterator argP2;
741 while (arg != newArgs.end())
743 argP1 = arg;
744 IncrementArguments(newArgs,argP1,argP2);
745 if (argP1 != newArgs.end() && *arg == "NOT")
747 bool rhs = GetBooleanValueWithAutoDereference(*argP1, makefile,
748 errorString,
749 Policy12Status,
750 status);
751 HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
753 ++arg;
756 while (reducible);
757 return true;
760 //=========================================================================
761 // level 4 handles AND OR
762 bool HandleLevel4(std::list<std::string> &newArgs,
763 cmMakefile *makefile,
764 std::string &errorString,
765 cmPolicies::PolicyStatus Policy12Status,
766 cmake::MessageType &status)
768 int reducible;
769 bool lhs;
770 bool rhs;
773 reducible = 0;
774 std::list<std::string>::iterator arg = newArgs.begin();
775 std::list<std::string>::iterator argP1;
776 std::list<std::string>::iterator argP2;
777 while (arg != newArgs.end())
779 argP1 = arg;
780 IncrementArguments(newArgs,argP1,argP2);
781 if (argP1 != newArgs.end() && *(argP1) == "AND" &&
782 argP2 != newArgs.end())
784 lhs = GetBooleanValueWithAutoDereference(*arg, makefile,
785 errorString,
786 Policy12Status,
787 status);
788 rhs = GetBooleanValueWithAutoDereference(*argP2, makefile,
789 errorString,
790 Policy12Status,
791 status);
792 HandleBinaryOp((lhs && rhs),
793 reducible, arg, newArgs, argP1, argP2);
796 if (argP1 != newArgs.end() && *(argP1) == "OR" &&
797 argP2 != newArgs.end())
799 lhs = GetBooleanValueWithAutoDereference(*arg, makefile,
800 errorString,
801 Policy12Status,
802 status);
803 rhs = GetBooleanValueWithAutoDereference(*argP2, makefile,
804 errorString,
805 Policy12Status,
806 status);
807 HandleBinaryOp((lhs || rhs),
808 reducible, arg, newArgs, argP1, argP2);
810 ++arg;
813 while (reducible);
814 return true;
819 //=========================================================================
820 // order of operations,
821 // 1. ( ) -- parenthetical groups
822 // 2. IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates
823 // 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops
824 // 4. NOT
825 // 5. AND OR
827 // There is an issue on whether the arguments should be values of references,
828 // for example IF (FOO AND BAR) should that compare the strings FOO and BAR
829 // or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY
830 // EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can
831 // take numeric values or variable names. STRLESS and STRGREATER take
832 // variable names but if the variable name is not found it will use the name
833 // directly. AND OR take variables or the values 0 or 1.
836 bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
837 std::string &errorString, cmMakefile *makefile,
838 cmake::MessageType &status)
840 errorString = "";
842 // handle empty invocation
843 if (args.size() < 1)
845 return false;
848 // store the reduced args in this vector
849 std::list<std::string> newArgs;
851 // copy to the list structure
852 for(unsigned int i = 0; i < args.size(); ++i)
854 newArgs.push_back(args[i]);
857 // now loop through the arguments and see if we can reduce any of them
858 // we do this multiple times. Once for each level of precedence
859 // parens
860 if (!HandleLevel0(newArgs, makefile, errorString, status))
862 return false;
864 //predicates
865 if (!HandleLevel1(newArgs, makefile, errorString, status))
867 return false;
869 // binary ops
870 if (!HandleLevel2(newArgs, makefile, errorString, status))
872 return false;
875 // used to store the value of policy CMP0012 for performance
876 cmPolicies::PolicyStatus Policy12Status =
877 makefile->GetPolicyStatus(cmPolicies::CMP0012);
879 // NOT
880 if (!HandleLevel3(newArgs, makefile, errorString,
881 Policy12Status, status))
883 return false;
885 // AND OR
886 if (!HandleLevel4(newArgs, makefile, errorString,
887 Policy12Status, status))
889 return false;
892 // now at the end there should only be one argument left
893 if (newArgs.size() != 1)
895 errorString = "Unknown arguments specified";
896 return false;
899 return GetBooleanValueWithAutoDereference(*(newArgs.begin()),
900 makefile,
901 errorString,
902 Policy12Status,
903 status);
906 //=========================================================================
907 const char* cmIfCommand::GetVariableOrString(const char* str,
908 const cmMakefile* mf)
910 const char* def = mf->GetDefinition(str);
911 if(!def)
913 def = str;
915 return def;