diff options
Diffstat (limited to 'Source/cmGeneratorExpressionEvaluator.cxx')
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx new file mode 100644 index 0000000..af94bcc --- /dev/null +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -0,0 +1,253 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmMakefile.h" + +#include "cmGeneratorExpressionEvaluator.h" +#include "cmGeneratorExpressionParser.h" +#include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" +#include "cmGlobalGenerator.h" +#include "cmSourceFile.h" +#include "cmAlgorithms.h" + +#include <cmsys/String.h> + +#include <assert.h> +#include <errno.h> + +#include "cmGeneratorExpressionNode.h" + +//---------------------------------------------------------------------------- +GeneratorExpressionContent::GeneratorExpressionContent( + const char *startContent, + size_t length) + : StartContent(startContent), ContentLength(length) +{ + +} + +//---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::GetOriginalExpression() const +{ + return std::string(this->StartContent, this->ContentLength); +} + +//---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::ProcessArbitraryContent( + const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pit) const +{ + std::string result; + + const + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pend = this->ParamChildren.end(); + for ( ; pit != pend; ++pit) + { + std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it + = pit->begin(); + const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end + = pit->end(); + for ( ; it != end; ++it) + { + if (node->RequiresLiteralInput()) + { + if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires literal input."); + return std::string(); + } + } + result += (*it)->Evaluate(context, dagChecker); + if (context->HadError) + { + return std::string(); + } + } + if ((pit + 1) != pend) + { + result += ","; + } + } + if (node->RequiresLiteralInput()) + { + std::vector<std::string> parameters; + parameters.push_back(result); + return node->Evaluate(parameters, context, this, dagChecker); + } + return result; +} + +//---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::Evaluate( + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker) const +{ + std::string identifier; + { + std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it + = this->IdentifierChildren.begin(); + const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end + = this->IdentifierChildren.end(); + for ( ; it != end; ++it) + { + identifier += (*it)->Evaluate(context, dagChecker); + if (context->HadError) + { + return std::string(); + } + } + } + + const cmGeneratorExpressionNode *node = + cmGeneratorExpressionNode::GetNode(identifier); + + if (!node) + { + reportError(context, this->GetOriginalExpression(), + "Expression did not evaluate to a known generator expression"); + return std::string(); + } + + if (!node->GeneratesContent()) + { + if (node->NumExpectedParameters() == 1 + && node->AcceptsArbitraryContentParameter()) + { + if (this->ParamChildren.empty()) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires a parameter."); + } + } + else + { + std::vector<std::string> parameters; + this->EvaluateParameters(node, identifier, context, dagChecker, + parameters); + } + return std::string(); + } + + std::vector<std::string> parameters; + this->EvaluateParameters(node, identifier, context, dagChecker, parameters); + if (context->HadError) + { + return std::string(); + } + + return node->Evaluate(parameters, context, this, dagChecker); +} + +//---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::EvaluateParameters( + const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector<std::string> ¶meters) const +{ + const int numExpected = node->NumExpectedParameters(); + { + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pit = this->ParamChildren.begin(); + const + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pend = this->ParamChildren.end(); + const bool acceptsArbitraryContent + = node->AcceptsArbitraryContentParameter(); + int counter = 1; + for ( ; pit != pend; ++pit, ++counter) + { + if (acceptsArbitraryContent && counter == numExpected) + { + std::string lastParam = this->ProcessArbitraryContent(node, identifier, + context, + dagChecker, + pit); + parameters.push_back(lastParam); + return std::string(); + } + else + { + std::string parameter; + std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it = + pit->begin(); + const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end = + pit->end(); + for ( ; it != end; ++it) + { + parameter += (*it)->Evaluate(context, dagChecker); + if (context->HadError) + { + return std::string(); + } + } + parameters.push_back(parameter); + } + } + } + + if ((numExpected > cmGeneratorExpressionNode::DynamicParameters + && (unsigned int)numExpected != parameters.size())) + { + if (numExpected == 0) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires no parameters."); + } + else if (numExpected == 1) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires " + "exactly one parameter."); + } + else + { + std::ostringstream e; + e << "$<" + identifier + "> expression requires " + << numExpected + << " comma separated parameters, but got " + << parameters.size() << " instead."; + reportError(context, this->GetOriginalExpression(), e.str()); + } + return std::string(); + } + + if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters + && parameters.empty()) + { + reportError(context, this->GetOriginalExpression(), "$<" + identifier + + "> expression requires at least one parameter."); + } + if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters + && parameters.size() > 1) + { + reportError(context, this->GetOriginalExpression(), "$<" + identifier + + "> expression requires one or zero parameters."); + } + return std::string(); +} + +//---------------------------------------------------------------------------- +GeneratorExpressionContent::~GeneratorExpressionContent() +{ + cmDeleteAll(this->IdentifierChildren); + std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(), + cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*> >); +} |