/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium 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 "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmTarget.h" #include "assert.h" #include #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" #include "cmGeneratorExpressionDAGChecker.h" //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( cmListFileBacktrace const& backtrace): Backtrace(backtrace), CompiledExpression(0) { } //---------------------------------------------------------------------------- const cmCompiledGeneratorExpression & cmGeneratorExpression::Parse(std::string const& input) { return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- const cmCompiledGeneratorExpression & cmGeneratorExpression::Parse(const char* input) { cmGeneratorExpressionLexer l; std::vector tokens = l.Tokenize(input); bool needsParsing = l.GetSawGeneratorExpression(); std::vector evaluators; if (needsParsing) { cmGeneratorExpressionParser p(tokens); p.Parse(evaluators); } delete this->CompiledExpression; this->CompiledExpression = new cmCompiledGeneratorExpression( this->Backtrace, evaluators, input, needsParsing); return *this->CompiledExpression; } cmGeneratorExpression::~cmGeneratorExpression() { delete this->CompiledExpression; } //---------------------------------------------------------------------------- const char *cmCompiledGeneratorExpression::Evaluate( cmMakefile* mf, const char* config, bool quiet, cmGeneratorTarget *target, cmGeneratorExpressionDAGChecker *dagChecker) const { if (!this->NeedsParsing) { return this->Input; } this->Output = ""; std::vector::const_iterator it = this->Evaluators.begin(); const std::vector::const_iterator end = this->Evaluators.end(); cmGeneratorExpressionContext context; context.Makefile = mf; context.Config = config; context.Quiet = quiet; context.HadError = false; context.Target = target; context.Backtrace = this->Backtrace; for ( ; it != end; ++it) { this->Output += (*it)->Evaluate(&context, dagChecker); if (context.HadError) { this->Output = ""; break; } } this->Targets = context.Targets; // TODO: Return a std::string from here instead? return this->Output.c_str(); } cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, const std::vector &evaluators, const char *input, bool needsParsing) : Backtrace(backtrace), Evaluators(evaluators), Input(input), NeedsParsing(needsParsing) { } //---------------------------------------------------------------------------- cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() { std::vector::const_iterator it = this->Evaluators.begin(); const std::vector::const_iterator end = this->Evaluators.end(); for ( ; it != end; ++it) { delete *it; } } std::string cmGeneratorExpression::Preprocess(const std::string &input, PreprocessContext context) { if (context != StripAllGeneratorExpressions) { assert(!"cmGeneratorExpression::Preprocess called with invalid args"); return std::string(); } std::string result; std::string::size_type pos = 0; std::string::size_type lastPos = pos; while((pos = input.find("$<", lastPos)) != input.npos) { result += input.substr(lastPos, pos - lastPos); pos += 2; int nestingLevel = 1; const char *c = input.c_str() + pos; const char * const cStart = c; for ( ; *c; ++c) { if(c[0] == '$' && c[1] == '<') { ++nestingLevel; ++c; continue; } if(c[0] == '>') { --nestingLevel; if (nestingLevel == 0) { break; } } } const std::string::size_type traversed = (c - cStart) + 1; if (!*c) { result += "$<" + input.substr(pos, traversed); } pos += traversed; lastPos = pos; } result += input.substr(lastPos); return result; }