From 13c7bb5b0cb08713b178169fe0d571a6e4689f39 Mon Sep 17 00:00:00 2001 From: Martin Duffy Date: Tue, 8 Apr 2025 09:32:46 -0400 Subject: [PATCH] cmGeneratorExpression: Update strip function to collect parsed expressions --- Source/cmGeneratorExpression.cxx | 42 ++++++++++++++++++++++++++------ Source/cmGeneratorExpression.h | 4 +++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 873ed7e062..f0dcde7a47 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -156,27 +157,40 @@ std::string cmGeneratorExpression::StripEmptyListElements( return result; } -static std::string stripAllGeneratorExpressions(std::string const& input) +static std::string extractAllGeneratorExpressions( + std::string const& input, + std::map>* collected) { std::string result; std::string::size_type pos = 0; std::string::size_type lastPos = pos; - int nestingLevel = 0; + // stack of { Generator Expression Name, Start Position of Value } + std::stack> genexps; while ((pos = input.find("$<", lastPos)) != std::string::npos) { result += input.substr(lastPos, pos - lastPos); pos += 2; - nestingLevel = 1; char const* c = input.c_str() + pos; + char const* cName = c; char const* const cStart = c; for (; *c; ++c) { if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) { - ++nestingLevel; ++c; + cName = c + 1; continue; } - if (c[0] == '>') { - --nestingLevel; - if (nestingLevel == 0) { + if (c[0] == ':' && cName) { + genexps.push({ input.substr(pos + (cName - cStart), c - cName), + pos + (c + 1 - cStart) }); + cName = nullptr; + } else if (c[0] == '>') { + if (!cName && !genexps.empty()) { + if (collected) { + (*collected)[genexps.top().first].push_back(input.substr( + genexps.top().second, pos + c - cStart - genexps.top().second)); + } + genexps.pop(); + } + if (genexps.empty()) { break; } } @@ -188,12 +202,17 @@ static std::string stripAllGeneratorExpressions(std::string const& input) pos += traversed; lastPos = pos; } - if (nestingLevel == 0) { + if (genexps.empty()) { result += input.substr(lastPos); } return cmGeneratorExpression::StripEmptyListElements(result); } +static std::string stripAllGeneratorExpressions(std::string const& input) +{ + return extractAllGeneratorExpressions(input, nullptr); +} + static void prefixItems(std::string const& content, std::string& result, cm::string_view const& prefix) { @@ -375,6 +394,13 @@ std::string cmGeneratorExpression::Preprocess(std::string const& input, return std::string(); } +std::string cmGeneratorExpression::Collect( + std::string const& input, + std::map>& collected) +{ + return extractAllGeneratorExpressions(input, &collected); +} + cm::string_view::size_type cmGeneratorExpression::Find( cm::string_view const& input) { diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 293459c672..3ffc39d3b5 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -63,6 +63,10 @@ public: PreprocessContext context, cm::string_view importPrefix = {}); + static std::string Collect( + std::string const& input, + std::map>& collected); + static void Split(std::string const& input, std::vector& output);