Skip implicit link info for multiple OS X archs
[cmake.git] / Source / cmForEachCommand.cxx
blob1b3fdd560ac7563006f873d733e4ea542a5bab5b
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmForEachCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2009-05-13 15:08:28 $
7 Version: $Revision: 1.32 $
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;
75 if(cmSystemTools::GetFatalErrorOccured() )
77 return true;
81 // restore the variable to its prior value
82 mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
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 bool cmForEachCommand
118 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
120 if(args.size() < 1)
122 this->SetError("called with incorrect number of arguments");
123 return false;
125 if(args.size() > 1 && args[1] == "IN")
127 return this->HandleInMode(args);
130 // create a function blocker
131 cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
132 if ( args.size() > 1 )
134 if ( args[1] == "RANGE" )
136 int start = 0;
137 int stop = 0;
138 int step = 0;
139 if ( args.size() == 3 )
141 stop = atoi(args[2].c_str());
143 if ( args.size() == 4 )
145 start = atoi(args[2].c_str());
146 stop = atoi(args[3].c_str());
148 if ( args.size() == 5 )
150 start = atoi(args[2].c_str());
151 stop = atoi(args[3].c_str());
152 step = atoi(args[4].c_str());
154 if ( step == 0 )
156 if ( start > stop )
158 step = -1;
160 else
162 step = 1;
165 if (
166 (start > stop && step > 0) ||
167 (start < stop && step < 0) ||
168 step == 0
171 cmOStringStream str;
172 str << "called with incorrect range specification: start ";
173 str << start << ", stop " << stop << ", step " << step;
174 this->SetError(str.str().c_str());
175 return false;
177 std::vector<std::string> range;
178 char buffer[100];
179 range.push_back(args[0]);
180 int cc;
181 for ( cc = start; ; cc += step )
183 if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
185 break;
187 sprintf(buffer, "%d", cc);
188 range.push_back(buffer);
189 if ( cc == stop )
191 break;
194 f->Args = range;
196 else
198 f->Args = args;
201 else
203 f->Args = args;
205 this->Makefile->AddFunctionBlocker(f);
207 return true;
210 //----------------------------------------------------------------------------
211 bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
213 cmsys::auto_ptr<cmForEachFunctionBlocker> f(new cmForEachFunctionBlocker());
214 f->Args.push_back(args[0]);
216 enum Doing { DoingNone, DoingLists, DoingItems };
217 Doing doing = DoingNone;
218 for(unsigned int i=2; i < args.size(); ++i)
220 if(doing == DoingItems)
222 f->Args.push_back(args[i]);
224 else if(args[i] == "LISTS")
226 doing = DoingLists;
228 else if(args[i] == "ITEMS")
230 doing = DoingItems;
232 else if(doing == DoingLists)
234 const char* value = this->Makefile->GetDefinition(args[i].c_str());
235 if(value && *value)
237 cmSystemTools::ExpandListArgument(value, f->Args, true);
240 else
242 cmOStringStream e;
243 e << "Unknown argument:\n" << " " << args[i] << "\n";
244 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
245 return true;
249 this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
250 return true;