You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
5.0 KiB

24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
22 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmForEachCommand.h"
  14. bool cmForEachFunctionBlocker::
  15. IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
  16. {
  17. // Prevent recusion and don't let this blobker block its own
  18. // commands.
  19. if (this->Executing)
  20. {
  21. return false;
  22. }
  23. if (!cmSystemTools::Strucmp(lff.Name.c_str(),"foreach"))
  24. {
  25. // record the number of nested foreach commands
  26. this->Depth++;
  27. }
  28. else if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
  29. {
  30. // if this is the endofreach for this statement
  31. if (!this->Depth)
  32. {
  33. // at end of for each execute recorded commands
  34. // store the old value
  35. std::string oldDef;
  36. if (mf.GetDefinition(this->Args[0].c_str()))
  37. {
  38. oldDef = mf.GetDefinition(this->Args[0].c_str());
  39. }
  40. this->Executing = true;
  41. std::vector<std::string>::const_iterator j = this->Args.begin();
  42. ++j;
  43. std::string tmps;
  44. cmListFileArgument arg;
  45. for( ; j != this->Args.end(); ++j)
  46. {
  47. // set the variable to the loop value
  48. mf.AddDefinition(this->Args[0].c_str(),j->c_str());
  49. // Invoke all the functions that were collected in the block.
  50. for(unsigned int c = 0; c < this->Functions.size(); ++c)
  51. {
  52. mf.ExecuteCommand(this->Functions[c]);
  53. }
  54. }
  55. // restore the variable to its prior value
  56. mf.AddDefinition(this->Args[0].c_str(),oldDef.c_str());
  57. mf.RemoveFunctionBlocker(lff);
  58. return true;
  59. }
  60. else
  61. {
  62. // close out a nested foreach
  63. this->Depth--;
  64. }
  65. }
  66. // record the command
  67. this->Functions.push_back(lff);
  68. // always return true
  69. return true;
  70. }
  71. bool cmForEachFunctionBlocker::
  72. ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
  73. {
  74. if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endforeach"))
  75. {
  76. std::vector<std::string> expandedArguments;
  77. mf.ExpandArguments(lff.Arguments, expandedArguments);
  78. if ((!expandedArguments.empty() &&
  79. (expandedArguments[0] == this->Args[0]))
  80. || cmSystemTools::IsOn
  81. (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")))
  82. {
  83. return true;
  84. }
  85. }
  86. return false;
  87. }
  88. void cmForEachFunctionBlocker::
  89. ScopeEnded(cmMakefile &mf)
  90. {
  91. cmSystemTools::Error("The end of a CMakeLists file was reached with a "
  92. "FOREACH statement that was not closed properly. "
  93. "Within the directory: ",
  94. mf.GetCurrentDirectory());
  95. }
  96. bool cmForEachCommand::InitialPass(std::vector<std::string> const& args)
  97. {
  98. if(args.size() < 1)
  99. {
  100. this->SetError("called with incorrect number of arguments");
  101. return false;
  102. }
  103. // create a function blocker
  104. cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
  105. if ( args.size() > 1 )
  106. {
  107. if ( args[1] == "RANGE" )
  108. {
  109. int start = 0;
  110. int stop = 0;
  111. int step = 0;
  112. if ( args.size() == 3 )
  113. {
  114. stop = atoi(args[2].c_str());
  115. }
  116. if ( args.size() == 4 )
  117. {
  118. start = atoi(args[2].c_str());
  119. stop = atoi(args[3].c_str());
  120. }
  121. if ( args.size() == 5 )
  122. {
  123. start = atoi(args[2].c_str());
  124. stop = atoi(args[3].c_str());
  125. step = atoi(args[4].c_str());
  126. }
  127. if ( step == 0 )
  128. {
  129. if ( start > stop )
  130. {
  131. step = -1;
  132. }
  133. else
  134. {
  135. step = 1;
  136. }
  137. }
  138. if (
  139. (start > stop && step > 0) ||
  140. (start < stop && step < 0) ||
  141. step == 0
  142. )
  143. {
  144. cmOStringStream str;
  145. str << "called with incorrect range specification: start ";
  146. str << start << ", stop " << stop << ", step " << step;
  147. this->SetError(str.str().c_str());
  148. return false;
  149. }
  150. std::vector<std::string> range;
  151. char buffer[100];
  152. range.push_back(args[0]);
  153. int cc;
  154. for ( cc = start; ; cc += step )
  155. {
  156. if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) )
  157. {
  158. break;
  159. }
  160. sprintf(buffer, "%d", cc);
  161. range.push_back(buffer);
  162. if ( cc == stop )
  163. {
  164. break;
  165. }
  166. }
  167. f->Args = range;
  168. }
  169. else
  170. {
  171. f->Args = args;
  172. }
  173. }
  174. else
  175. {
  176. f->Args = args;
  177. }
  178. this->Makefile->AddFunctionBlocker(f);
  179. return true;
  180. }