summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt5
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.cxx5
-rw-r--r--Source/QtDialog/CMakeSetup.cxx6
-rw-r--r--Source/cmCacheManager.cxx43
-rw-r--r--Source/cmCacheManager.h14
-rw-r--r--Source/cmCoreTryCompile.cxx40
-rw-r--r--Source/cmFileCommand.cxx7
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx11
-rw-r--r--Source/cmGetPropertyCommand.cxx10
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx4
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx10
-rw-r--r--Source/cmLoadCommandCommand.cxx10
-rw-r--r--Source/cmLocalGenerator.cxx10
-rw-r--r--Source/cmLocalNinjaGenerator.cxx5
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx40
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx4
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx3
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx27
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx27
-rw-r--r--Source/cmNinjaTargetGenerator.cxx2
-rw-r--r--Source/cmRulePlaceholderExpander.cxx13
-rw-r--r--Source/cmSetPropertyCommand.cxx10
-rw-r--r--Source/cmSourceGroupCommand.cxx21
-rw-r--r--Source/cmStandardLexer.h13
-rw-r--r--Source/cmState.cxx41
-rw-r--r--Source/cmState.h3
-rw-r--r--Source/cmSystemTools.cxx10
-rw-r--r--Source/cmTarget.cxx2
-rw-r--r--Source/cmTimestamp.cxx10
-rw-r--r--Source/kwsys/Directory.cxx12
-rw-r--r--Source/kwsys/Directory.hxx.in10
-rw-r--r--Source/kwsys/Glob.cxx3
-rw-r--r--Source/kwsys/SystemInformation.cxx19
-rw-r--r--Source/kwsys/SystemTools.cxx160
37 files changed, 332 insertions, 284 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 467abe9..564e647 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -1,6 +1,11 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+# To ensure maximum portability across various compilers and platforms
+# deactivate any compiler extensions
+set(CMAKE_C_EXTENSIONS FALSE)
+set(CMAKE_CXX_EXTENSIONS FALSE)
+
include(CheckIncludeFile)
# Check if we can build support for ELF parsing.
if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 14e01fa..73b7771 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 17)
-set(CMake_VERSION_PATCH 20200323)
+set(CMake_VERSION_PATCH 20200326)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index c0d879a..b4085d5 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -1,5 +1,10 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#if defined(__CYGWIN__)
+// For S_IWRITE symbol
+# define _DEFAULT_SOURCE
+#endif
+
#include "cmWIXFilesSourceWriter.h"
#include "cm_sys_stat.h"
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index ee81a7d..9d928b2 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -201,8 +201,7 @@ int main(int argc, char** argv)
cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data());
// check if argument is a directory containing CMakeCache.txt
- std::string buildFilePath =
- cmSystemTools::CollapseFullPath("CMakeCache.txt", filePath.c_str());
+ std::string buildFilePath = cmStrCat(filePath, "/CMakeCache.txt");
// check if argument is a CMakeCache.txt file
if (cmSystemTools::GetFilenameName(filePath) == "CMakeCache.txt" &&
@@ -211,8 +210,7 @@ int main(int argc, char** argv)
}
// check if argument is a directory containing CMakeLists.txt
- std::string srcFilePath =
- cmSystemTools::CollapseFullPath("CMakeLists.txt", filePath.c_str());
+ std::string srcFilePath = cmStrCat(filePath, "/CMakeLists.txt");
if (cmSystemTools::FileExists(buildFilePath.c_str())) {
dialog.setBinaryDirectory(QString::fromLocal8Bit(
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 0e05936..c444fce 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -124,13 +124,13 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
}
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- if (const std::string* cmajor =
+ if (cmProp cmajor =
this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
unsigned int v = 0;
if (sscanf(cmajor->c_str(), "%u", &v) == 1) {
this->CacheMajorVersion = v;
}
- if (const std::string* cminor =
+ if (cmProp cminor =
this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
if (sscanf(cminor->c_str(), "%u", &v) == 1) {
this->CacheMinorVersion = v;
@@ -150,8 +150,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
}
// check to make sure the cache directory has not
// been moved
- const std::string* oldDir =
- this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ cmProp oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
if (internal && oldDir) {
std::string currentcwd = path;
std::string oldcwd = *oldDir;
@@ -159,8 +158,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- const std::string* dir =
- this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ cmProp dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
std::ostringstream message;
message << "The current CMakeCache.txt directory " << currentcwd
<< " is different than the directory " << (dir ? *dir : "")
@@ -210,7 +208,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
cmMessenger* messenger)
{
for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) {
- if (const char* value = i.GetProperty(*p)) {
+ if (cmProp value = i.GetProperty(*p)) {
std::string helpstring =
cmStrCat(*p, " property for variable: ", i.GetName());
cmCacheManager::OutputHelpString(os, helpstring);
@@ -218,9 +216,9 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
std::string key = cmStrCat(i.GetName(), '-', *p);
cmCacheManager::OutputKey(os, key);
os << ":INTERNAL=";
- cmCacheManager::OutputValue(os, value);
+ cmCacheManager::OutputValue(os, *value);
os << "\n";
- cmCacheManager::OutputNewlineTruncationWarning(os, key, value,
+ cmCacheManager::OutputNewlineTruncationWarning(os, key, *value,
messenger);
}
}
@@ -305,8 +303,8 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
*/
} else if (t != cmStateEnums::INTERNAL) {
// Format is key:type=value
- if (const char* help = ce.GetProperty("HELPSTRING")) {
- cmCacheManager::OutputHelpString(fout, help);
+ if (cmProp help = ce.GetProperty("HELPSTRING")) {
+ cmCacheManager::OutputHelpString(fout, *help);
} else {
cmCacheManager::OutputHelpString(fout, "Missing description");
}
@@ -336,8 +334,8 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
this->WritePropertyEntries(fout, i, messenger);
if (t == cmStateEnums::INTERNAL) {
// Format is key:type=value
- if (const char* help = i.GetProperty("HELPSTRING")) {
- cmCacheManager::OutputHelpString(fout, help);
+ if (cmProp help = i.GetProperty("HELPSTRING")) {
+ cmCacheManager::OutputHelpString(fout, *help);
}
cmCacheManager::OutputKey(fout, i.GetName());
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
@@ -510,8 +508,7 @@ cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator()
return { *this, nullptr };
}
-const std::string* cmCacheManager::GetInitializedCacheValue(
- const std::string& key) const
+cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const
{
auto i = this->Cache.find(key);
if (i != this->Cache.end() && i->second.Initialized) {
@@ -621,17 +618,15 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
return this->Properties.GetKeys();
}
-const char* cmCacheManager::CacheEntry::GetProperty(
- const std::string& prop) const
+cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
{
if (prop == "TYPE") {
- return cmState::CacheEntryTypeToString(this->Type).c_str();
+ return &cmState::CacheEntryTypeToString(this->Type);
}
if (prop == "VALUE") {
- return this->Value.c_str();
+ return &this->Value;
}
- cmProp retVal = this->Properties.GetPropertyValue(prop);
- return retVal ? retVal->c_str() : nullptr;
+ return this->Properties.GetPropertyValue(prop);
}
void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
@@ -665,7 +660,7 @@ void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop,
}
}
-const char* cmCacheManager::CacheIterator::GetProperty(
+cmProp cmCacheManager::CacheIterator::GetProperty(
const std::string& prop) const
{
if (!this->IsAtEnd()) {
@@ -694,8 +689,8 @@ void cmCacheManager::CacheIterator::AppendProperty(const std::string& p,
bool cmCacheManager::CacheIterator::GetPropertyAsBool(
const std::string& prop) const
{
- if (const char* value = this->GetProperty(prop)) {
- return cmIsOn(value);
+ if (cmProp value = this->GetProperty(prop)) {
+ return cmIsOn(*value);
}
return false;
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index d8be991..3db76a9 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -37,7 +37,7 @@ private:
cmStateEnums::CacheEntryType Type = cmStateEnums::UNINITIALIZED;
cmPropertyMap Properties;
std::vector<std::string> GetPropertyList() const;
- const char* GetProperty(const std::string&) const;
+ cmProp GetProperty(const std::string&) const;
void SetProperty(const std::string& property, const char* value);
void AppendProperty(const std::string& property, const std::string& value,
bool asString = false);
@@ -54,7 +54,7 @@ public:
void Next();
std::string GetName() const { return this->Position->first; }
std::vector<std::string> GetPropertyList() const;
- const char* GetProperty(const std::string&) const;
+ cmProp GetProperty(const std::string&) const;
bool GetPropertyAsBool(const std::string&) const;
bool PropertyExists(const std::string&) const;
void SetProperty(const std::string& property, const char* value);
@@ -121,19 +121,19 @@ public:
int GetSize() { return static_cast<int>(this->Cache.size()); }
//! Get a value from the cache given a key
- const std::string* GetInitializedCacheValue(const std::string& key) const;
+ cmProp GetInitializedCacheValue(const std::string& key) const;
- const char* GetCacheEntryValue(const std::string& key)
+ cmProp GetCacheEntryValue(const std::string& key)
{
cmCacheManager::CacheIterator it = this->GetCacheIterator(key);
if (it.IsAtEnd()) {
return nullptr;
}
- return it.GetValue().c_str();
+ return &it.GetValue();
}
- const char* GetCacheEntryProperty(std::string const& key,
- std::string const& propName)
+ cmProp GetCacheEntryProperty(std::string const& key,
+ std::string const& propName)
{
return this->GetCacheIterator(key).GetProperty(propName);
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index da04396..9c26f61 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -101,29 +101,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->SrcFileSignature = true;
cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
- const char* tt =
- this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
- if (!isTryRun && tt && *tt) {
- if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) ==
- 0) {
+ const std::string* tt =
+ this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE");
+ if (!isTryRun && tt && !tt->empty()) {
+ if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) {
targetType = cmStateEnums::EXECUTABLE;
- } else if (strcmp(tt,
- cmState::GetTargetTypeName(
- cmStateEnums::STATIC_LIBRARY)) == 0) {
+ } else if (*tt ==
+ cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) {
targetType = cmStateEnums::STATIC_LIBRARY;
} else {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- std::string("Invalid value '") + tt +
- "' for "
- "CMAKE_TRY_COMPILE_TARGET_TYPE. Only "
- "'" +
- cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) +
- "' and "
- "'" +
- cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) +
- "' "
- "are allowed.");
+ cmStrCat("Invalid value '", *tt,
+ "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '",
+ cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE),
+ "' and '",
+ cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY),
+ "' are allowed."));
return -1;
}
}
@@ -296,12 +290,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
default:
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- "Only libraries may be used as try_compile or try_run IMPORTED "
- "LINK_LIBRARIES. Got " +
- std::string(tgt->GetName()) +
- " of "
- "type " +
- cmState::GetTargetTypeName(tgt->GetType()) + ".");
+ cmStrCat("Only libraries may be used as try_compile or try_run "
+ "IMPORTED LINK_LIBRARIES. Got ",
+ tgt->GetName(), " of type ",
+ cmState::GetTargetTypeName(tgt->GetType()), "."));
return -1;
}
if (tgt->IsImported()) {
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 8b450d0..4603b13 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2327,12 +2327,9 @@ bool HandleLockCommand(std::vector<std::string> const& args,
path += "/cmake.lock";
}
- if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = status.GetMakefile().GetCurrentSourceDirectory() + "/" + path;
- }
-
// Unify path (remove '//', '/../', ...)
- path = cmSystemTools::CollapseFullPath(path);
+ path = cmSystemTools::CollapseFullPath(
+ path, status.GetMakefile().GetCurrentSourceDirectory());
// Create file and directories if needed
std::string parentDir = cmSystemTools::GetParentDirectory(path);
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 64438d5..65b3457 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -7,7 +7,6 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
namespace {
@@ -37,14 +36,8 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
"DIRECTORY argument provided without subsequent arguments");
return false;
}
- std::string sd = *i;
- // make sure the start dir is a full path
- if (!cmSystemTools::FileIsFullPath(sd)) {
- sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
- }
-
- // The local generators are associated with collapsed paths.
- sd = cmSystemTools::CollapseFullPath(sd);
+ std::string sd = cmSystemTools::CollapseFullPath(
+ *i, status.GetMakefile().GetCurrentSourceDirectory());
// lookup the makefile from the directory name
dir = status.GetMakefile().GetGlobalGenerator()->FindMakefile(sd);
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 947d893..2c3adde 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -256,14 +256,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
if (!name.empty()) {
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
- std::string dir = name;
- if (!cmSystemTools::FileIsFullPath(dir)) {
- dir =
- cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name);
- }
-
- // The local generators are associated with collapsed paths.
- dir = cmSystemTools::CollapseFullPath(dir);
+ std::string dir = cmSystemTools::CollapseFullPath(
+ name, status.GetMakefile().GetCurrentSourceDirectory());
// Lookup the generator.
mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index d58113c..94483ca 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1009,7 +1009,7 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
// Get a stream where to generate things.
this->CompileCommandsStream =
cm::make_unique<cmGeneratedFileStream>(buildFilePath);
- *this->CompileCommandsStream << "[";
+ *this->CompileCommandsStream << "[\n";
} else {
*this->CompileCommandsStream << "," << std::endl;
}
@@ -1021,7 +1021,7 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
}
/* clang-format off */
- *this->CompileCommandsStream << "\n{\n"
+ *this->CompileCommandsStream << "{\n"
<< R"( "directory": ")"
<< cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
<< R"( "command": ")"
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 7daca74..e213023 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -697,9 +697,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
// # in target
- progCmd << lg.ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progress.Dir),
- cmOutputConverter::SHELL);
+ progCmd << lg.ConvertToOutputFormat(progress.Dir,
+ cmOutputConverter::SHELL);
//
std::set<cmGeneratorTarget const*> emitted;
progCmd << " "
@@ -711,9 +710,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
- progCmd << lg.ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progress.Dir),
- cmOutputConverter::SHELL);
+ progCmd << lg.ConvertToOutputFormat(progress.Dir,
+ cmOutputConverter::SHELL);
progCmd << " 0";
commands.push_back(progCmd.str());
}
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 92258e2..5790e16 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -1,5 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+
+#if !defined(_WIN32) && !defined(__sun)
+// POSIX APIs are needed
+# define _POSIX_C_SOURCE 200809L
+#endif
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+// For isascii
+# define _XOPEN_SOURCE 700
+#endif
+
#include "cmLoadCommandCommand.h"
#include <csignal>
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index a7799b6..e7cc189 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -877,7 +877,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) {
flags.back() = ' ';
}
- return flags;
+ return cmTrimWhitespace(flags);
}
void cmLocalGenerator::AddCompileOptions(std::string& flags,
@@ -1390,8 +1390,8 @@ void cmLocalGenerator::GetTargetFlags(
for (cmSourceFile* sf : sources) {
if (sf->GetExtension() == "def") {
sharedLibFlags += defFlag;
- sharedLibFlags += this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(sf->ResolveFullPath()), SHELL);
+ sharedLibFlags +=
+ this->ConvertToOutputFormat(sf->ResolveFullPath(), SHELL);
sharedLibFlags += " ";
}
}
@@ -2396,7 +2396,9 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
void cmLocalGenerator::AppendFlags(std::string& flags,
const std::string& newFlags) const
{
- if (!newFlags.empty()) {
+ bool allSpaces = std::all_of(newFlags.begin(), newFlags.end(), cmIsSpace);
+
+ if (!newFlags.empty() && !allSpaces) {
if (!flags.empty()) {
flags += " ";
}
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index be1dd0d..1568397 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -144,8 +144,9 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
bool forceFullPaths)
{
if (forceFullPaths) {
- return this->ConvertToOutputFormat(cmSystemTools::CollapseFullPath(path),
- format);
+ return this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()),
+ format);
}
return this->ConvertToOutputFormat(
this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path),
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index cab23ef..95c326a 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -623,8 +623,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables(
this->MaybeConvertWatcomShellCommand(cmSystemTools::GetCMakeCommand());
if (cmakeShellCommand.empty()) {
cmakeShellCommand = this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
- cmOutputConverter::SHELL);
+ cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
}
/* clang-format off */
@@ -648,16 +647,14 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables(
<< "# The top-level source directory on which CMake was run.\n"
<< "CMAKE_SOURCE_DIR = "
<< this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(this->GetSourceDirectory()),
- cmOutputConverter::SHELL)
+ this->GetSourceDirectory(), cmOutputConverter::SHELL)
<< "\n"
<< "\n";
makefileStream
<< "# The top-level build directory on which CMake was run.\n"
<< "CMAKE_BINARY_DIR = "
<< this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(this->GetBinaryDirectory()),
- cmOutputConverter::SHELL)
+ this->GetBinaryDirectory(), cmOutputConverter::SHELL)
<< "\n"
<< "\n";
/* clang-format on */
@@ -974,7 +971,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
// Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = target->GetName().c_str();
- vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(target->GetType()).c_str();
std::string output;
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
@@ -1053,10 +1051,9 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
cleanfile += filename;
}
cleanfile += ".cmake";
- std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
- cmsys::ofstream fout(cleanfilePath.c_str());
+ cmsys::ofstream fout(cleanfile.c_str());
if (!fout) {
- cmSystemTools::Error("Could not create " + cleanfilePath);
+ cmSystemTools::Error("Could not create " + cleanfile);
}
if (!files.empty()) {
fout << "file(REMOVE_RECURSE\n";
@@ -1116,10 +1113,9 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
// Write clean script
{
- std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
- cmsys::ofstream fout(cleanfilePath.c_str());
+ cmsys::ofstream fout(cleanfile.c_str());
if (!fout) {
- cmSystemTools::Error("Could not create " + cleanfilePath);
+ cmSystemTools::Error("Could not create " + cleanfile);
return;
}
fout << "file(REMOVE_RECURSE\n";
@@ -1190,9 +1186,8 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
color_name);
if (progress) {
cmd += "--progress-dir=";
- cmd += this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progress->Dir),
- cmOutputConverter::SHELL);
+ cmd += this->ConvertToOutputFormat(progress->Dir,
+ cmOutputConverter::SHELL);
cmd += " ";
cmd += "--progress-num=";
cmd += progress->Arg;
@@ -1632,15 +1627,14 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
- progCmd << this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL);
+ progCmd << this->ConvertToOutputFormat(progressDir,
+ cmOutputConverter::SHELL);
std::string progressFile = "/CMakeFiles/progress.marks";
std::string progressFileNameFull = this->ConvertToFullPath(progressFile);
progCmd << " "
- << this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progressFileNameFull),
- cmOutputConverter::SHELL);
+ << this->ConvertToOutputFormat(progressFileNameFull,
+ cmOutputConverter::SHELL);
commands.push_back(progCmd.str());
}
std::string mf2Dir = "CMakeFiles/Makefile2";
@@ -1650,8 +1644,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
- progCmd << this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL);
+ progCmd << this->ConvertToOutputFormat(progressDir,
+ cmOutputConverter::SHELL);
progCmd << " 0";
commands.push_back(progCmd.str());
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index e635f5b..0c1f0cc 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -226,7 +226,6 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
std::string makefileIn =
cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
- makefileIn = cmSystemTools::CollapseFullPath(makefileIn);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
if (file->GetCustomCommand()) {
return file;
@@ -257,8 +256,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
"--check-stamp-file", stampName });
std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
const char* no_working_directory = nullptr;
- std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName);
- this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn,
+ this->AddCustomCommandToOutput(stampName, listFiles, makefileIn,
commandLines, comment.c_str(),
no_working_directory, true, false);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 8d50898..7267976 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -154,8 +154,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
script += newline;
newline = newline_text;
script += "cd ";
- script += this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(workingDirectory), SHELL);
+ script += this->ConvertToOutputFormat(workingDirectory, SHELL);
script += check_error;
// Change the working drive.
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 0471a45..4fe10ad 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -547,7 +547,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
vars.CMTargetType =
- cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
vars.Language = linkLanguage.c_str();
vars.Objects = buildObjs.c_str();
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d3f3a4f..4434f1d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -756,7 +756,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
vars.CMTargetType =
- cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
vars.Language = linkLanguage.c_str();
vars.AIXExports = aixExports.c_str();
vars.Objects = buildObjs.c_str();
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 451f19e..f0fc34f 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -639,7 +639,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
vars.CMTargetType =
- cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
+ cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
vars.Language = lang.c_str();
vars.Target = targetOutPathReal.c_str();
vars.TargetPDB = targetOutPathPDB.c_str();
@@ -716,8 +716,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// no launcher for CMAKE_EXPORT_COMPILE_COMMANDS
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
compileCommand, vars);
- std::string workingDirectory = cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetCurrentBinaryDirectory());
+ std::string workingDirectory =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
this->GetFlags(lang, this->GetConfigName()));
std::string langDefines = std::string("$(") + lang + "_DEFINES)";
@@ -1129,8 +1129,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
// translation table for the dependency scanning process.
depCmd << "cd "
<< (this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetBinaryDirectory()),
+ this->LocalGenerator->GetBinaryDirectory(),
cmOutputConverter::SHELL))
<< " && ";
#endif
@@ -1146,23 +1145,19 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
<< this->GlobalGenerator->GetName() << "\" "
<< this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetSourceDirectory()),
+ this->LocalGenerator->GetSourceDirectory(),
cmOutputConverter::SHELL)
<< " "
<< this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetCurrentSourceDirectory()),
+ this->LocalGenerator->GetCurrentSourceDirectory(),
cmOutputConverter::SHELL)
<< " "
<< this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetBinaryDirectory()),
+ this->LocalGenerator->GetBinaryDirectory(),
cmOutputConverter::SHELL)
<< " "
<< this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetCurrentBinaryDirectory()),
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
cmOutputConverter::SHELL)
<< " "
<< this->LocalGenerator->ConvertToOutputFormat(
@@ -1250,8 +1245,10 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
// Setup implicit dependency scanning.
for (auto const& idi : ccg.GetCC().GetImplicitDepends()) {
- std::string objFullPath = cmSystemTools::CollapseFullPath(outputs[0]);
- std::string srcFullPath = cmSystemTools::CollapseFullPath(idi.second);
+ std::string objFullPath = cmSystemTools::CollapseFullPath(
+ outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
+ std::string srcFullPath = cmSystemTools::CollapseFullPath(
+ idi.second, this->LocalGenerator->GetCurrentBinaryDirectory());
this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first,
objFullPath, srcFullPath);
}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 062c46c..9c4ff83 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -156,23 +156,25 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule(
const std::string& config) const
{
- return this->TargetLinkLanguage(config) + "_" +
- cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_LINKER__" +
+ return cmStrCat(
+ this->TargetLinkLanguage(config), "_",
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()),
+ "_LINKER__",
cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName()) +
- "_" + config;
+ this->GetGeneratorTarget()->GetName()),
+ "_", config);
}
std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule(
const std::string& config) const
{
- return this->TargetLinkLanguage(config) + "_" +
- cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_DEVICE_LINKER__" +
+ return cmStrCat(
+ this->TargetLinkLanguage(config), "_",
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()),
+ "_DEVICE_LINKER__",
cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName()) +
- "_" + config;
+ this->GetGeneratorTarget()->GetName()),
+ "_", config);
}
struct cmNinjaRemoveNoOpCommands
@@ -191,7 +193,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
vars.CMTargetType =
- cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
+ .c_str();
vars.Language = "CUDA";
@@ -282,7 +285,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
cmNinjaRule rule(std::move(linkRuleName));
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
- vars.CMTargetType = cmState::GetTargetTypeName(targetType);
+ vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str();
std::string lang = this->TargetLinkLanguage(config);
vars.Language = config.c_str();
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 0e1136f..8833fa4 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -495,7 +495,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
vars.CMTargetType =
- cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str();
vars.Language = lang.c_str();
vars.Source = "$in";
vars.Object = "$out";
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index 5ab1b3a..254131b 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -236,8 +236,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
}
if (variable == "CMAKE_COMMAND") {
return outputConverter->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
- cmOutputConverter::SHELL);
+ cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
}
auto compIt = this->Compilers.find(variable);
@@ -334,7 +333,17 @@ void cmRulePlaceholderExpander::ExpandRuleVariables(
std::string replace =
this->ExpandRuleVariable(outputConverter, var, replaceValues);
expandedInput += s.substr(pos, start - pos);
+
+ // Prevent consecutive whitespace in the output if the rule variable
+ // expands to an empty string.
+ bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' &&
+ end + 1 < s.size() && s[end + 1] == ' ';
+ if (consecutive) {
+ expandedInput.pop_back();
+ }
+
expandedInput += replace;
+
// move to next one
start = s.find('<', start + var.size() + 2);
pos = end + 1;
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index e7330ef..4dbbbd7 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -235,14 +235,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status,
if (!names.empty()) {
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
- std::string dir = *names.begin();
- if (!cmSystemTools::FileIsFullPath(dir)) {
- dir = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
- *names.begin());
- }
-
- // The local generators are associated with collapsed paths.
- dir = cmSystemTools::CollapseFullPath(dir);
+ std::string dir = cmSystemTools::CollapseFullPath(
+ *names.begin(), status.GetMakefile().GetCurrentSourceDirectory());
mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
if (!mf) {
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index cc62952..8350410 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -30,18 +30,6 @@ std::vector<std::string> tokenizePath(const std::string& path)
return cmTokenize(path, "\\/");
}
-std::string getFullFilePath(const std::string& currentPath,
- const std::string& path)
-{
- std::string fullPath = path;
-
- if (!cmSystemTools::FileIsFullPath(path)) {
- fullPath = cmStrCat(currentPath, '/', path);
- }
-
- return cmSystemTools::CollapseFullPath(fullPath);
-}
-
std::set<std::string> getSourceGroupFilesPaths(
const std::string& root, const std::vector<std::string>& files)
{
@@ -124,7 +112,8 @@ bool addFilesToItsSourceGroups(const std::string& root,
errorMsg = "Could not create source group for file: " + sgFilesPath;
return false;
}
- const std::string fullPath = getFullFilePath(root, sgFilesPath);
+ const std::string fullPath =
+ cmSystemTools::CollapseFullPath(sgFilesPath, root);
sg->AddGroupFile(fullPath);
}
}
@@ -255,10 +244,8 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args,
parsedArguments[kFilesOptionName];
for (auto const& filesArg : filesArguments) {
std::string src = filesArg;
- if (!cmSystemTools::FileIsFullPath(src)) {
- src = cmStrCat(mf.GetCurrentSourceDirectory(), '/', filesArg);
- }
- src = cmSystemTools::CollapseFullPath(src);
+ src =
+ cmSystemTools::CollapseFullPath(src, mf.GetCurrentSourceDirectory());
sg->AddGroupFile(src);
}
}
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index 13f7622..55d23c1 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -3,6 +3,19 @@
#ifndef cmStandardLexer_h
#define cmStandardLexer_h
+#if !defined(_WIN32) && !defined(__sun)
+/* POSIX APIs are needed */
+# define _POSIX_C_SOURCE 200809L
+#endif
+#if defined(__sun) && defined(__GNUC__) && !defined(__cplusplus)
+/* C sources: for fileno and strdup */
+# define _XOPEN_SOURCE 600
+#endif
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+/* For isascii */
+# define _XOPEN_SOURCE 700
+#endif
+
#include "cmsys/Configure.h" // IWYU pragma: keep
/* Disable some warnings. */
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index bc08223..6d95c7a 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -34,30 +34,44 @@ cmState::cmState()
cmState::~cmState() = default;
-const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
-{
+const std::string& cmState::GetTargetTypeName(
+ cmStateEnums::TargetType targetType)
+{
+#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
+ MAKE_STATIC_PROP(STATIC_LIBRARY);
+ MAKE_STATIC_PROP(MODULE_LIBRARY);
+ MAKE_STATIC_PROP(SHARED_LIBRARY);
+ MAKE_STATIC_PROP(OBJECT_LIBRARY);
+ MAKE_STATIC_PROP(EXECUTABLE);
+ MAKE_STATIC_PROP(UTILITY);
+ MAKE_STATIC_PROP(GLOBAL_TARGET);
+ MAKE_STATIC_PROP(INTERFACE_LIBRARY);
+ MAKE_STATIC_PROP(UNKNOWN_LIBRARY);
+ static const std::string propEmpty;
+#undef MAKE_STATIC_PROP
+
switch (targetType) {
case cmStateEnums::STATIC_LIBRARY:
- return "STATIC_LIBRARY";
+ return propSTATIC_LIBRARY;
case cmStateEnums::MODULE_LIBRARY:
- return "MODULE_LIBRARY";
+ return propMODULE_LIBRARY;
case cmStateEnums::SHARED_LIBRARY:
- return "SHARED_LIBRARY";
+ return propSHARED_LIBRARY;
case cmStateEnums::OBJECT_LIBRARY:
- return "OBJECT_LIBRARY";
+ return propOBJECT_LIBRARY;
case cmStateEnums::EXECUTABLE:
- return "EXECUTABLE";
+ return propEXECUTABLE;
case cmStateEnums::UTILITY:
- return "UTILITY";
+ return propUTILITY;
case cmStateEnums::GLOBAL_TARGET:
- return "GLOBAL_TARGET";
+ return propGLOBAL_TARGET;
case cmStateEnums::INTERFACE_LIBRARY:
- return "INTERFACE_LIBRARY";
+ return propINTERFACE_LIBRARY;
case cmStateEnums::UNKNOWN_LIBRARY:
- return "UNKNOWN_LIBRARY";
+ return propUNKNOWN_LIBRARY;
}
assert(false && "Unexpected target type");
- return nullptr;
+ return propEmpty;
}
static const std::array<std::string, 7> cmCacheEntryTypes = {
@@ -199,7 +213,8 @@ const char* cmState::GetCacheEntryProperty(std::string const& key,
if (!it.PropertyExists(propertyName)) {
return nullptr;
}
- return it.GetProperty(propertyName);
+ cmProp retVal = it.GetProperty(propertyName);
+ return retVal ? retVal->c_str() : nullptr;
}
bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
diff --git a/Source/cmState.h b/Source/cmState.h
index b577a72..89400d6 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -53,7 +53,8 @@ public:
CPack,
};
- static const char* GetTargetTypeName(cmStateEnums::TargetType targetType);
+ static const std::string& GetTargetTypeName(
+ cmStateEnums::TargetType targetType);
cmStateSnapshot CreateBaseSnapshot();
cmStateSnapshot CreateBuildsystemDirectorySnapshot(
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 071f18e..d290c0c 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1,5 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+
+#if !defined(_WIN32) && !defined(__sun)
+// POSIX APIs are needed
+# define _POSIX_C_SOURCE 200809L
+#endif
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+// For isascii
+# define _XOPEN_SOURCE 700
+#endif
+
#include "cmSystemTools.h"
#include <cmext/algorithm>
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 03f1525..872f02c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1668,7 +1668,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
}
// the type property returns what type the target is
if (prop == propTYPE) {
- return cmState::GetTargetTypeName(this->GetType());
+ return cmState::GetTargetTypeName(this->GetType()).c_str();
}
if (prop == propINCLUDE_DIRECTORIES) {
if (impl->IncludeDirectoriesEntries.empty()) {
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 390fd16..13f73dc 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -1,5 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+
+#if !defined(_WIN32) && !defined(__sun)
+// POSIX APIs are needed
+# define _POSIX_C_SOURCE 200809L
+#endif
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+// For isascii
+# define _XOPEN_SOURCE 700
+#endif
+
#include "cmTimestamp.h"
#include <cstdlib>
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 1a772b4..d640948 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -35,6 +35,18 @@ Directory::Directory()
this->Internal = new DirectoryInternals;
}
+Directory::Directory(Directory&& other)
+{
+ this->Internal = other.Internal;
+ other.Internal = nullptr;
+}
+
+Directory& Directory::operator=(Directory&& other)
+{
+ std::swap(this->Internal, other.Internal);
+ return *this;
+}
+
Directory::~Directory()
{
delete this->Internal;
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index ad8c51b..9b0f4c3 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -23,6 +23,11 @@ class @KWSYS_NAMESPACE@_EXPORT Directory
{
public:
Directory();
+ Directory(Directory&& other);
+ Directory(const Directory&) = delete;
+ Directory& operator=(const Directory&) = delete;
+ Directory& operator=(Directory&& other);
+ bool operator==(const Directory&) = delete;
~Directory();
/**
@@ -62,10 +67,7 @@ public:
private:
// Private implementation details.
DirectoryInternals* Internal;
-
- Directory(const Directory&); // Not implemented.
- void operator=(const Directory&); // Not implemented.
-}; // End Class: Directory
+}; // End Class: Directory
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 658b816..8e30f92 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -385,10 +385,9 @@ bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages)
}
if (skip > 0) {
- expr = expr.substr(skip);
+ expr.erase(0, skip);
}
- cexpr = "";
for (cc = 0; cc < expr.size(); cc++) {
int ch = expr[cc];
if (ch == '/') {
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 3cf64a8..95b06e1 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1367,7 +1367,7 @@ std::string SymbolProperties::GetFileName(const std::string& path) const
if (!this->ReportPath) {
size_t at = file.rfind("/");
if (at != std::string::npos) {
- file = file.substr(at + 1);
+ file.erase(0, at + 1);
}
}
return file;
@@ -2170,7 +2170,7 @@ void SystemInformationImplementation::FindManufacturer(
this->ChipManufacturer = HP; // Hewlett-Packard
else if (this->ChipID.Vendor == "Motorola")
this->ChipManufacturer = Motorola; // Motorola Microelectronics
- else if (family.substr(0, 7) == "PA-RISC")
+ else if (family.compare(0, 7, "PA-RISC") == 0)
this->ChipManufacturer = HP; // Hewlett-Packard
else
this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
@@ -2885,7 +2885,7 @@ static void SystemInformationStripLeadingSpace(std::string& str)
// post-process the name.
std::string::size_type pos = str.find_first_not_of(" ");
if (pos != std::string::npos) {
- str = str.substr(pos);
+ str.erase(0, pos);
}
}
#endif
@@ -3400,7 +3400,9 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(
return this->ExtractValueFromCpuInfoFile(buffer, word, pos2);
}
}
- return buffer.substr(pos + 2, pos2 - pos - 2);
+ buffer.erase(0, pos + 2);
+ buffer.resize(pos2 - pos - 2);
+ return buffer;
}
}
this->CurrentPositionInFile = std::string::npos;
@@ -3549,7 +3551,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
if (!cacheSize.empty()) {
pos = cacheSize.find(" KB");
if (pos != std::string::npos) {
- cacheSize = cacheSize.substr(0, pos);
+ cacheSize.resize(pos);
}
this->Features.L1CacheSize += atoi(cacheSize.c_str());
}
@@ -4774,7 +4776,8 @@ std::string SystemInformationImplementation::ParseValueFromKStat(
}
pos = command.find(' ', pos + 1);
}
- args_string.push_back(command.substr(start + 1, command.size() - start - 1));
+ command.erase(0, start + 1);
+ args_string.push_back(command);
std::vector<const char*> args;
args.reserve(3 + args_string.size());
@@ -4963,7 +4966,9 @@ bool SystemInformationImplementation::QueryQNXMemory()
while (buffer[pos] == ' ')
pos++;
- this->TotalPhysicalMemory = atoi(buffer.substr(pos, pos2 - pos).c_str());
+ buffer.erase(0, pos);
+ buffer.resize(pos2);
+ this->TotalPhysicalMemory = atoi(buffer.c_str());
return true;
#endif
return false;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 3fa1745..e073cbf 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -221,11 +221,17 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft)
#ifdef KWSYS_WINDOWS_DIRS
# include <wctype.h>
+# ifdef _MSC_VER
+typedef KWSYS_NAMESPACE::SystemTools::mode_t mode_t;
+# endif
-inline int Mkdir(const std::string& dir)
+inline int Mkdir(const std::string& dir, const mode_t* mode)
{
- return _wmkdir(
- KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
+ int ret =
+ _wmkdir(KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
+ if (ret == 0 && mode)
+ KWSYS_NAMESPACE::SystemTools::SetPermissions(dir, *mode);
+ return ret;
}
inline int Rmdir(const std::string& dir)
{
@@ -295,9 +301,9 @@ inline void Realpath(const std::string& path, std::string& resolved_path,
# include <fcntl.h>
# include <unistd.h>
-inline int Mkdir(const std::string& dir)
+inline int Mkdir(const std::string& dir, const mode_t* mode)
{
- return mkdir(dir.c_str(), 00777);
+ return mkdir(dir.c_str(), mode ? *mode : 00777);
}
inline int Rmdir(const std::string& dir)
{
@@ -912,16 +918,17 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
std::string::size_type pos = 0;
std::string topdir;
while ((pos = dir.find('/', pos)) != std::string::npos) {
- topdir = dir.substr(0, pos);
+ // all underlying functions use C strings, so temporarily
+ // end the string here
+ dir[pos] = '\0';
- if (Mkdir(topdir) == 0 && mode != nullptr) {
- SystemTools::SetPermissions(topdir, *mode);
- }
+ Mkdir(dir, mode);
+ dir[pos] = '/';
++pos;
}
topdir = dir;
- if (Mkdir(topdir) != 0) {
+ if (Mkdir(topdir, mode) != 0) {
// There is a bug in the Borland Run time library which makes MKDIR
// return EACCES when it should return EEXISTS
// if it is some other error besides directory exists
@@ -933,8 +940,6 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
) {
return false;
}
- } else if (mode != nullptr) {
- SystemTools::SetPermissions(topdir, *mode);
}
return true;
@@ -1010,38 +1015,40 @@ void SystemToolsStatic::ReplaceString(std::string& source, const char* replace,
# define KWSYS_ST_KEY_WOW64_64KEY 0x0100
# endif
-static bool SystemToolsParseRegistryKey(const std::string& key,
- HKEY& primaryKey, std::string& second,
- std::string& valuename)
+static bool hasPrefix(const std::string& s, const char* pattern,
+ std::string::size_type spos)
{
- std::string primary = key;
+ size_t plen = strlen(pattern);
+ if (spos != plen)
+ return false;
+ return s.compare(0, plen, pattern) == 0;
+}
- size_t start = primary.find('\\');
+static bool SystemToolsParseRegistryKey(const std::string& key,
+ HKEY& primaryKey, std::wstring& second,
+ std::string* valuename)
+{
+ size_t start = key.find('\\');
if (start == std::string::npos) {
return false;
}
- size_t valuenamepos = primary.find(';');
- if (valuenamepos != std::string::npos) {
- valuename = primary.substr(valuenamepos + 1);
+ size_t valuenamepos = key.find(';');
+ if (valuenamepos != std::string::npos && valuename) {
+ *valuename = key.substr(valuenamepos + 1);
}
- second = primary.substr(start + 1, valuenamepos - start - 1);
- primary = primary.substr(0, start);
+ second = Encoding::ToWide(key.substr(start + 1, valuenamepos - start - 1));
- if (primary == "HKEY_CURRENT_USER") {
+ if (hasPrefix(key, "HKEY_CURRENT_USER", start)) {
primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG") {
+ } else if (hasPrefix(key, "HKEY_CURRENT_CONFIG", start)) {
primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT") {
+ } else if (hasPrefix(key, "HKEY_CLASSES_ROOT", start)) {
primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE") {
+ } else if (hasPrefix(key, "HKEY_LOCAL_MACHINE", start)) {
primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS") {
+ } else if (hasPrefix(key, "HKEY_USERS", start)) {
primaryKey = HKEY_USERS;
}
@@ -1073,14 +1080,13 @@ bool SystemTools::GetRegistrySubKeys(const std::string& key,
KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- std::string second;
- std::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
+ std::wstring second;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, nullptr)) {
return false;
}
HKEY hKey;
- if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ if (RegOpenKeyExW(primaryKey, second.c_str(), 0,
SystemToolsMakeRegistryMode(KEY_READ, view),
&hKey) != ERROR_SUCCESS) {
return false;
@@ -1120,14 +1126,14 @@ bool SystemTools::ReadRegistryValue(const std::string& key, std::string& value,
{
bool valueset = false;
HKEY primaryKey = HKEY_CURRENT_USER;
- std::string second;
+ std::wstring second;
std::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) {
return false;
}
HKEY hKey;
- if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ if (RegOpenKeyExW(primaryKey, second.c_str(), 0,
SystemToolsMakeRegistryMode(KEY_READ, view),
&hKey) != ERROR_SUCCESS) {
return false;
@@ -1174,16 +1180,16 @@ bool SystemTools::WriteRegistryValue(const std::string& key,
const std::string& value, KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- std::string second;
+ std::wstring second;
std::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) {
return false;
}
HKEY hKey;
DWORD dwDummy;
wchar_t lpClass[] = L"";
- if (RegCreateKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, lpClass,
+ if (RegCreateKeyExW(primaryKey, second.c_str(), 0, lpClass,
REG_OPTION_NON_VOLATILE,
SystemToolsMakeRegistryMode(KEY_WRITE, view), nullptr,
&hKey, &dwDummy) != ERROR_SUCCESS) {
@@ -1218,14 +1224,14 @@ bool SystemTools::WriteRegistryValue(const std::string&, const std::string&,
bool SystemTools::DeleteRegistryValue(const std::string& key, KeyWOW64 view)
{
HKEY primaryKey = HKEY_CURRENT_USER;
- std::string second;
+ std::wstring second;
std::string valuename;
- if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) {
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) {
return false;
}
HKEY hKey;
- if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0,
+ if (RegOpenKeyExW(primaryKey, second.c_str(), 0,
SystemToolsMakeRegistryMode(KEY_WRITE, view),
&hKey) != ERROR_SUCCESS) {
return false;
@@ -1866,7 +1872,7 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len)
size_t middle = max_len / 2;
- n += s.substr(0, middle);
+ n.assign(s, 0, middle);
n += s.substr(s.size() - (max_len - middle));
if (max_len > 2) {
@@ -2064,8 +2070,10 @@ void SystemTools::ConvertToUnixSlashes(std::string& path)
#ifdef HAVE_GETPWNAM
else if (pathCString[0] == '~') {
std::string::size_type idx = path.find_first_of("/\0");
- std::string user = path.substr(1, idx - 1);
- passwd* pw = getpwnam(user.c_str());
+ char oldch = path[idx];
+ path[idx] = '\0';
+ passwd* pw = getpwnam(path.c_str() + 1);
+ path[idx] = oldch;
if (pw) {
path.replace(0, idx, pw->pw_dir);
}
@@ -3131,17 +3139,17 @@ bool SystemTools::SplitProgramPath(const std::string& in_name,
std::string& dir, std::string& file, bool)
{
dir = in_name;
- file = "";
+ file.clear();
SystemTools::ConvertToUnixSlashes(dir);
if (!SystemTools::FileIsDirectory(dir)) {
std::string::size_type slashPos = dir.rfind("/");
if (slashPos != std::string::npos) {
file = dir.substr(slashPos + 1);
- dir = dir.substr(0, slashPos);
+ dir.resize(slashPos);
} else {
file = dir;
- dir = "";
+ dir.clear();
}
}
if (!(dir.empty()) && !SystemTools::FileIsDirectory(dir)) {
@@ -3268,7 +3276,7 @@ void SystemTools::CheckTranslationPath(std::string& path)
// Now convert any path found in the table back to the one desired:
for (auto const& pair : SystemTools::Statics->TranslationMap) {
// We need to check of the path is a substring of the other path
- if (path.find(pair.first) == 0) {
+ if (path.compare(0, pair.first.size(), pair.first) == 0) {
path = path.replace(0, pair.first.size(), pair.second);
}
}
@@ -3540,7 +3548,7 @@ void SystemTools::SplitPath(const std::string& p,
// Expand home directory references if requested.
if (expand_home_dir && !root.empty() && root[0] == '~') {
std::string homedir;
- root = root.substr(0, root.size() - 1);
+ root.resize(root.size() - 1);
if (root.size() == 1) {
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!SystemTools::GetEnv("USERPROFILE", homedir))
@@ -3685,18 +3693,19 @@ std::string SystemTools::GetFilenamePath(const std::string& filename)
SystemTools::ConvertToUnixSlashes(fn);
std::string::size_type slash_pos = fn.rfind("/");
- if (slash_pos != std::string::npos) {
- std::string ret = fn.substr(0, slash_pos);
- if (ret.size() == 2 && ret[1] == ':') {
- return ret + '/';
- }
- if (ret.empty()) {
- return "/";
- }
- return ret;
- } else {
+ if (slash_pos == 0) {
+ return "/";
+ }
+ if (slash_pos == 2 && fn[1] == ':') {
+ // keep the / after a drive letter
+ fn.resize(3);
+ return fn;
+ }
+ if (slash_pos == std::string::npos) {
return "";
}
+ fn.resize(slash_pos);
+ return fn;
}
/**
@@ -3726,7 +3735,8 @@ std::string SystemTools::GetFilenameExtension(const std::string& filename)
std::string name = SystemTools::GetFilenameName(filename);
std::string::size_type dot_pos = name.find('.');
if (dot_pos != std::string::npos) {
- return name.substr(dot_pos);
+ name.erase(0, dot_pos);
+ return name;
} else {
return "";
}
@@ -3741,7 +3751,8 @@ std::string SystemTools::GetFilenameLastExtension(const std::string& filename)
std::string name = SystemTools::GetFilenameName(filename);
std::string::size_type dot_pos = name.rfind('.');
if (dot_pos != std::string::npos) {
- return name.substr(dot_pos);
+ name.erase(0, dot_pos);
+ return name;
} else {
return "";
}
@@ -3757,10 +3768,9 @@ std::string SystemTools::GetFilenameWithoutExtension(
std::string name = SystemTools::GetFilenameName(filename);
std::string::size_type dot_pos = name.find('.');
if (dot_pos != std::string::npos) {
- return name.substr(0, dot_pos);
- } else {
- return name;
+ name.resize(dot_pos);
}
+ return name;
}
/**
@@ -3774,10 +3784,9 @@ std::string SystemTools::GetFilenameWithoutLastExtension(
std::string name = SystemTools::GetFilenameName(filename);
std::string::size_type dot_pos = name.rfind('.');
if (dot_pos != std::string::npos) {
- return name.substr(0, dot_pos);
- } else {
- return name;
+ name.resize(dot_pos);
}
+ return name;
}
bool SystemTools::FileHasSignature(const char* filename, const char* signature,
@@ -3999,7 +4008,8 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
// if the path passed in has quotes around it, first remove the quotes
if (!path.empty() && path[0] == '"' && path.back() == '"') {
- tempPath = path.substr(1, path.length() - 2);
+ tempPath.resize(path.length() - 1);
+ tempPath.erase(0, 1);
}
std::wstring wtempPath = Encoding::ToWide(tempPath);
@@ -4218,8 +4228,8 @@ bool SystemTools::IsSubDirectory(const std::string& cSubdir,
if (subdir[expectedSlashPosition] != '/') {
return false;
}
- std::string s = subdir.substr(0, dir.size());
- return SystemTools::ComparePath(s, dir);
+ subdir.resize(dir.size());
+ return SystemTools::ComparePath(subdir, dir);
}
void SystemTools::Delay(unsigned int msec)
@@ -4580,8 +4590,8 @@ std::string SystemTools::DecodeURL(const std::string& url)
std::string ret;
for (size_t i = 0; i < url.length(); i++) {
if (urlByteRe.find(url.substr(i, 3))) {
- ret +=
- static_cast<char>(strtoul(url.substr(i + 1, 2).c_str(), nullptr, 16));
+ char bytes[] = { url[i + 1], url[i + 2], '\0' };
+ ret += static_cast<char>(strtoul(bytes, nullptr, 16));
i += 2;
} else {
ret += url[i];