cmGeneratorExpressionEvaluator.cxx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmGeneratorExpressionEvaluator.h"
  4. #include "cmAlgorithms.h"
  5. #include "cmGeneratorExpressionContext.h"
  6. #include "cmGeneratorExpressionNode.h"
  7. #include <algorithm>
  8. #include <sstream>
  9. GeneratorExpressionContent::GeneratorExpressionContent(
  10. const char* startContent, size_t length)
  11. : StartContent(startContent)
  12. , ContentLength(length)
  13. {
  14. }
  15. std::string GeneratorExpressionContent::GetOriginalExpression() const
  16. {
  17. return std::string(this->StartContent, this->ContentLength);
  18. }
  19. std::string GeneratorExpressionContent::ProcessArbitraryContent(
  20. const cmGeneratorExpressionNode* node, const std::string& identifier,
  21. cmGeneratorExpressionContext* context,
  22. cmGeneratorExpressionDAGChecker* dagChecker,
  23. std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
  24. pit) const
  25. {
  26. std::string result;
  27. const std::vector<
  28. std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator pend =
  29. this->ParamChildren.end();
  30. for (; pit != pend; ++pit) {
  31. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
  32. pit->begin();
  33. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
  34. pit->end();
  35. for (; it != end; ++it) {
  36. if (node->RequiresLiteralInput()) {
  37. if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
  38. reportError(context, this->GetOriginalExpression(), "$<" +
  39. identifier + "> expression requires literal input.");
  40. return std::string();
  41. }
  42. }
  43. result += (*it)->Evaluate(context, dagChecker);
  44. if (context->HadError) {
  45. return std::string();
  46. }
  47. }
  48. if ((pit + 1) != pend) {
  49. result += ",";
  50. }
  51. }
  52. if (node->RequiresLiteralInput()) {
  53. std::vector<std::string> parameters;
  54. parameters.push_back(result);
  55. return node->Evaluate(parameters, context, this, dagChecker);
  56. }
  57. return result;
  58. }
  59. std::string GeneratorExpressionContent::Evaluate(
  60. cmGeneratorExpressionContext* context,
  61. cmGeneratorExpressionDAGChecker* dagChecker) const
  62. {
  63. std::string identifier;
  64. {
  65. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
  66. this->IdentifierChildren.begin();
  67. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
  68. this->IdentifierChildren.end();
  69. for (; it != end; ++it) {
  70. identifier += (*it)->Evaluate(context, dagChecker);
  71. if (context->HadError) {
  72. return std::string();
  73. }
  74. }
  75. }
  76. const cmGeneratorExpressionNode* node =
  77. cmGeneratorExpressionNode::GetNode(identifier);
  78. if (!node) {
  79. reportError(context, this->GetOriginalExpression(),
  80. "Expression did not evaluate to a known generator expression");
  81. return std::string();
  82. }
  83. if (!node->GeneratesContent()) {
  84. if (node->NumExpectedParameters() == 1 &&
  85. node->AcceptsArbitraryContentParameter()) {
  86. if (this->ParamChildren.empty()) {
  87. reportError(context, this->GetOriginalExpression(),
  88. "$<" + identifier + "> expression requires a parameter.");
  89. }
  90. } else {
  91. std::vector<std::string> parameters;
  92. this->EvaluateParameters(node, identifier, context, dagChecker,
  93. parameters);
  94. }
  95. return std::string();
  96. }
  97. std::vector<std::string> parameters;
  98. this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
  99. if (context->HadError) {
  100. return std::string();
  101. }
  102. return node->Evaluate(parameters, context, this, dagChecker);
  103. }
  104. std::string GeneratorExpressionContent::EvaluateParameters(
  105. const cmGeneratorExpressionNode* node, const std::string& identifier,
  106. cmGeneratorExpressionContext* context,
  107. cmGeneratorExpressionDAGChecker* dagChecker,
  108. std::vector<std::string>& parameters) const
  109. {
  110. const int numExpected = node->NumExpectedParameters();
  111. {
  112. std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
  113. pit = this->ParamChildren.begin();
  114. const std::vector<
  115. std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator pend =
  116. this->ParamChildren.end();
  117. const bool acceptsArbitraryContent =
  118. node->AcceptsArbitraryContentParameter();
  119. int counter = 1;
  120. for (; pit != pend; ++pit, ++counter) {
  121. if (acceptsArbitraryContent && counter == numExpected) {
  122. std::string lastParam = this->ProcessArbitraryContent(
  123. node, identifier, context, dagChecker, pit);
  124. parameters.push_back(lastParam);
  125. return std::string();
  126. }
  127. std::string parameter;
  128. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
  129. pit->begin();
  130. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
  131. pit->end();
  132. for (; it != end; ++it) {
  133. parameter += (*it)->Evaluate(context, dagChecker);
  134. if (context->HadError) {
  135. return std::string();
  136. }
  137. }
  138. parameters.push_back(parameter);
  139. }
  140. }
  141. if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
  142. static_cast<unsigned int>(numExpected) != parameters.size())) {
  143. if (numExpected == 0) {
  144. reportError(context, this->GetOriginalExpression(),
  145. "$<" + identifier + "> expression requires no parameters.");
  146. } else if (numExpected == 1) {
  147. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  148. "> expression requires "
  149. "exactly one parameter.");
  150. } else {
  151. std::ostringstream e;
  152. e << "$<" + identifier + "> expression requires " << numExpected
  153. << " comma separated parameters, but got " << parameters.size()
  154. << " instead.";
  155. reportError(context, this->GetOriginalExpression(), e.str());
  156. }
  157. return std::string();
  158. }
  159. if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
  160. parameters.empty()) {
  161. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  162. "> expression requires at least one parameter.");
  163. }
  164. if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
  165. parameters.size() > 1) {
  166. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  167. "> expression requires one or zero parameters.");
  168. }
  169. return std::string();
  170. }
  171. GeneratorExpressionContent::~GeneratorExpressionContent()
  172. {
  173. cmDeleteAll(this->IdentifierChildren);
  174. std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
  175. cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>);
  176. }