1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmForEachCommand.cxx,v $
6 Date: $Date: 2008-02-29 17:18:11 $
7 Version: $Revision: 1.27 $
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 "cmForEachCommand.h"
19 bool cmForEachFunctionBlocker::
20 IsFunctionBlocked(const cmListFileFunction
& lff
, cmMakefile
&mf
,
21 cmExecutionStatus
&inStatus
)
23 // Prevent recusion and don't let this blocker block its own
30 if (!cmSystemTools::Strucmp(lff
.Name
.c_str(),"foreach"))
32 // record the number of nested foreach commands
35 else if (!cmSystemTools::Strucmp(lff
.Name
.c_str(),"endforeach"))
37 // if this is the endofreach for this statement
40 // at end of for each execute recorded commands
41 // store the old value
43 if (mf
.GetDefinition(this->Args
[0].c_str()))
45 oldDef
= mf
.GetDefinition(this->Args
[0].c_str());
47 this->Executing
= true;
48 std::vector
<std::string
>::const_iterator j
= this->Args
.begin();
52 cmListFileArgument arg
;
53 for( ; j
!= this->Args
.end(); ++j
)
55 // set the variable to the loop value
56 mf
.AddDefinition(this->Args
[0].c_str(),j
->c_str());
57 // Invoke all the functions that were collected in the block.
58 cmExecutionStatus status
;
59 for(unsigned int c
= 0; c
< this->Functions
.size(); ++c
)
62 mf
.ExecuteCommand(this->Functions
[c
],status
);
63 if (status
.GetReturnInvoked())
65 inStatus
.SetReturnInvoked(true);
66 // restore the variable to its prior value
67 mf
.AddDefinition(this->Args
[0].c_str(),oldDef
.c_str());
68 mf
.RemoveFunctionBlocker(lff
);
71 if (status
.GetBreakInvoked())
73 // restore the variable to its prior value
74 mf
.AddDefinition(this->Args
[0].c_str(),oldDef
.c_str());
75 mf
.RemoveFunctionBlocker(lff
);
80 // restore the variable to its prior value
81 mf
.AddDefinition(this->Args
[0].c_str(),oldDef
.c_str());
82 mf
.RemoveFunctionBlocker(lff
);
87 // close out a nested foreach
93 this->Functions
.push_back(lff
);
99 bool cmForEachFunctionBlocker::
100 ShouldRemove(const cmListFileFunction
& lff
, cmMakefile
& mf
)
102 if(!cmSystemTools::Strucmp(lff
.Name
.c_str(),"endforeach"))
104 std::vector
<std::string
> expandedArguments
;
105 mf
.ExpandArguments(lff
.Arguments
, expandedArguments
);
106 // if the endforeach has arguments then make sure
107 // they match the begin foreach arguments
108 if ((expandedArguments
.empty() ||
109 (expandedArguments
[0] == this->Args
[0])))
117 void cmForEachFunctionBlocker::
118 ScopeEnded(cmMakefile
&mf
)
120 cmSystemTools::Error("The end of a CMakeLists file was reached with a "
121 "FOREACH statement that was not closed properly. "
122 "Within the directory: ",
123 mf
.GetCurrentDirectory());
126 bool cmForEachCommand
127 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
131 this->SetError("called with incorrect number of arguments");
135 // create a function blocker
136 cmForEachFunctionBlocker
*f
= new cmForEachFunctionBlocker();
137 if ( args
.size() > 1 )
139 if ( args
[1] == "RANGE" )
144 if ( args
.size() == 3 )
146 stop
= atoi(args
[2].c_str());
148 if ( args
.size() == 4 )
150 start
= atoi(args
[2].c_str());
151 stop
= atoi(args
[3].c_str());
153 if ( args
.size() == 5 )
155 start
= atoi(args
[2].c_str());
156 stop
= atoi(args
[3].c_str());
157 step
= atoi(args
[4].c_str());
171 (start
> stop
&& step
> 0) ||
172 (start
< stop
&& step
< 0) ||
177 str
<< "called with incorrect range specification: start ";
178 str
<< start
<< ", stop " << stop
<< ", step " << step
;
179 this->SetError(str
.str().c_str());
182 std::vector
<std::string
> range
;
184 range
.push_back(args
[0]);
186 for ( cc
= start
; ; cc
+= step
)
188 if ( (step
> 0 && cc
> stop
) || (step
< 0 && cc
< stop
) )
192 sprintf(buffer
, "%d", cc
);
193 range
.push_back(buffer
);
210 this->Makefile
->AddFunctionBlocker(f
);