Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGetFilenameComponentCommand.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 "cmGetFilenameComponentCommand.h"
4
5
#include "cmExecutionStatus.h"
6
#include "cmMakefile.h"
7
#include "cmStateTypes.h"
8
#include "cmStringAlgorithms.h"
9
#include "cmSystemTools.h"
10
#include "cmValue.h"
11
#include "cmake.h"
12
13
// cmGetFilenameComponentCommand
14
bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
15
                                   cmExecutionStatus& status)
16
0
{
17
0
  if (args.size() < 3) {
18
0
    status.SetError("called with incorrect number of arguments");
19
0
    cmSystemTools::SetFatalErrorOccurred();
20
0
    return false;
21
0
  }
22
23
  // Check and see if the value has been stored in the cache
24
  // already, if so use that value
25
0
  if (args.size() >= 4 && args.back() == "CACHE") {
26
0
    cmValue cacheValue = status.GetMakefile().GetDefinition(args.front());
27
0
    if (cacheValue && !cmIsNOTFOUND(*cacheValue)) {
28
0
      return true;
29
0
    }
30
0
  }
31
32
0
  std::string result;
33
0
  std::string filename = args[1];
34
0
  if (filename.find("[HKEY") != std::string::npos) {
35
    // Check the registry as the target application would view it.
36
0
    cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
37
0
    cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
38
0
    if (status.GetMakefile().PlatformIs64Bit()) {
39
0
      view = cmSystemTools::KeyWOW64_64;
40
0
      other_view = cmSystemTools::KeyWOW64_32;
41
0
    }
42
0
    cmSystemTools::ExpandRegistryValues(filename, view);
43
0
    if (filename.find("/registry") != std::string::npos) {
44
0
      std::string other = args[1];
45
0
      cmSystemTools::ExpandRegistryValues(other, other_view);
46
0
      if (other.find("/registry") == std::string::npos) {
47
0
        filename = other;
48
0
      }
49
0
    }
50
0
  }
51
0
  std::string storeArgs;
52
0
  std::string programArgs;
53
0
  if (args[2] == "DIRECTORY" || args[2] == "PATH") {
54
0
    result = cmSystemTools::GetFilenamePath(filename);
55
0
  } else if (args[2] == "NAME") {
56
0
    result = cmSystemTools::GetFilenameName(filename);
57
0
  } else if (args[2] == "PROGRAM") {
58
0
    for (unsigned int i = 2; i < args.size(); ++i) {
59
0
      if (args[i] == "PROGRAM_ARGS") {
60
0
        i++;
61
0
        if (i < args.size()) {
62
0
          storeArgs = args[i];
63
0
        }
64
0
      }
65
0
    }
66
67
    // First assume the path to the program was specified with no
68
    // arguments and with no quoting or escaping for spaces.
69
    // Only bother doing this if there is non-whitespace.
70
0
    if (!cmTrimWhitespace(filename).empty()) {
71
0
      result = cmSystemTools::FindProgram(filename);
72
0
    }
73
74
    // If that failed then assume a command-line string was given
75
    // and split the program part from the rest of the arguments.
76
0
    if (result.empty()) {
77
0
      std::string program;
78
0
      if (cmSystemTools::SplitProgramFromArgs(filename, program,
79
0
                                              programArgs)) {
80
0
        if (cmSystemTools::FileExists(program)) {
81
0
          result = program;
82
0
        } else {
83
0
          result = cmSystemTools::FindProgram(program);
84
0
        }
85
0
      }
86
0
      if (result.empty()) {
87
0
        programArgs.clear();
88
0
      }
89
0
    }
90
0
  } else if (args[2] == "EXT") {
91
0
    result = cmSystemTools::GetFilenameExtension(filename);
92
0
  } else if (args[2] == "NAME_WE") {
93
0
    result = cmSystemTools::GetFilenameWithoutExtension(filename);
94
0
  } else if (args[2] == "LAST_EXT") {
95
0
    result = cmSystemTools::GetFilenameLastExtension(filename);
96
0
  } else if (args[2] == "NAME_WLE") {
97
0
    result = cmSystemTools::GetFilenameWithoutLastExtension(filename);
98
0
  } else if (args[2] == "ABSOLUTE" || args[2] == "REALPATH") {
99
    // If the path given is relative, evaluate it relative to the
100
    // current source directory unless the user passes a different
101
    // base directory.
102
0
    std::string baseDir = status.GetMakefile().GetCurrentSourceDirectory();
103
0
    for (unsigned int i = 3; i < args.size(); ++i) {
104
0
      if (args[i] == "BASE_DIR") {
105
0
        ++i;
106
0
        if (i < args.size()) {
107
0
          baseDir = args[i];
108
0
        }
109
0
      }
110
0
    }
111
    // Collapse the path to its simplest form.
112
0
    result = cmSystemTools::CollapseFullPath(filename, baseDir);
113
0
    if (args[2] == "REALPATH") {
114
      // Resolve symlinks if possible
115
0
      result = cmSystemTools::GetRealPath(result);
116
0
    }
117
0
    result = cmSystemTools::GetActualCaseForPath(
118
0
      result, status.GetMakefile().GetCMakeInstance()->GetActualCaseCache());
119
0
  } else {
120
0
    std::string err = "unknown component " + args[2];
121
0
    status.SetError(err);
122
0
    cmSystemTools::SetFatalErrorOccurred();
123
0
    return false;
124
0
  }
125
126
0
  if (args.size() >= 4 && args.back() == "CACHE") {
127
0
    if (!programArgs.empty() && !storeArgs.empty()) {
128
0
      status.GetMakefile().AddCacheDefinition(
129
0
        storeArgs, programArgs, "",
130
0
        args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
131
0
    }
132
0
    status.GetMakefile().AddCacheDefinition(
133
0
      args.front(), result, "",
134
0
      args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
135
0
  } else {
136
0
    if (!programArgs.empty() && !storeArgs.empty()) {
137
0
      status.GetMakefile().AddDefinition(storeArgs, programArgs);
138
0
    }
139
0
    status.GetMakefile().AddDefinition(args.front(), result);
140
0
  }
141
142
0
  return true;
143
0
}