resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmPlaceholderExpander.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmPlaceholderExpander.h"
4
5 #include <cctype>
6
7 std::string& cmPlaceholderExpander::ExpandVariables(std::string& s)
8 {
9   std::string::size_type start = s.find('<');
10   // no variables to expand
11   if (start == std::string::npos) {
12     return s;
13   }
14   std::string::size_type pos = 0;
15   std::string expandedInput;
16   while (start != std::string::npos && start < s.size() - 2) {
17     std::string::size_type end = s.find('>', start);
18     // if we find a < with no > we are done
19     if (end == std::string::npos) {
20       s = expandedInput;
21       return s;
22     }
23     char c = s[start + 1];
24     // if the next char after the < is not A-Za-z then
25     // skip it and try to find the next < in the string
26     if (!isalpha(c)) {
27       start = s.find('<', start + 1);
28     } else {
29       // extract the var
30       std::string var = s.substr(start + 1, end - start - 1);
31       std::string replace = this->ExpandVariable(var);
32       expandedInput += s.substr(pos, start - pos);
33
34       // Prevent consecutive whitespace in the output if the rule variable
35       // expands to an empty string.
36       bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' &&
37         end + 1 < s.size() && s[end + 1] == ' ';
38       if (consecutive) {
39         expandedInput.pop_back();
40       }
41
42       expandedInput += replace;
43
44       // move to next one
45       start = s.find('<', start + var.size() + 2);
46       pos = end + 1;
47     }
48   }
49   // add the rest of the input
50   expandedInput += s.substr(pos, s.size() - pos);
51   s = expandedInput;
52
53   return s;
54 }