| 170 | } |
| 171 | |
| 172 | static std::string extractAllGeneratorExpressions( |
| 173 | cm::string_view input, |
| 174 | std::map<std::string, std::vector<std::string>>* collected) |
| 175 | { |
| 176 | std::string result; |
| 177 | std::string::size_type pos = 0; |
| 178 | std::string::size_type lastPos = pos; |
| 179 | std::stack<char const*> starts; // indices of "$<" |
| 180 | std::stack<char const*> colons; // indices of ":" |
| 181 | while ((pos = input.find("$<", lastPos)) != std::string::npos) { |
| 182 | result += input.substr(lastPos, pos - lastPos); |
| 183 | starts.push(input.data() + pos); |
| 184 | pos += 2; |
| 185 | char const* c = input.data() + pos; |
| 186 | char const* const cStart = c; |
| 187 | for (; *c; ++c) { |
| 188 | if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) { |
| 189 | starts.push(c); |
| 190 | ++c; |
| 191 | continue; |
| 192 | } |
| 193 | if (c[0] == ':') { |
| 194 | if (colons.size() < starts.size()) { |
| 195 | colons.push(c); |
| 196 | } |
| 197 | } else if (c[0] == '>') { |
| 198 | if (!colons.empty() && !starts.empty() && |
| 199 | starts.top() < colons.top()) { |
| 200 | if (collected) { |
| 201 | (*collected)[std::string(starts.top() + 2, colons.top())] |
| 202 | .push_back(std::string(colons.top() + 1, c)); |
| 203 | } |
| 204 | colons.pop(); |
| 205 | } |
| 206 | if (!starts.empty()) { |
| 207 | starts.pop(); |
| 208 | } |
| 209 | if (starts.empty()) { |
| 210 | break; |
| 211 | } |
| 212 | } |
| 213 | } |
| 214 | std::string::size_type const traversed = (c - cStart) + 1; |
| 215 | if (!*c) { |
| 216 | result += cmStrCat("$<", input.substr(pos, traversed)); |
| 217 | } |
| 218 | pos += traversed; |
| 219 | lastPos = pos; |
| 220 | } |
| 221 | if (starts.empty()) { |
| 222 | result += input.substr(lastPos); |
| 223 | } |
| 224 | return cmGeneratorExpression::StripEmptyListElements(result); |
| 225 | } |
| 226 | |
| 227 | static std::string stripAllGeneratorExpressions(cm::string_view input) |
| 228 | { |