cmMacroCommand.cxx 5.0 KB

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