From 5647e6e254f82a81997cd3913f872b06fe761f1e Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Wed, 21 Feb 2007 21:24:17 -0500 Subject: [PATCH] ENH: fix parens in the path with spaces in the path --- Source/CMakeLists.txt | 23 ++++++-- Source/cmLocalGenerator.cxx | 10 +++- Source/cmLocalUnixMakefileGenerator3.cxx | 4 +- Source/cmSystemTools.cxx | 58 +++++++++++++++++++ Source/cmSystemTools.h | 6 +- Source/kwsys/SystemTools.cxx | 19 +----- Tests/SubDirSpaces/CMakeLists.txt | 4 +- .../Some(x86) Sources/CMakeLists.txt | 1 + Tests/SubDirSpaces/Some(x86) Sources/test.c | 3 + .../ThirdSubDir/testfromauxsubdir.c | 3 +- 10 files changed, 103 insertions(+), 28 deletions(-) create mode 100644 Tests/SubDirSpaces/Some(x86) Sources/CMakeLists.txt create mode 100644 Tests/SubDirSpaces/Some(x86) Sources/test.c diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8b75c850e..f452ceb68 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1011,12 +1011,24 @@ IF(BUILD_TESTING) --test-command testIOS ) ENDIF(NOT CMAKE_TEST_DIFFERENT_GENERATOR) - + SET(MAKE_IS_GNU ) + IF(${CMAKE_TEST_MAKEPROGRAM} MATCHES make) + EXECUTE_PROCESS(COMMAND ${CMAKE_TEST_MAKEPROGRAM} --version + RESULT_VARIABLE res OUTPUT_VARIABLE out + ERROR_QUIET + OUTPUT_QUIET) + IF("${res}" EQUAL 0) + IF("${out}" MATCHES "GNU") + SET(MAKE_IS_GNU 1) + ENDIF("${out}" MATCHES "GNU") + ENDIF("${res}" EQUAL 0) + ENDIF(${CMAKE_TEST_MAKEPROGRAM} MATCHES make) # only add this test on platforms that support it # some old versions of make simply cannot handle spaces in paths - IF ("${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR - "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|Xcode") + IF (MAKE_IS_GNU OR + "${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR + "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|XCode") ADD_TEST(SubDirSpaces ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/SubDirSpaces" @@ -1030,8 +1042,9 @@ IF(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/SubDirSpaces/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj" ) - ENDIF ("${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR - "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|Xcode") + ENDIF (MAKE_IS_GNU OR + "${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR + "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|XCode") IF (WIN32) ADD_TEST(SubDir ${CMAKE_CTEST_COMMAND} diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4ab899ab2..cacce6862 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1023,7 +1023,7 @@ cmLocalGenerator::ConvertToOutputForExisting(const char* p) { if(!cmSystemTools::GetShortPath(ret.c_str(), ret)) { - ret = this->Convert(p,START_OUTPUT,MAKEFILE,true); + ret = this->Convert(p,START_OUTPUT,SHELL,true); } } } @@ -2088,6 +2088,14 @@ std::string cmLocalGenerator::Convert(const char* source, result[0] = '/'; } } + // if this is unix then we need to escape () in the shell +#if !defined(WIN32) || defined(CYGWIN) + forceOn = true; +#endif + if(forceOn ) + { + result = cmSystemTools::EscapeForUnixShell(result); + } } return result; } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index affcf525b..d399a896a 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1743,7 +1743,7 @@ cmLocalUnixMakefileGenerator3 // Call make on the given file. std::string cmd; cmd += "$(MAKE) -f "; - cmd += this->Convert(makefile,NONE,MAKEFILE); + cmd += this->Convert(makefile,NONE,SHELL); cmd += " "; // Passg down verbosity level. @@ -1765,7 +1765,7 @@ cmLocalUnixMakefileGenerator3 // Add the target. if (tgt && tgt[0] != '\0') { - std::string tgt2 = this->Convert(tgt,HOME_OUTPUT,MAKEFILE); + std::string tgt2 = this->Convert(tgt,HOME_OUTPUT,SHELL); tgt2 = this->ConvertToMakeTarget(tgt2.c_str()); cmd += tgt2; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 7af78fb79..942f59333 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1341,6 +1341,64 @@ std::string cmSystemTools::ConvertToOutputPath(const char* path) #endif } +std::string cmSystemTools::EscapeForUnixShell(std::string& result) +{ + // For UNIX Shell paths we need to escape () in the path + if(result.find_first_of("()") != result.npos) + { + std::string newResult = ""; + char lastch = 1; + bool inDollarVariable = false; + for(const char* ch = result.c_str(); *ch != '\0'; ++ch) + { + // if it is already escaped then don't try to escape it again + if((*ch == ' ' || *ch == '(' || *ch == ')') && lastch != '\\') + { + if(*ch == '(' && lastch == '$') + { + inDollarVariable = true; + } + // if we are in a $(..... and we get a ) then do not escape + // the ) and but set inDollarVariable to false + else if(*ch == ')' && inDollarVariable) + { + inDollarVariable = false; + } + else + { + newResult += '\\'; + } + } + newResult += *ch; + lastch = *ch; + } + return newResult; + } + return result; +} + +std::string cmSystemTools::ConvertToShellPath(const char* path) +{ + bool useUnix = false; // assume windows +#if defined(_WIN32) && !defined(__CYGWIN__) + // if windows and force paths but not cygwin useUnix is on + if(s_ForceUnixPaths) + { + useUnix = true; + } +#else + // if not win32 and maybe cygwin then unix is true + useUnix = true; +#endif + // if unix we need to call EscapeForUnixShell as well + if(useUnix) + { + std::string result = cmSystemTools::ConvertToUnixOutputPath(path); + return cmSystemTools::EscapeForUnixShell(result); + } + return cmSystemTools::ConvertToWindowsOutputPath(path); +} + std::string cmSystemTools::ConvertToRunCommandPath(const char* path) { #if defined(_WIN32) && !defined(__CYGWIN__) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 6165d9803..f42ac17a1 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -293,10 +293,12 @@ public: // be used when RunCommand is called from cmake, because the // running cmake needs paths to be in its format static std::string ConvertToRunCommandPath(const char* path); - + // convert to a shell path + static std::string ConvertToShellPath(const char* path); //! Check if the first string ends with the second one. static bool StringEndsWith(const char* str1, const char* str2); - + // escape for unix shells + static std::string EscapeForUnixShell(std::string& result); static bool CreateSymlink(const char* origName, const char* newName); /** compute the relative path from local to remote. local must diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index f75a39d03..0d6700a11 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -1414,7 +1414,7 @@ kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path) ret.erase(pos, 1); } // escape spaces and () in the path - if(ret.find_first_of(" ()") != kwsys_stl::string::npos) + if(ret.find_first_of(" ") != kwsys_stl::string::npos) { kwsys_stl::string result = ""; char lastch = 1; @@ -1422,22 +1422,9 @@ kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path) for(const char* ch = ret.c_str(); *ch != '\0'; ++ch) { // if it is already escaped then don't try to escape it again - if((*ch == ' ' || *ch == '(' || *ch == ')') && lastch != '\\') + if((*ch == ' ') && lastch != '\\') { - if(*ch == '(' && lastch == '$') - { - inDollarVariable = true; - } - // if we are in a $(..... and we get a ) then do not escape - // the ) and but set inDollarVariable to false - else if(*ch == ')' && inDollarVariable) - { - inDollarVariable = false; - } - else - { - result += '\\'; - } + result += '\\'; } result += *ch; lastch = *ch; diff --git a/Tests/SubDirSpaces/CMakeLists.txt b/Tests/SubDirSpaces/CMakeLists.txt index 3535070e4..29f4f64fb 100644 --- a/Tests/SubDirSpaces/CMakeLists.txt +++ b/Tests/SubDirSpaces/CMakeLists.txt @@ -1,5 +1,5 @@ PROJECT(SUBDIR) -SUBDIRS("Executable Sources" EXCLUDE_FROM_ALL "Some Examples") +SUBDIRS("Executable Sources" "Some(x86) Sources" EXCLUDE_FROM_ALL "Some Examples") WRITE_FILE(${SUBDIR_BINARY_DIR}/ShouldBeHere "This file should exist.") #WATCOM WMAKE does not support + in the name of a file! IF(WATCOM) @@ -41,3 +41,5 @@ ELSE(WATCOM) vcl_algorithm+vcl_pair+double.foo.c) ENDIF(WATCOM) ADD_EXECUTABLE(TestWithAuxSourceDir ${SOURCES}) +target_link_libraries(TestWithAuxSourceDir testOddPath) + diff --git a/Tests/SubDirSpaces/Some(x86) Sources/CMakeLists.txt b/Tests/SubDirSpaces/Some(x86) Sources/CMakeLists.txt new file mode 100644 index 000000000..cfba9169c --- /dev/null +++ b/Tests/SubDirSpaces/Some(x86) Sources/CMakeLists.txt @@ -0,0 +1 @@ +add_library(testOddPath test.c) diff --git a/Tests/SubDirSpaces/Some(x86) Sources/test.c b/Tests/SubDirSpaces/Some(x86) Sources/test.c new file mode 100644 index 000000000..66568d4c2 --- /dev/null +++ b/Tests/SubDirSpaces/Some(x86) Sources/test.c @@ -0,0 +1,3 @@ +void testOdd() +{ +} diff --git a/Tests/SubDirSpaces/ThirdSubDir/testfromauxsubdir.c b/Tests/SubDirSpaces/ThirdSubDir/testfromauxsubdir.c index d1620845f..b6d6b8650 100644 --- a/Tests/SubDirSpaces/ThirdSubDir/testfromauxsubdir.c +++ b/Tests/SubDirSpaces/ThirdSubDir/testfromauxsubdir.c @@ -4,11 +4,12 @@ void secondone(); void pair_stuff(); void pair_p_stuff(); void vcl_stuff(); - +void testOdd(); int main() { printf("Hello from subdirectory\n"); secondone(); + testOdd(); pair_stuff(); pair_p_stuff(); vcl_stuff();