BUG: fix some bad changes in progress calc
[cmake.git] / Source / cmForEachCommand.cxx
blobe2786928c18122d29bb2d3c6f1fffcb36bf37d89
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmForEachCommand.cxx,v $
5 Language: C++
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
24 // commands.
25 if (this->Executing)
27 return false;
30 if (!cmSystemTools::Strucmp(lff.Name.c_str(),"foreach"))
32 // record the number of nested foreach commands
33 this->Depth++;
35 else if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
37 // if this is the endofreach for this statement
38 if (!this->Depth)
40 // at end of for each execute recorded commands
41 // store the old value
42 std::string oldDef;
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();
49 ++j;
51 std::string tmps;
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)
61 status.Clear();
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);
69 return true;
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);
76 return true;
80 // restore the variable to its prior value
81 mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
82 mf.RemoveFunctionBlocker(lff);
83 return true;
85 else
87 // close out a nested foreach
88 this->Depth--;
92 // record the command
93 this->Functions.push_back(lff);
95 // always return true
96 return true;
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])))
111 return true;
114 return false;
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 &)
129 if(args.size() < 1)
131 this->SetError("called with incorrect number of arguments");
132 return false;
135 // create a function blocker
136 cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
137 if ( args.size() > 1 )
139 if ( args[1] == "RANGE" )
141 int start = 0;
142 int stop = 0;
143 int step = 0;
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());
159 if ( step == 0 )
161 if ( start > stop )
163 step = -1;
165 else
167 step = 1;
170 if (
171 (start > stop && step > 0) ||
172 (start < stop && step < 0) ||
173 step == 0
176 cmOStringStream str;
177 str << "called with incorrect range specification: start ";
178 str << start << ", stop " << stop << ", step " << step;
179 this->SetError(str.str().c_str());
180 return false;
182 std::vector<std::string> range;
183 char buffer[100];
184 range.push_back(args[0]);
185 int cc;
186 for ( cc = start; ; cc += step )
188 if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
190 break;
192 sprintf(buffer, "%d", cc);
193 range.push_back(buffer);
194 if ( cc == stop )
196 break;
199 f->Args = range;
201 else
203 f->Args = args;
206 else
208 f->Args = args;
210 this->Makefile->AddFunctionBlocker(f);
212 return true;