Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmPlaceholderExpander.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmPlaceholderExpander.h"
4
5
#include "cmsys/String.h"
6
7
std::string& cmPlaceholderExpander::ExpandVariables(std::string& s,
8
                                                    HandleGenex handleGenex)
9
0
{
10
0
  std::string::size_type start = s.find('<');
11
  // no variables to expand
12
0
  if (start == std::string::npos) {
13
0
    return s;
14
0
  }
15
0
  std::string::size_type pos = 0;
16
0
  std::string expandedInput;
17
0
  while (start != std::string::npos && start < s.size() - 2) {
18
0
    if (handleGenex == HandleGenex::Yes && start != 0 && s[start - 1] == '$') {
19
      // this is a generator expression
20
      // skip it and try to find the next < in the string
21
0
      start = s.find('<', start + 1);
22
0
      continue;
23
0
    }
24
25
0
    std::string::size_type end = s.find('>', start);
26
    // if we find a < with no > we are done
27
0
    if (end == std::string::npos) {
28
0
      s = expandedInput;
29
0
      return s;
30
0
    }
31
32
    // if the previous character is a '$',  this is a generator expression
33
    // or if the next char after the < is not A-Za-z then
34
    // skip it and try to find the next < in the string
35
0
    if ((handleGenex == HandleGenex::Yes && start != 0 &&
36
0
         s[start - 1] == '$') ||
37
0
        !cmsysString_isalpha(s[start + 1])) {
38
0
      start = s.find('<', start + 1);
39
0
    } else {
40
      // extract the var
41
0
      std::string var = s.substr(start + 1, end - start - 1);
42
0
      std::string replace = this->ExpandVariable(var);
43
0
      expandedInput += s.substr(pos, start - pos);
44
45
      // Prevent consecutive whitespace in the output if the rule variable
46
      // expands to an empty string.
47
0
      bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' &&
48
0
        end + 1 < s.size() && s[end + 1] == ' ';
49
0
      if (consecutive) {
50
0
        expandedInput.pop_back();
51
0
      }
52
53
0
      expandedInput += replace;
54
55
      // move to next one
56
0
      start = s.find('<', start + var.size() + 2);
57
0
      pos = end + 1;
58
0
    }
59
0
  }
60
  // add the rest of the input
61
0
  expandedInput += s.substr(pos, s.size() - pos);
62
  // remove trailing whitespace
63
0
  if (!expandedInput.empty() && expandedInput.back() == ' ') {
64
0
    expandedInput.pop_back();
65
0
  }
66
0
  s = expandedInput;
67
68
0
  return s;
69
0
}