cmGeneratorExpressionEvaluator.cxx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. parameters.push_back(this->ProcessArbitraryContent(
  123. node, identifier, context, dagChecker, pit));
  124. return std::string();
  125. }
  126. std::string parameter;
  127. std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
  128. pit->begin();
  129. const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
  130. pit->end();
  131. for (; it != end; ++it) {
  132. parameter += (*it)->Evaluate(context, dagChecker);
  133. if (context->HadError) {
  134. return std::string();
  135. }
  136. }
  137. parameters.push_back(std::move(parameter));
  138. }
  139. }
  140. if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
  141. static_cast<unsigned int>(numExpected) != parameters.size())) {
  142. if (numExpected == 0) {
  143. reportError(context, this->GetOriginalExpression(),
  144. "$<" + identifier + "> expression requires no parameters.");
  145. } else if (numExpected == 1) {
  146. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  147. "> expression requires "
  148. "exactly one parameter.");
  149. } else {
  150. std::ostringstream e;
  151. e << "$<" + identifier + "> expression requires " << numExpected
  152. << " comma separated parameters, but got " << parameters.size()
  153. << " instead.";
  154. reportError(context, this->GetOriginalExpression(), e.str());
  155. }
  156. return std::string();
  157. }
  158. if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
  159. parameters.empty()) {
  160. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  161. "> expression requires at least one parameter.");
  162. }
  163. if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
  164. parameters.size() > 1) {
  165. reportError(context, this->GetOriginalExpression(), "$<" + identifier +
  166. "> expression requires one or zero parameters.");
  167. }
  168. return std::string();
  169. }
  170. GeneratorExpressionContent::~GeneratorExpressionContent()
  171. {
  172. cmDeleteAll(this->IdentifierChildren);
  173. std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
  174. cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>);
  175. }