Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmForEachCommand.cxx
blob85506f5de4aad26a5b209a6b6d6b9377a291db27
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmForEachCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-17 19:10:15 $
7 Version: $Revision: 1.31 $
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 #include <cmsys/auto_ptr.hxx>
21 bool cmForEachFunctionBlocker::
22 IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
23 cmExecutionStatus &inStatus)
25 if (!cmSystemTools::Strucmp(lff.Name.c_str(),"foreach"))
27 // record the number of nested foreach commands
28 this->Depth++;
30 else if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
32 // if this is the endofreach for this statement
33 if (!this->Depth)
35 // Remove the function blocker for this scope or bail.
36 cmsys::auto_ptr<cmFunctionBlocker>
37 fb(mf.RemoveFunctionBlocker(this, lff));
38 if(!fb.get()) { return false; }
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 std::vector<std::string>::const_iterator j = this->Args.begin();
48 ++j;
50 std::string tmps;
51 cmListFileArgument arg;
52 for( ; j != this->Args.end(); ++j)
54 // set the variable to the loop value
55 mf.AddDefinition(this->Args[0].c_str(),j->c_str());
56 // Invoke all the functions that were collected in the block.
57 cmExecutionStatus status;
58 for(unsigned int c = 0; c < this->Functions.size(); ++c)
60 status.Clear();
61 mf.ExecuteCommand(this->Functions[c],status);
62 if (status.GetReturnInvoked())
64 inStatus.SetReturnInvoked(true);
65 // restore the variable to its prior value
66 mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
67 return true;
69 if (status.GetBreakInvoked())
71 // restore the variable to its prior value
72 mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
73 return true;
77 // restore the variable to its prior value
78 mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
79 return true;
81 else
83 // close out a nested foreach
84 this->Depth--;
88 // record the command
89 this->Functions.push_back(lff);
91 // always return true
92 return true;
95 bool cmForEachFunctionBlocker::
96 ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
98 if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
100 std::vector<std::string> expandedArguments;
101 mf.ExpandArguments(lff.Arguments, expandedArguments);
102 // if the endforeach has arguments then make sure
103 // they match the begin foreach arguments
104 if ((expandedArguments.empty() ||
105 (expandedArguments[0] == this->Args[0])))
107 return true;
110 return false;
113 bool cmForEachCommand
114 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
116 if(args.size() < 1)
118 this->SetError("called with incorrect number of arguments");
119 return false;
121 if(args.size() > 1 && args[1] == "IN")
123 return this->HandleInMode(args);
126 // create a function blocker
127 cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
128 if ( args.size() > 1 )
130 if ( args[1] == "RANGE" )
132 int start = 0;
133 int stop = 0;
134 int step = 0;
135 if ( args.size() == 3 )
137 stop = atoi(args[2].c_str());
139 if ( args.size() == 4 )
141 start = atoi(args[2].c_str());
142 stop = atoi(args[3].c_str());
144 if ( args.size() == 5 )
146 start = atoi(args[2].c_str());
147 stop = atoi(args[3].c_str());
148 step = atoi(args[4].c_str());
150 if ( step == 0 )
152 if ( start > stop )
154 step = -1;
156 else
158 step = 1;
161 if (
162 (start > stop && step > 0) ||
163 (start < stop && step < 0) ||
164 step == 0
167 cmOStringStream str;
168 str << "called with incorrect range specification: start ";
169 str << start << ", stop " << stop << ", step " << step;
170 this->SetError(str.str().c_str());
171 return false;
173 std::vector<std::string> range;
174 char buffer[100];
175 range.push_back(args[0]);
176 int cc;
177 for ( cc = start; ; cc += step )
179 if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
181 break;
183 sprintf(buffer, "%d", cc);
184 range.push_back(buffer);
185 if ( cc == stop )
187 break;
190 f->Args = range;
192 else
194 f->Args = args;
197 else
199 f->Args = args;
201 this->Makefile->AddFunctionBlocker(f);
203 return true;
206 //----------------------------------------------------------------------------
207 bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
209 cmsys::auto_ptr<cmForEachFunctionBlocker> f(new cmForEachFunctionBlocker());
210 f->Args.push_back(args[0]);
212 enum Doing { DoingNone, DoingLists, DoingItems };
213 Doing doing = DoingNone;
214 for(unsigned int i=2; i < args.size(); ++i)
216 if(doing == DoingItems)
218 f->Args.push_back(args[i]);
220 else if(args[i] == "LISTS")
222 doing = DoingLists;
224 else if(args[i] == "ITEMS")
226 doing = DoingItems;
228 else if(doing == DoingLists)
230 const char* value = this->Makefile->GetDefinition(args[i].c_str());
231 if(value && *value)
233 cmSystemTools::ExpandListArgument(value, f->Args, true);
236 else
238 cmOStringStream e;
239 e << "Unknown argument:\n" << " " << args[i] << "\n";
240 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
241 return true;
245 this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
246 return true;