From ef8aa19c33e83ff019595fd7f8fdc29c35c336a3 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 13 Feb 2013 18:21:12 -0800 Subject: Imported Upstream version 2.8.10.2 --- Source/cmGeneratorExpression.cxx | 261 +++++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 137 deletions(-) (limited to 'Source/cmGeneratorExpression.cxx') diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index f88ab0b71..7d8df3733 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -13,181 +13,168 @@ #include "cmMakefile.h" #include "cmTarget.h" +#include "assert.h" + +#include + +#include "cmGeneratorExpressionEvaluator.h" +#include "cmGeneratorExpressionLexer.h" +#include "cmGeneratorExpressionParser.h" +#include "cmGeneratorExpressionDAGChecker.h" //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( - cmMakefile* mf, const char* config, - cmListFileBacktrace const& backtrace, bool quiet): - Makefile(mf), Config(config), Backtrace(backtrace), Quiet(quiet) + cmListFileBacktrace const& backtrace): + Backtrace(backtrace), CompiledExpression(0) { - this->TargetInfo.compile("^\\$$"); } //---------------------------------------------------------------------------- -const char* cmGeneratorExpression::Process(std::string const& input) +const cmCompiledGeneratorExpression & +cmGeneratorExpression::Parse(std::string const& input) { - return this->Process(input.c_str()); + return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- -const char* cmGeneratorExpression::Process(const char* input) +const cmCompiledGeneratorExpression & +cmGeneratorExpression::Parse(const char* input) { - this->Data.clear(); + cmGeneratorExpressionLexer l; + std::vector tokens = l.Tokenize(input); + bool needsParsing = l.GetSawGeneratorExpression(); + std::vector evaluators; - // We construct and evaluate expressions directly in the output - // buffer. Each expression is replaced by its own output value - // after evaluation. A stack of barriers records the starting - // indices of open (pending) expressions. - for(const char* c = input; *c; ++c) + if (needsParsing) { - if(c[0] == '$' && c[1] == '<') - { - this->Barriers.push(this->Data.size()); - this->Data.push_back('$'); - this->Data.push_back('<'); - c += 1; - } - else if(c[0] == '>' && !this->Barriers.empty()) - { - this->Data.push_back('>'); - if(!this->Evaluate()) { break; } - this->Barriers.pop(); - } - else - { - this->Data.push_back(c[0]); - } + cmGeneratorExpressionParser p(tokens); + p.Parse(evaluators); } - // Return a null-terminated output value. - this->Data.push_back('\0'); - return &*this->Data.begin(); + delete this->CompiledExpression; + this->CompiledExpression = new cmCompiledGeneratorExpression( + this->Backtrace, + evaluators, + input, + needsParsing); + return *this->CompiledExpression; } -//---------------------------------------------------------------------------- -bool cmGeneratorExpression::Evaluate() +cmGeneratorExpression::~cmGeneratorExpression() { - // The top-most barrier points at the beginning of the expression. - size_t barrier = this->Barriers.top(); - - // Construct a null-terminated representation of the expression. - this->Data.push_back('\0'); - const char* expr = &*(this->Data.begin()+barrier); - - // Evaluate the expression. - std::string result; - if(this->Evaluate(expr, result)) - { - // Success. Replace the expression with its evaluation result. - this->Data.erase(this->Data.begin()+barrier, this->Data.end()); - this->Data.insert(this->Data.end(), result.begin(), result.end()); - return true; - } - else if(!this->Quiet) - { - // Failure. Report the error message. - cmOStringStream e; - e << "Error evaluating generator expression:\n" - << " " << expr << "\n" - << result; - this->Makefile->GetCMakeInstance() - ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), - this->Backtrace); - return false; - } - return true; + delete this->CompiledExpression; } //---------------------------------------------------------------------------- -bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result) +const char *cmCompiledGeneratorExpression::Evaluate( + cmMakefile* mf, const char* config, bool quiet, + cmGeneratorTarget *target, + cmGeneratorExpressionDAGChecker *dagChecker) const { - if(this->TargetInfo.find(expr)) - { - if(!this->EvaluateTargetInfo(result)) - { - return false; - } - } - else if(strcmp(expr, "$") == 0) + if (!this->NeedsParsing) { - result = this->Config? this->Config : ""; + return this->Input; } - else + + 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) { - result = "Expression syntax not recognized."; - return false; + this->Output += (*it)->Evaluate(&context, dagChecker); + if (context.HadError) + { + this->Output = ""; + break; + } } - return true; + + 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) +{ + +} + + //---------------------------------------------------------------------------- -bool cmGeneratorExpression::EvaluateTargetInfo(std::string& result) +cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() { - // Lookup the referenced target. - std::string name = this->TargetInfo.match(3); - cmTarget* target = this->Makefile->FindTargetToUse(name.c_str()); - if(!target) - { - result = "No target \"" + name + "\""; - return false; - } - if(target->GetType() >= cmTarget::UTILITY && - target->GetType() != cmTarget::UNKNOWN_LIBRARY) - { - result = "Target \"" + name + "\" is not an executable or library."; - return false; - } - this->Targets.insert(target); + std::vector::const_iterator it + = this->Evaluators.begin(); + const std::vector::const_iterator end + = this->Evaluators.end(); - // Lookup the target file with the given purpose. - std::string purpose = this->TargetInfo.match(1); - if(purpose == "") + for ( ; it != end; ++it) { - // The target implementation file (.so.1.2, .dll, .exe, .a). - result = target->GetFullPath(this->Config, false, true); + delete *it; } - else if(purpose == "_LINKER") - { - // The file used to link to the target (.so, .lib, .a). - if(!target->IsLinkable()) - { - result = ("TARGET_LINKER_FILE is allowed only for libraries and " - "executables with ENABLE_EXPORTS."); - return false; - } - result = target->GetFullPath(this->Config, target->HasImportLibrary()); - } - else if(purpose == "_SONAME") +} + +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) { - // The target soname file (.so.1). - if(target->IsDLLPlatform()) + 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) { - result = "TARGET_SONAME_FILE is not allowed for DLL target platforms."; - return false; + if(c[0] == '$' && c[1] == '<') + { + ++nestingLevel; + ++c; + continue; + } + if(c[0] == '>') + { + --nestingLevel; + if (nestingLevel == 0) + { + break; + } + } } - if(target->GetType() != cmTarget::SHARED_LIBRARY) + const std::string::size_type traversed = (c - cStart) + 1; + if (!*c) { - result = "TARGET_SONAME_FILE is allowed only for SHARED libraries."; - return false; + result += "$<" + input.substr(pos, traversed); } - result = target->GetDirectory(this->Config); - result += "/"; - result += target->GetSOName(this->Config); - } - - // Extract the requested portion of the full path. - std::string part = this->TargetInfo.match(2); - if(part == "_NAME") - { - result = cmSystemTools::GetFilenameName(result); - } - else if(part == "_DIR") - { - result = cmSystemTools::GetFilenamePath(result); + pos += traversed; + lastPos = pos; } - return true; + result += input.substr(lastPos); + return result; } -- cgit v1.2.3