diff options
Diffstat (limited to 'Source/cmGeneratorExpression.cxx')
-rw-r--r-- | Source/cmGeneratorExpression.cxx | 263 |
1 files changed, 225 insertions, 38 deletions
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 7d8df37..7add1bf 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -25,55 +25,55 @@ //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( cmListFileBacktrace const& backtrace): - Backtrace(backtrace), CompiledExpression(0) + Backtrace(backtrace) { } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(std::string const& input) { return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(const char* input) { - cmGeneratorExpressionLexer l; - std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(input); - bool needsParsing = l.GetSawGeneratorExpression(); - std::vector<cmGeneratorExpressionEvaluator*> evaluators; - - if (needsParsing) - { - cmGeneratorExpressionParser p(tokens); - p.Parse(evaluators); - } - - delete this->CompiledExpression; - this->CompiledExpression = new cmCompiledGeneratorExpression( - this->Backtrace, - evaluators, - input, - needsParsing); - return *this->CompiledExpression; + return cmsys::auto_ptr<cmCompiledGeneratorExpression>( + new cmCompiledGeneratorExpression( + this->Backtrace, + input)); } cmGeneratorExpression::~cmGeneratorExpression() { - delete this->CompiledExpression; } //---------------------------------------------------------------------------- const char *cmCompiledGeneratorExpression::Evaluate( cmMakefile* mf, const char* config, bool quiet, - cmGeneratorTarget *target, + cmTarget *headTarget, + cmGeneratorExpressionDAGChecker *dagChecker) const +{ + return this->Evaluate(mf, + config, + quiet, + headTarget, + headTarget, + dagChecker); +} + +//---------------------------------------------------------------------------- +const char *cmCompiledGeneratorExpression::Evaluate( + cmMakefile* mf, const char* config, bool quiet, + cmTarget *headTarget, + cmTarget *currentTarget, cmGeneratorExpressionDAGChecker *dagChecker) const { if (!this->NeedsParsing) { - return this->Input; + return this->Input.c_str(); } this->Output = ""; @@ -88,18 +88,32 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Config = config; context.Quiet = quiet; context.HadError = false; - context.Target = target; + context.HadContextSensitiveCondition = false; + context.HeadTarget = headTarget; + context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.Backtrace = this->Backtrace; for ( ; it != end; ++it) { - this->Output += (*it)->Evaluate(&context, dagChecker); + const std::string result = (*it)->Evaluate(&context, dagChecker); + this->Output += result; + + for(std::set<cmStdString>::const_iterator + p = context.SeenTargetProperties.begin(); + p != context.SeenTargetProperties.end(); ++p) + { + this->SeenTargetProperties[*p] += result + ";"; + } if (context.HadError) { this->Output = ""; break; } } + if (!context.HadError) + { + this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; + } this->Targets = context.Targets; // TODO: Return a std::string from here instead? @@ -108,12 +122,20 @@ const char *cmCompiledGeneratorExpression::Evaluate( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, - const std::vector<cmGeneratorExpressionEvaluator*> &evaluators, - const char *input, bool needsParsing) - : Backtrace(backtrace), Evaluators(evaluators), Input(input), - NeedsParsing(needsParsing) + const char *input) + : Backtrace(backtrace), Input(input ? input : ""), + HadContextSensitiveCondition(false) { + cmGeneratorExpressionLexer l; + std::vector<cmGeneratorExpressionToken> tokens = + l.Tokenize(this->Input.c_str()); + this->NeedsParsing = l.GetSawGeneratorExpression(); + if (this->NeedsParsing) + { + cmGeneratorExpressionParser p(tokens); + p.Parse(this->Evaluators); + } } @@ -131,15 +153,41 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() } } -std::string cmGeneratorExpression::Preprocess(const std::string &input, - PreprocessContext context) +//---------------------------------------------------------------------------- +static std::string stripEmptyListElements(const std::string &input) { - if (context != StripAllGeneratorExpressions) - { - assert(!"cmGeneratorExpression::Preprocess called with invalid args"); - return std::string(); - } + std::string result; + + const char *c = input.c_str(); + bool skipSemiColons = true; + for ( ; *c; ++c) + { + if(c[0] == ';') + { + if(skipSemiColons) + { + continue; + } + skipSemiColons = true; + } + else + { + skipSemiColons = false; + } + result += *c; + } + if (!result.empty() && *(result.end() - 1) == ';') + { + result.resize(result.size() - 1); + } + + return result; +} + +//---------------------------------------------------------------------------- +static std::string stripAllGeneratorExpressions(const std::string &input) +{ std::string result; std::string::size_type pos = 0; std::string::size_type lastPos = pos; @@ -176,5 +224,144 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input, lastPos = pos; } result += input.substr(lastPos); - return result; + return stripEmptyListElements(result); +} + +//---------------------------------------------------------------------------- +static std::string stripExportInterface(const std::string &input, + cmGeneratorExpression::PreprocessContext context) +{ + std::string result; + + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$<BUILD_INTERFACE:", lastPos)) != input.npos + || (pos = input.find("$<INSTALL_INTERFACE:", lastPos)) != input.npos) + { + result += input.substr(lastPos, pos - lastPos); + const bool gotInstallInterface = input[pos + 2] == 'I'; + pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1 + : sizeof("$<BUILD_INTERFACE:") - 1; + 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) + { + continue; + } + if(context == cmGeneratorExpression::BuildInterface + && !gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + else if(context == cmGeneratorExpression::InstallInterface + && gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + break; + } + } + const std::string::size_type traversed = (c - cStart) + 1; + if (!*c) + { + result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:" + : "$<BUILD_INTERFACE:") + + input.substr(pos, traversed); + } + pos += traversed; + lastPos = pos; + } + result += input.substr(lastPos); + + return stripEmptyListElements(result); +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpression::Split(const std::string &input, + std::vector<std::string> &output) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$<", lastPos)) != input.npos) + { + std::string part = input.substr(lastPos, pos - lastPos); + std::string preGenex; + if (!part.empty()) + { + std::string::size_type startPos = input.rfind(";", pos); + if (startPos != pos - 1 && startPos >= lastPos) + { + part = input.substr(lastPos, startPos - lastPos); + preGenex = input.substr(startPos + 1, pos - startPos - 1); + } + cmSystemTools::ExpandListArgument(part.c_str(), output); + } + 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; + } + } + } + for ( ; *c; ++c) + { + // Capture the part after the genex and before the next ';' + if(c[0] == ';') + { + --c; + break; + } + } + const std::string::size_type traversed = (c - cStart) + 1; + output.push_back(preGenex + "$<" + input.substr(pos, traversed)); + pos += traversed; + lastPos = pos; + } + if (lastPos < input.size()) + { + cmSystemTools::ExpandListArgument(input.substr(lastPos), output); + } +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorExpression::Preprocess(const std::string &input, + PreprocessContext context) +{ + if (context == StripAllGeneratorExpressions) + { + return stripAllGeneratorExpressions(input); + } + else if (context == BuildInterface || context == InstallInterface) + { + return stripExportInterface(input, context); + } + + assert(!"cmGeneratorExpression::Preprocess called with invalid args"); + return std::string(); } |