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"
7 #include "cmGeneratorExpressionContext.h"
8 #include "cmGeneratorExpressionNode.h"
10 GeneratorExpressionContent::GeneratorExpressionContent(
11 const char* startContent, size_t length)
12 : StartContent(startContent)
13 , ContentLength(length)
17 GeneratorExpressionContent::~GeneratorExpressionContent() = default;
19 std::string GeneratorExpressionContent::GetOriginalExpression() const
21 return std::string(this->StartContent, this->ContentLength);
24 std::string GeneratorExpressionContent::ProcessArbitraryContent(
25 const cmGeneratorExpressionNode* node, const std::string& identifier,
26 cmGeneratorExpressionContext* context,
27 cmGeneratorExpressionDAGChecker* dagChecker,
28 std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const
32 const auto pend = this->ParamChildren.end();
33 for (; pit != pend; ++pit) {
34 for (const auto& pExprEval : *pit) {
35 if (node->RequiresLiteralInput()) {
36 if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
37 reportError(context, this->GetOriginalExpression(),
39 "> expression requires literal input.");
43 result += pExprEval->Evaluate(context, dagChecker);
44 if (context->HadError) {
48 if ((pit + 1) != pend) {
52 if (node->RequiresLiteralInput()) {
53 std::vector<std::string> parameters;
54 parameters.push_back(result);
55 return node->Evaluate(parameters, context, this, dagChecker);
60 std::string GeneratorExpressionContent::Evaluate(
61 cmGeneratorExpressionContext* context,
62 cmGeneratorExpressionDAGChecker* dagChecker) const
64 std::string identifier;
66 for (const auto& pExprEval : this->IdentifierChildren) {
67 identifier += pExprEval->Evaluate(context, dagChecker);
68 if (context->HadError) {
74 const cmGeneratorExpressionNode* node =
75 cmGeneratorExpressionNode::GetNode(identifier);
78 reportError(context, this->GetOriginalExpression(),
79 "Expression did not evaluate to a known generator expression");
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.");
91 std::vector<std::string> parameters;
92 this->EvaluateParameters(node, identifier, context, dagChecker,
98 std::vector<std::string> parameters;
99 this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
100 if (context->HadError) {
101 return std::string();
104 return node->Evaluate(parameters, context, this, dagChecker);
107 std::string GeneratorExpressionContent::EvaluateParameters(
108 const cmGeneratorExpressionNode* node, const std::string& identifier,
109 cmGeneratorExpressionContext* context,
110 cmGeneratorExpressionDAGChecker* dagChecker,
111 std::vector<std::string>& parameters) const
113 const int numExpected = node->NumExpectedParameters();
115 auto pit = this->ParamChildren.begin();
116 const auto pend = this->ParamChildren.end();
117 const bool acceptsArbitraryContent =
118 node->AcceptsArbitraryContentParameter();
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();
126 std::string parameter;
127 for (const auto& pExprEval : *pit) {
128 parameter += pExprEval->Evaluate(context, dagChecker);
129 if (context->HadError) {
130 return std::string();
133 parameters.push_back(std::move(parameter));
137 if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
138 static_cast<unsigned int>(numExpected) != parameters.size())) {
139 if (numExpected == 0) {
140 reportError(context, this->GetOriginalExpression(),
141 "$<" + identifier + "> expression requires no parameters.");
142 } else if (numExpected == 1) {
143 reportError(context, this->GetOriginalExpression(),
145 "> expression requires "
146 "exactly one parameter.");
148 std::ostringstream e;
149 e << "$<" + identifier + "> expression requires " << numExpected
150 << " comma separated parameters, but got " << parameters.size()
152 reportError(context, this->GetOriginalExpression(), e.str());
154 return std::string();
157 if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
158 parameters.empty()) {
159 reportError(context, this->GetOriginalExpression(),
161 "> expression requires at least one parameter.");
162 } else if (numExpected == cmGeneratorExpressionNode::TwoOrMoreParameters &&
163 parameters.size() < 2) {
164 reportError(context, this->GetOriginalExpression(),
166 "> expression requires at least two parameters.");
167 } else if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
168 parameters.size() > 1) {
169 reportError(context, this->GetOriginalExpression(),
171 "> expression requires one or zero parameters.");
173 return std::string();