From fc8ac9f2ec3541fa03a40544ef651009789a5dfb Mon Sep 17 00:00:00 2001
From: KWSys Upstream <kwrobot@kitware.com>
Date: Fri, 1 Sep 2017 09:55:04 -0400
Subject: [PATCH] KWSys 2017-09-01 (aee0cf59)

Code extracted from:

    https://gitlab.kitware.com/utils/kwsys.git

at commit aee0cf59bbed8c8ccc07fa3d77760024cdca520a (master).

Upstream Shortlog
-----------------
---
 CMakeLists.txt        | 53 +++++++++++++++++++++--------
 Directory.cxx         |  4 +--
 ProcessUNIX.c         |  3 +-
 RegularExpression.cxx |  5 ---
 SystemTools.cxx       | 15 ++------
 testDirectory.cxx     | 79 +++++++++++++++++++++++++++++++++++++++++++
 testSystemTools.cxx   | 26 ++++++++++++++
 7 files changed, 150 insertions(+), 35 deletions(-)
 create mode 100644 testDirectory.cxx

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d5fa9df5..5b8ce00a9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,18 +23,18 @@
 #  KWSYS_SPLIT_OBJECTS_FROM_INTERFACE
 #                    = Instead of creating a single ${KWSYS_NAMESPACE} library
 #                      target, create three separate targets:
+#                        ${KWSYS_NAMESPACE}
+#                          - An INTERFACE library only containing usage
+#                            requirements.
 #                        ${KWSYS_NAMESPACE}_objects
 #                          - An OBJECT library for the built kwsys objects.
-#                        ${KWSYS_NAMESPACE}_interface
-#                          - An INTERFACE library for the usage requirements.
-#                        ${KWSYS_NAMESPACE}
+#                            Note: This is omitted from the install rules
+#                        ${KWSYS_NAMESPACE}_private
 #                          - An INTERFACE library combining both that is
 #                            appropriate for use with PRIVATE linking in
 #                            target_link_libraries. Because of how interface
 #                            properties propagate, this target is not suitable
 #                            for use with PUBLIC or INTERFACE linking.
-#                      Note: only the ${KWSYS_NAMESPACE}_interface library will
-#                      be installed
 #
 #    Example:
 #
@@ -449,6 +449,11 @@ SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES
   COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}"
   )
 
+IF(DEFINED KWSYS_PROCESS_USE_SELECT)
+  GET_PROPERTY(ProcessUNIX_FLAGS SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS)
+  SET_PROPERTY(SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS "${ProcessUNIX_FLAGS} -DKWSYSPE_USE_SELECT=${KWSYSPE_USE_SELECT}")
+ENDIF()
+
 IF(KWSYS_USE_DynamicLoader)
   GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
   IF(KWSYS_SUPPORTS_SHARED_LIBS)
@@ -815,9 +820,10 @@ ENDFOREACH()
 # Add the library with the configured name and list of sources.
 IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
   IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE)
-    SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}_interface)
+    SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE})
     SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}_objects)
-    SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE})
+    SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}_private)
+    SET(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_INTERFACE} ${KWSYS_TARGET_LINK})
     SET(KWSYS_LINK_DEPENDENCY INTERFACE)
     ADD_LIBRARY(${KWSYS_TARGET_OBJECT} OBJECT
       ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
@@ -835,6 +841,7 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
     SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE})
     SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE})
     SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE})
+    set(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_LINK})
     SET(KWSYS_LINK_DEPENDENCY PUBLIC)
     ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE}
       ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
@@ -886,21 +893,27 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
   # Set up include usage requirement
   IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
     TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
-      ${CMAKE_CURRENT_BINARY_DIR})
+      $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+    IF(KWSYS_INSTALL_INCLUDE_DIR)
+      TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
+        $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
+    ENDIF()
   ENDIF()
 
   # Create an install target for the library.
   IF(KWSYS_INSTALL_LIBRARY_RULE)
-    INSTALL(TARGETS ${KWSYS_TARGET_INTERFACE} ${KWSYS_INSTALL_LIBRARY_RULE})
+    INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE})
   ENDIF()
 ENDIF()
 
 # Add a C-only library if requested.
 IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
  IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE)
-    SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c_interface)
-    SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c_object)
-    SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c)
+    SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c)
+    SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c_objects)
+    SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c_private)
+    SET(KWSYS_TARGET_C_INSTALL
+      ${KWSYS_TARGET_C_INTERFACE} ${KWSYS_TARGET_C_LINK})
     SET(KWSYS_LINK_DEPENDENCY INTERFACE)
     ADD_LIBRARY(${KWSYS_TARGET_C_OBJECT} OBJECT ${KWSYS_C_SRCS})
     IF(KWSYS_BUILD_SHARED)
@@ -917,6 +930,7 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
     SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c)
     SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c)
     SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c)
+    SET(KWSYS_TARGET_C_INSTALL ${KWSYS_TARGET_C_LINK})
     SET(KWSYS_LINK_DEPENDENCY PUBLIC)
     ADD_LIBRARY(${KWSYS_TARGET_C_INTERFACE} ${KWSYS_LIBRARY_TYPE}
       ${KWSYS_C_SRCS})
@@ -930,10 +944,20 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
       ${KWSYS_PROPERTIES_C})
   ENDIF()
 
+  # Set up include usage requirement
+  IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
+    TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
+      $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+    IF(KWSYS_INSTALL_INCLUDE_DIR)
+      TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
+        $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
+    ENDIF()
+  ENDIF()
+
   # Create an install target for the library.
   IF(KWSYS_INSTALL_LIBRARY_RULE)
-    INSTALL(TARGETS ${KWSYS_TARGET_C_INTERFACE} ${KWSYS_INSTALL_LIBRARY_RULE})
-   ENDIF()
+    INSTALL(TARGETS ${KWSYS_TARGET_C_INSTALL})
+  ENDIF()
 ENDIF()
 
 # For building kwsys itself, we use a macro defined on the command
@@ -1008,6 +1032,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
       testSystemTools
       testCommandLineArguments
       testCommandLineArguments1
+      testDirectory
       )
     IF(KWSYS_STL_HAS_WSTRING)
       SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
diff --git a/Directory.cxx b/Directory.cxx
index 5141d4519..69068aaf8 100644
--- a/Directory.cxx
+++ b/Directory.cxx
@@ -118,8 +118,8 @@ bool Directory::Load(const std::string& name)
   struct _wfinddata_t data; // data of current file
 
   // Now put them into the file array
-  srchHandle =
-    _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+  srchHandle = _wfindfirst_func(
+    (wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
   delete[] buf;
 
   if (srchHandle == -1) {
diff --git a/ProcessUNIX.c b/ProcessUNIX.c
index 9ebcfce59..3b32ca7d0 100644
--- a/ProcessUNIX.c
+++ b/ProcessUNIX.c
@@ -99,7 +99,8 @@ static inline void kwsysProcess_usleep(unsigned int msec)
  * pipes' file handles to be non-blocking and just poll them directly
  * without select().
  */
-#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__)
+#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) &&            \
+  !defined(KWSYSPE_USE_SELECT)
 #define KWSYSPE_USE_SELECT 1
 #endif
 
diff --git a/RegularExpression.cxx b/RegularExpression.cxx
index 6d7f83295..26e84e04e 100644
--- a/RegularExpression.cxx
+++ b/RegularExpression.cxx
@@ -258,11 +258,6 @@ const unsigned char MAGIC = 0234;
 
 #define UCHARAT(p) (reinterpret_cast<const unsigned char*>(p))[0]
 
-#define FAIL(m)                                                               \
-  {                                                                           \
-    regerror(m);                                                              \
-    return (0);                                                               \
-  }
 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
 #define META "^$.[()|?+*\\"
 
diff --git a/SystemTools.cxx b/SystemTools.cxx
index c5bbd416a..560c19c02 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -847,6 +847,8 @@ void SystemTools::ReplaceString(std::string& source, const char* replace,
   free(orig);
 }
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
 #if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
 #define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
 #define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
@@ -855,7 +857,6 @@ void SystemTools::ReplaceString(std::string& source, const char* replace,
 #define KWSYS_ST_KEY_WOW64_64KEY 0x0100
 #endif
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
 static bool SystemToolsParseRegistryKey(const std::string& key,
                                         HKEY& primaryKey, std::string& second,
                                         std::string& valuename)
@@ -2268,11 +2269,7 @@ bool SystemTools::CopyADirectory(const std::string& source,
                                  const std::string& destination, bool always)
 {
   Directory dir;
-#ifdef _WIN32
-  dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
   dir.Load(source);
-#endif
   size_t fileNum;
   if (!SystemTools::MakeDirectory(destination)) {
     return false;
@@ -2625,11 +2622,7 @@ bool SystemTools::RemoveADirectory(const std::string& source)
   }
 
   Directory dir;
-#ifdef _WIN32
-  dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
   dir.Load(source);
-#endif
   size_t fileNum;
   for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
     if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") &&
@@ -3796,11 +3789,7 @@ std::string SystemTools::GetFilenamePath(const std::string& filename)
  */
 std::string SystemTools::GetFilenameName(const std::string& filename)
 {
-#if defined(_WIN32)
   std::string::size_type slash_pos = filename.find_last_of("/\\");
-#else
-  std::string::size_type slash_pos = filename.rfind('/');
-#endif
   if (slash_pos != std::string::npos) {
     return filename.substr(slash_pos + 1);
   } else {
diff --git a/testDirectory.cxx b/testDirectory.cxx
new file mode 100644
index 000000000..983f2c631
--- /dev/null
+++ b/testDirectory.cxx
@@ -0,0 +1,79 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Directory.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(SystemTools.hxx)
+
+// Work-around CMake dependency scanning limitation.  This must
+// duplicate the above list of headers.
+#if 0
+#include "Directory.hxx.in"
+#include "Encoding.hxx.in"
+#include "SystemTools.hxx.in"
+#endif
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include <testSystemTools.h>
+
+int _doLongPathTest()
+{
+  using namespace kwsys;
+  static const int LONG_PATH_THRESHOLD = 512;
+  int res = 0;
+  std::string topdir(TEST_SYSTEMTOOLS_BINARY_DIR "/directory_testing/");
+  std::stringstream testpathstrm;
+  std::string testdirpath;
+  std::string extendedtestdirpath;
+
+  testpathstrm << topdir;
+  size_t pathlen = testpathstrm.str().length();
+  testpathstrm.seekp(0, std::ios_base::end);
+  while (pathlen < LONG_PATH_THRESHOLD) {
+    testpathstrm << "0123456789/";
+    pathlen = testpathstrm.str().length();
+  }
+
+  testdirpath = testpathstrm.str();
+#ifdef _WIN32
+  extendedtestdirpath =
+    Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(testdirpath));
+#else
+  extendedtestdirpath = testdirpath;
+#endif
+
+  if (SystemTools::MakeDirectory(extendedtestdirpath)) {
+    std::ofstream testfile1(
+      (extendedtestdirpath + "longfilepathtest1.txt").c_str());
+    std::ofstream testfile2(
+      (extendedtestdirpath + "longfilepathtest2.txt").c_str());
+    testfile1 << "foo";
+    testfile2 << "bar";
+    testfile1.close();
+    testfile2.close();
+
+    Directory testdir;
+    // Set res to failure if the directory doesn't load
+    res += !testdir.Load(testdirpath);
+    // Increment res failure if the directory appears empty
+    res += testdir.GetNumberOfFiles() == 0;
+    // Increment res failures if the path has changed from
+    // what was provided.
+    res += testdirpath != testdir.GetPath();
+
+    SystemTools::RemoveADirectory(topdir);
+  } else {
+    std::cerr << "Failed to create directory with long path: "
+              << extendedtestdirpath << std::endl;
+    res += 1;
+  }
+  return res;
+}
+
+int testDirectory(int, char* [])
+{
+  return _doLongPathTest();
+}
diff --git a/testSystemTools.cxx b/testSystemTools.cxx
index e6fbf6cda..1871f5dd0 100644
--- a/testSystemTools.cxx
+++ b/testSystemTools.cxx
@@ -758,6 +758,30 @@ static bool CheckGetPath()
   return res;
 }
 
+static bool CheckGetFilenameName()
+{
+  const char* windowsFilepath = "C:\\somewhere\\something";
+  const char* unixFilepath = "/somewhere/something";
+
+  std::string expectedFilename = "something";
+
+  bool res = true;
+  std::string filename = kwsys::SystemTools::GetFilenameName(windowsFilepath);
+  if (filename != expectedFilename) {
+    std::cerr << "GetFilenameName(" << windowsFilepath << ") yielded "
+              << filename << " instead of " << expectedFilename << std::endl;
+    res = false;
+  }
+
+  filename = kwsys::SystemTools::GetFilenameName(unixFilepath);
+  if (filename != expectedFilename) {
+    std::cerr << "GetFilenameName(" << unixFilepath << ") yielded " << filename
+              << " instead of " << expectedFilename << std::endl;
+    res = false;
+  }
+  return res;
+}
+
 static bool CheckFind()
 {
   bool res = true;
@@ -875,5 +899,7 @@ int testSystemTools(int, char* [])
 
   res &= CheckGetLineFromStream();
 
+  res &= CheckGetFilenameName();
+
   return res ? 0 : 1;
 }
-- 
GitLab