cmMacroCommand.cxx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 "cmMacroCommand.h"
  14. bool cmMacroFunctionBlocker::
  15. IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
  16. {
  17. // record commands until we hit the ENDMACRO
  18. if (!m_Executing)
  19. {
  20. // at the ENDMACRO call we shift gears and start looking for invocations
  21. if(lff.m_Name == "ENDMACRO")
  22. {
  23. std::vector<std::string> expandedArguments;
  24. mf.ExpandArguments(lff.m_Arguments, expandedArguments);
  25. if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0]))
  26. {
  27. m_Executing = true;
  28. return true;
  29. }
  30. }
  31. // if it wasn't an endmacro and we are not executing then we must be
  32. // recording
  33. m_Functions.push_back(lff);
  34. return true;
  35. }
  36. // otherwise the macro has been recorded and we are executing
  37. // so we look for macro invocations
  38. if(lff.m_Name == m_Args[0])
  39. {
  40. std::string tmps;
  41. cmListFileArgument arg;
  42. std::string variable;
  43. // Expand the argument list to the macro.
  44. std::vector<std::string> expandedArguments;
  45. mf.ExpandArguments(lff.m_Arguments, expandedArguments);
  46. // make sure the number of arguments matches
  47. if (expandedArguments.size() != m_Args.size() - 1)
  48. {
  49. cmOStringStream error;
  50. error << "Error in cmake code at\n"
  51. << lff.m_FilePath << ":" << lff.m_Line << ":\n"
  52. << "Invocation of macro \""
  53. << lff.m_Name.c_str() << "\" with incorrect number of arguments.";
  54. cmSystemTools::Error(error.str().c_str());
  55. return true;
  56. }
  57. // Invoke all the functions that were collected in the block.
  58. cmListFileFunction newLFF;
  59. for(unsigned int c = 0; c < m_Functions.size(); ++c)
  60. {
  61. // Replace the formal arguments and then invoke the command.
  62. newLFF.m_Arguments.clear();
  63. newLFF.m_Arguments.reserve(m_Functions[c].m_Arguments.size());
  64. newLFF.m_Name = m_Functions[c].m_Name;
  65. newLFF.m_FilePath = m_Functions[c].m_FilePath;
  66. newLFF.m_Line = m_Functions[c].m_Line;
  67. for (std::vector<cmListFileArgument>::const_iterator k =
  68. m_Functions[c].m_Arguments.begin();
  69. k != m_Functions[c].m_Arguments.end(); ++k)
  70. {
  71. tmps = k->Value;
  72. for (unsigned int j = 1; j < m_Args.size(); ++j)
  73. {
  74. variable = "${";
  75. variable += m_Args[j];
  76. variable += "}";
  77. cmSystemTools::ReplaceString(tmps, variable.c_str(),
  78. expandedArguments[j-1].c_str());
  79. }
  80. arg.Value = tmps;
  81. arg.Quoted = k->Quoted;
  82. newLFF.m_Arguments.push_back(arg);
  83. }
  84. if(!mf.ExecuteCommand(newLFF))
  85. {
  86. cmOStringStream error;
  87. error << "Error in cmake code at\n"
  88. << lff.m_FilePath << ":" << lff.m_Line << ":\n"
  89. << "A command failed during the invocation of macro \""
  90. << lff.m_Name.c_str() << "\".";
  91. cmSystemTools::Error(error.str().c_str());
  92. }
  93. }
  94. return true;
  95. }
  96. // if not an invocation then it is just an ordinary line
  97. return false;
  98. }
  99. bool cmMacroFunctionBlocker::
  100. ShouldRemove(const cmListFileFunction&, cmMakefile &)
  101. {
  102. return false;
  103. }
  104. void cmMacroFunctionBlocker::
  105. ScopeEnded(cmMakefile &mf)
  106. {
  107. // macros never leave scope but we should have seen the ENDMACRO call by now
  108. if (m_Executing != true)
  109. {
  110. cmSystemTools::Error("The end of a CMakeLists file was reached with a MACRO statement that was not closed properly. Within the directory: ",
  111. mf.GetCurrentDirectory(), " with macro ",
  112. m_Args[0].c_str());
  113. }
  114. }
  115. bool cmMacroCommand::InitialPass(std::vector<std::string> const& args)
  116. {
  117. if(args.size() < 1)
  118. {
  119. this->SetError("called with incorrect number of arguments");
  120. return false;
  121. }
  122. // create a function blocker
  123. cmMacroFunctionBlocker *f = new cmMacroFunctionBlocker();
  124. for(std::vector<std::string>::const_iterator j = args.begin();
  125. j != args.end(); ++j)
  126. {
  127. f->m_Args.push_back(*j);
  128. }
  129. m_Makefile->AddFunctionBlocker(f);
  130. return true;
  131. }