From dc3fd5c26727ae81b57c4fa2b5559b6c1e36840c Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 23 Jun 2003 08:58:58 -0400 Subject: ENH: Merged use of kwsys library. --- CMakeLists.txt | 9 + Source/CMakeLists.txt | 3 +- Source/CursesDialog/cmCursesPathWidget.cxx | 1 - Source/cmAuxSourceDirectoryCommand.cxx | 5 +- Source/cmDirectory.cxx | 121 - Source/cmDirectory.h | 58 - Source/cmMakeDirectoryCommand.cxx | 1 - Source/cmMakefile.cxx | 1 - Source/cmSystemTools.cxx | 2440 ++++---------------- Source/cmSystemTools.h | 215 +- Source/cmTryCompileCommand.cxx | 4 +- Tests/Complex/Executable/CMakeLists.txt | 5 +- Tests/ComplexOneConfig/Executable/CMakeLists.txt | 5 +- .../ComplexRelativePaths/Executable/CMakeLists.txt | 5 +- bootstrap | 67 +- 15 files changed, 511 insertions(+), 2429 deletions(-) delete mode 100644 Source/cmDirectory.cxx delete mode 100644 Source/cmDirectory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 58b0212..63f67bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,15 @@ IF(CMAKE_SYSTEM MATCHES "OSF1-V.*") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local -no_implicit_include ") ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) ENDIF(CMAKE_SYSTEM MATCHES "OSF1-V.*") + +#----------------------------------------------------------------------------- +# Create the kwsys library for CMake. +SET(KWSYS_NAMESPACE cmsys) +SET(KWSYS_USE_SystemTools 1) +SET(KWSYS_USE_Directory 1) +SET(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source) +SUBDIRS(Source/kwsys) + SUBDIRS(Source Modules Templates Utilities) ENABLE_TESTING() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a707b55..c517353 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -8,7 +8,6 @@ cmMakefile.cxx cmRegularExpression.cxx cmSourceFile.cxx cmSystemTools.cxx -cmDirectory.cxx cmDocumentation.cxx cmDynamicLoader.cxx cmCommands.cxx @@ -30,7 +29,6 @@ cmRegularExpression.h cmSourceFile.h cmSystemTools.h cmDynamicLoader.h -cmDirectory.h cmCommands.h cmTarget.h cmCustomCommand.h @@ -96,6 +94,7 @@ ENDIF (WIN32) # create a library used by the command line and the GUI ADD_LIBRARY(CMakeLib ${SRCS}) +TARGET_LINK_LIBRARIES(CMakeLib cmsys) # always link in the library # the library is found here diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx index 5042838..391e413 100644 --- a/Source/CursesDialog/cmCursesPathWidget.cxx +++ b/Source/CursesDialog/cmCursesPathWidget.cxx @@ -18,7 +18,6 @@ #include "cmCursesMainForm.h" #include "cmSystemTools.h" -#include "cmDirectory.h" cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left, int top) : diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 0486253..e8d11e2 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -15,9 +15,10 @@ =========================================================================*/ #include "cmAuxSourceDirectoryCommand.h" -#include "cmDirectory.h" #include "cmSourceFile.h" +#include + // cmAuxSourceDirectoryCommand bool cmAuxSourceDirectoryCommand::InitialPass(std::vector const& args) { @@ -42,7 +43,7 @@ bool cmAuxSourceDirectoryCommand::InitialPass(std::vector const& ar } // Load all the files in the directory - cmDirectory dir; + cmsys::Directory dir; if(dir.Load(tdir.c_str())) { size_t numfiles = dir.GetNumberOfFiles(); diff --git a/Source/cmDirectory.cxx b/Source/cmDirectory.cxx deleted file mode 100644 index 583e8ef..0000000 --- a/Source/cmDirectory.cxx +++ /dev/null @@ -1,121 +0,0 @@ -/*========================================================================= - - Program: CMake - Cross-Platform Makefile Generator - Module: $RCSfile$ - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. - See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#include "cmDirectory.h" - - - -// First microsoft compilers - -#ifdef _MSC_VER -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * - */ -bool -cmDirectory -::Load(const char* name) -{ - char* buf; - size_t n = strlen(name); - if ( name[n - 1] == '/' ) - { - buf = new char[n + 1 + 1]; - sprintf(buf, "%s*", name); - } - else - { - buf = new char[n + 2 + 1]; - sprintf(buf, "%s/*", name); - } - struct _finddata_t data; // data of current file - - // Now put them into the file array - size_t srchHandle = _findfirst(buf, &data); - delete [] buf; - - if ( srchHandle == -1 ) - { - return 0; - } - - // Loop through names - do - { - m_Files.push_back(data.name); - } - while ( _findnext(srchHandle, &data) != -1 ); - m_Path = name; - return _findclose(srchHandle) != -1; -} - -#else - -// Now the POSIX style directory access - -#include -#include - -/** - * - */ -bool -cmDirectory -::Load(const char* name) -{ - DIR* dir = opendir(name); - - if (!dir) - { - return 0; - } - - for (dirent* d = readdir(dir); d; d = readdir(dir) ) - { - m_Files.push_back(d->d_name); - } - m_Path = name; - closedir(dir); - return 1; -} - -#endif - - -/** - * - */ -const char* -cmDirectory -::GetFile(size_t dindex) -{ - if ( dindex >= m_Files.size() ) - { - cmSystemTools::Error("Bad index for GetFile on cmDirectory\n", 0); - return 0; - } - return m_Files[dindex].c_str(); -} - diff --git a/Source/cmDirectory.h b/Source/cmDirectory.h deleted file mode 100644 index c049699..0000000 --- a/Source/cmDirectory.h +++ /dev/null @@ -1,58 +0,0 @@ -/*========================================================================= - - Program: CMake - Cross-Platform Makefile Generator - Module: $RCSfile$ - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. - See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef __cmDirectory_h -#define __cmDirectory_h - -#include "cmStandardIncludes.h" -#include "cmSystemTools.h" - -/** \class cmDirectory - * \brief Portable directory/filename traversal. - * - * cmDirectory provides a portable way of finding the names of the files - * in a system directory. - * - * cmDirectory currently works with Windows and Unix operating systems. - */ - -class cmDirectory -{ -public: - /** - * Load the specified directory and load the names of the files - * in that directory. 0 is returned if the directory can not be - * opened, 1 if it is opened. - */ - bool Load(const char* dir); - - /** - * Return the number of files in the current directory. - */ - size_t GetNumberOfFiles() { return m_Files.size();} - - /** - * Return the file at the given index, the indexing is 0 based - */ - const char* GetFile(size_t ); - -private: - std::vector m_Files; // Array of Files - std::string m_Path; // Path to Open'ed directory - -}; // End Class: cmDirectory - -#endif diff --git a/Source/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx index 7c17e4d..b1a2821 100644 --- a/Source/cmMakeDirectoryCommand.cxx +++ b/Source/cmMakeDirectoryCommand.cxx @@ -15,7 +15,6 @@ =========================================================================*/ #include "cmMakeDirectoryCommand.h" -#include "cmDirectory.h" // cmMakeDirectoryCommand bool cmMakeDirectoryCommand::InitialPass(std::vector const& args) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 9246b89..49a7fb8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -18,7 +18,6 @@ #include "cmCommand.h" #include "cmStandardIncludes.h" #include "cmSourceFile.h" -#include "cmDirectory.h" #include "cmSystemTools.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index b729333..38c8648 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -16,13 +16,12 @@ =========================================================================*/ #include "cmSystemTools.h" #include -#include #include "cmRegularExpression.h" #include -#include "cmDirectory.h" #include #include +#include // support for realpath call #ifndef _WIN32 @@ -37,95 +36,13 @@ #include #include #define _unlink unlink -inline int Mkdir(const char* dir) -{ - return _mkdir(dir); -} -inline const char* Getcwd(char* buf, unsigned int len) -{ - return _getcwd(buf, len); -} -inline int Chdir(const char* dir) -{ - #if defined(__BORLANDC__) - return chdir(dir); - #else - return _chdir(dir); - #endif -} #else #include #include #include -inline int Mkdir(const char* dir) -{ - return mkdir(dir, 00777); -} -inline const char* Getcwd(char* buf, unsigned int len) -{ - return getcwd(buf, len); -} -inline int Chdir(const char* dir) -{ - return chdir(dir); -} #endif -/* Implement floattime() for various platforms */ -// Taken from Python 2.1.3 - -#if defined( _WIN32 ) && !defined( __CYGWIN__ ) -# include -# define HAVE_FTIME -# if defined( __BORLANDC__) -# define FTIME ftime -# define TIMEB timeb -# else // Visual studio? -# define FTIME _ftime -# define TIMEB _timeb -# endif -#elif defined( __CYGWIN__ ) || defined( __linux__ ) -# include -# include -# define HAVE_GETTIMEOFDAY -#endif - -double -cmSystemTools::GetTime(void) -{ - /* There are three ways to get the time: - (1) gettimeofday() -- resolution in microseconds - (2) ftime() -- resolution in milliseconds - (3) time() -- resolution in seconds - In all cases the return value is a float in seconds. - Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may - fail, so we fall back on ftime() or time(). - Note: clock resolution does not imply clock accuracy! */ -#ifdef HAVE_GETTIMEOFDAY - { - struct timeval t; -#ifdef GETTIMEOFDAY_NO_TZ - if (gettimeofday(&t) == 0) - return (double)t.tv_sec + t.tv_usec*0.000001; -#else /* !GETTIMEOFDAY_NO_TZ */ - if (gettimeofday(&t, (struct timezone *)NULL) == 0) - return (double)t.tv_sec + t.tv_usec*0.000001; -#endif /* !GETTIMEOFDAY_NO_TZ */ - } -#endif /* !HAVE_GETTIMEOFDAY */ - { -#if defined(HAVE_FTIME) - struct TIMEB t; - FTIME(&t); - return (double)t.time + (double)t.millitm * (double)0.001; -#else /* !HAVE_FTIME */ - time_t secs; - time(&secs); - return (double)secs; -#endif /* !HAVE_FTIME */ - } -} bool cmSystemTools::s_RunCommandHideConsole = false; bool cmSystemTools::s_DisableRunCommandOutput = false; bool cmSystemTools::s_ErrorOccured = false; @@ -148,1909 +65,550 @@ const char* cmSystemTools::GetWindows9xComspecSubstitute() void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, bool&, void*); void* cmSystemTools::s_ErrorCallbackClientData = 0; -// adds the elements of the env variable path to the arg passed in -void cmSystemTools::GetPath(std::vector& path) -{ +// replace replace with with as many times as it shows up in source. +// write the result into source. #if defined(_WIN32) && !defined(__CYGWIN__) - const char* pathSep = ";"; -#else - const char* pathSep = ":"; -#endif - std::string pathEnv = getenv("PATH"); - // A hack to make the below algorithm work. - if(pathEnv[pathEnv.length()-1] != ':') - { - pathEnv += pathSep; - } - std::string::size_type start =0; - bool done = false; - while(!done) +void cmSystemTools::ExpandRegistryValues(std::string& source) +{ + // Regular expression to match anything inside [...] that begins in HKEY. + // Note that there is a special rule for regular expressions to match a + // close square-bracket inside a list delimited by square brackets. + // The "[^]]" part of this expression will match any character except + // a close square-bracket. The ']' character must be the first in the + // list of characters inside the [^...] block of the expression. + cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]"); + + // check for black line or comment + while (regEntry.find(source)) { - std::string::size_type endpos = pathEnv.find(pathSep, start); - if(endpos != std::string::npos) + // the arguments are the second match + std::string key = regEntry.match(1); + std::string val; + if (ReadRegistryValue(key.c_str(), val)) { - path.push_back(pathEnv.substr(start, endpos-start)); - start = endpos+1; + std::string reg = "["; + reg += key + "]"; + cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str()); } else { - done = true; + std::string reg = "["; + reg += key + "]"; + cmSystemTools::ReplaceString(source, reg.c_str(), "/registry"); } } - for(std::vector::iterator i = path.begin(); - i != path.end(); ++i) - { - cmSystemTools::ConvertToUnixSlashes(*i); - } } - - -const char* cmSystemTools::GetExecutableExtension() -{ -#if defined(_WIN32) || defined(__CYGWIN__) - return ".exe"; #else - return ""; -#endif +void cmSystemTools::ExpandRegistryValues(std::string&) +{ } +#endif - -bool cmSystemTools::MakeDirectory(const char* path) +std::string cmSystemTools::EscapeQuotes(const char* str) { - if(cmSystemTools::FileExists(path)) - { - return true; - } - std::string dir = path; - if(dir.size() == 0) - { - return false; - } - cmSystemTools::ConvertToUnixSlashes(dir); - - std::string::size_type pos = dir.find(':'); - if(pos == std::string::npos) - { - pos = 0; - } - std::string topdir; - while((pos = dir.find('/', pos)) != std::string::npos) - { - topdir = dir.substr(0, pos); - Mkdir(topdir.c_str()); - pos++; - } - if(dir[dir.size()-1] == '/') - { - topdir = dir.substr(0, dir.size()); - } - else - { - topdir = dir; - } - if(Mkdir(topdir.c_str()) != 0) + std::string result = ""; + for(const char* ch = str; *ch != '\0'; ++ch) { - // 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 - // then return false - if( (errno != EEXIST) -#ifdef __BORLANDC__ - && (errno != EACCES) -#endif - ) + if(*ch == '"') { - cmSystemTools::Error("Failed to create directory:", path); - return false; + result += '\\'; } + result += *ch; } - return true; + return result; } - -// replace replace with with as many times as it shows up in source. -// write the result into source. -void cmSystemTools::ReplaceString(std::string& source, - const char* replace, - const char* with) +std::string cmSystemTools::EscapeSpaces(const char* str) { - // get out quick if string is not found - std::string::size_type start = source.find(replace); - if(start == std::string::npos) +#if defined(_WIN32) && !defined(__CYGWIN__) + std::string result; + + // if there are spaces + std::string temp = str; + if (temp.find(" ") != std::string::npos && + temp.find("\"")==std::string::npos) { - return; + result = "\""; + result += str; + result += "\""; + return result; } - std::string rest; - std::string::size_type lengthReplace = strlen(replace); - std::string::size_type lengthWith = strlen(with); - while(start != std::string::npos) + return str; +#else + std::string result = ""; + for(const char* ch = str; *ch != '\0'; ++ch) { - rest = source.substr(start+lengthReplace); - source = source.substr(0, start); - source += with; - source += rest; - start = source.find(replace, start + lengthWith ); + if(*ch == ' ') + { + result += '\\'; + } + result += *ch; } + return result; +#endif } -// Read a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will return the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will return the data of the "Root" value of the key - -#if defined(_WIN32) && !defined(__CYGWIN__) -bool cmSystemTools::ReadRegistryValue(const char *key, std::string &value) +std::string cmSystemTools::RemoveEscapes(const char* s) { - - std::string primary = key; - std::string second; - std::string valuename; - - size_t start = primary.find("\\"); - if (start == std::string::npos) - { - return false; - } - - size_t valuenamepos = primary.find(";"); - if (valuenamepos != std::string::npos) + std::string result = ""; + for(const char* ch = s; *ch; ++ch) { - valuename = primary.substr(valuenamepos+1); + if(*ch == '\\' && *(ch+1) != ';') + { + ++ch; + switch (*ch) + { + case '\\': result.insert(result.end(), '\\'); break; + case '"': result.insert(result.end(), '"'); break; + case ' ': result.insert(result.end(), ' '); break; + case 't': result.insert(result.end(), '\t'); break; + case 'n': result.insert(result.end(), '\n'); break; + case 'r': result.insert(result.end(), '\r'); break; + case '0': result.insert(result.end(), '\0'); break; + case '\0': + { + cmSystemTools::Error("Trailing backslash in argument:\n", s); + return result; + } + default: + { + std::string chStr(1, *ch); + cmSystemTools::Error("Invalid escape sequence \\", chStr.c_str(), + "\nin argument ", s); + } + } + } + else + { + result.insert(result.end(), *ch); + } } + return result; +} - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey; - if (primary == "HKEY_CURRENT_USER") +void cmSystemTools::Error(const char* m1, const char* m2, + const char* m3, const char* m4) +{ + std::string message = "CMake Error: "; + if(m1) { - primaryKey = HKEY_CURRENT_USER; + message += m1; } - if (primary == "HKEY_CURRENT_CONFIG") + if(m2) { - primaryKey = HKEY_CURRENT_CONFIG; + message += m2; } - if (primary == "HKEY_CLASSES_ROOT") + if(m3) { - primaryKey = HKEY_CLASSES_ROOT; + message += m3; } - if (primary == "HKEY_LOCAL_MACHINE") + if(m4) { - primaryKey = HKEY_LOCAL_MACHINE; + message += m4; } - if (primary == "HKEY_USERS") + cmSystemTools::s_ErrorOccured = true; + cmSystemTools::Message(message.c_str(),"Error"); +} + + +void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData) +{ + s_ErrorCallback = f; + s_ErrorCallbackClientData = clientData; +} + +void cmSystemTools::Message(const char* m1, const char *title) +{ + if(s_DisableMessages) { - primaryKey = HKEY_USERS; + return; } - - HKEY hKey; - if(RegOpenKeyEx(primaryKey, - second.c_str(), - 0, - KEY_READ, - &hKey) != ERROR_SUCCESS) + if(s_ErrorCallback) { - return false; + (*s_ErrorCallback)(m1, title, s_DisableMessages, s_ErrorCallbackClientData); + return; } else { - DWORD dwType, dwSize; - dwSize = 1023; - char data[1024]; - if(RegQueryValueEx(hKey, - (LPTSTR)valuename.c_str(), - NULL, - &dwType, - (BYTE *)data, - &dwSize) == ERROR_SUCCESS) - { - if (dwType == REG_SZ) - { - value = data; - return true; - } - } + std::cerr << m1 << std::endl << std::flush; } - return false; -} -#else -bool cmSystemTools::ReadRegistryValue(const char *, std::string &) -{ - return false; + } -#endif - -// Write a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will set the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will set the data of the "Root" value of the key -#if defined(_WIN32) && !defined(__CYGWIN__) -bool cmSystemTools::WriteRegistryValue(const char *key, const char *value) +void cmSystemTools::ReportLastSystemError(const char* msg) { - std::string primary = key; - std::string second; - std::string valuename; + std::string m = msg; + m += ": System Error: "; + m += SystemTools::GetLastSystemError(); + cmSystemTools::Error(m.c_str()); +} + - size_t start = primary.find("\\"); - if (start == std::string::npos) +bool cmSystemTools::IsOn(const char* val) +{ + if (!val) { return false; } - - size_t valuenamepos = primary.find(";"); - if (valuenamepos != std::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } + std::basic_string v = val; - HKEY hKey; - DWORD dwDummy; - if(RegCreateKeyEx(primaryKey, - second.c_str(), - 0, - "", - REG_OPTION_NON_VOLATILE, - KEY_WRITE, - NULL, - &hKey, - &dwDummy) != ERROR_SUCCESS) + for(std::basic_string::iterator c = v.begin(); + c != v.end(); c++) { - return false; + *c = toupper(*c); } + return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y"); +} - if(RegSetValueEx(hKey, - (LPTSTR)valuename.c_str(), - 0, - REG_SZ, - (CONST BYTE *)value, - (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS) +bool cmSystemTools::IsNOTFOUND(const char* val) +{ + cmRegularExpression reg("-NOTFOUND$"); + if(reg.find(val)) { return true; } - return false; -} -#else -bool cmSystemTools::WriteRegistryValue(const char *, const char *) -{ - return false; + return std::string("NOTFOUND") == val; } -#endif -// Delete a registry value. -// Example : -// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath -// => will delete the data of the "default" value of the key -// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root -// => will delete the data of the "Root" value of the key -#if defined(_WIN32) && !defined(__CYGWIN__) -bool cmSystemTools::DeleteRegistryValue(const char *key) +bool cmSystemTools::IsOff(const char* val) { - std::string primary = key; - std::string second; - std::string valuename; - - size_t start = primary.find("\\"); - if (start == std::string::npos) - { - return false; - } - - size_t valuenamepos = primary.find(";"); - if (valuenamepos != std::string::npos) + if (!val || strlen(val) == 0) { - valuename = primary.substr(valuenamepos+1); + return true; } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); + std::basic_string v = val; - HKEY primaryKey; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") + for(std::basic_string::iterator c = v.begin(); + c != v.end(); c++) { - primaryKey = HKEY_CURRENT_CONFIG; + *c = toupper(*c); } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - - HKEY hKey; - if(RegOpenKeyEx(primaryKey, - second.c_str(), - 0, - KEY_WRITE, - &hKey) != ERROR_SUCCESS) - { - return false; - } - else - { - if(RegDeleteValue(hKey, - (LPTSTR)valuename.c_str()) == ERROR_SUCCESS) - { - return true; - } - } - return false; -} -#else -bool cmSystemTools::DeleteRegistryValue(const char *) -{ - return false; -} -#endif - -// replace replace with with as many times as it shows up in source. -// write the result into source. -#if defined(_WIN32) && !defined(__CYGWIN__) -void cmSystemTools::ExpandRegistryValues(std::string& source) -{ - // Regular expression to match anything inside [...] that begins in HKEY. - // Note that there is a special rule for regular expressions to match a - // close square-bracket inside a list delimited by square brackets. - // The "[^]]" part of this expression will match any character except - // a close square-bracket. The ']' character must be the first in the - // list of characters inside the [^...] block of the expression. - cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]"); - - // check for black line or comment - while (regEntry.find(source)) - { - // the arguments are the second match - std::string key = regEntry.match(1); - std::string val; - if (ReadRegistryValue(key.c_str(), val)) - { - std::string reg = "["; - reg += key + "]"; - cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str()); - } - else - { - std::string reg = "["; - reg += key + "]"; - cmSystemTools::ReplaceString(source, reg.c_str(), "/registry"); - } - } -} -#else -void cmSystemTools::ExpandRegistryValues(std::string&) -{ -} -#endif - - -std::string cmSystemTools::EscapeQuotes(const char* str) -{ - std::string result = ""; - for(const char* ch = str; *ch != '\0'; ++ch) - { - if(*ch == '"') - { - result += '\\'; - } - result += *ch; - } - return result; -} - -bool cmSystemTools::SameFile(const char* file1, const char* file2) -{ -#ifdef _WIN32 - HANDLE hFile1, hFile2; - - hFile1 = CreateFile( file1, - GENERIC_READ, - FILE_SHARE_READ , - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL - ); - hFile2 = CreateFile( file2, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL - ); - if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE) - { - if(hFile1 != INVALID_HANDLE_VALUE) - { - CloseHandle(hFile1); - } - if(hFile2 != INVALID_HANDLE_VALUE) - { - CloseHandle(hFile2); - } - return false; - } - - BY_HANDLE_FILE_INFORMATION fiBuf1; - BY_HANDLE_FILE_INFORMATION fiBuf2; - GetFileInformationByHandle( hFile1, &fiBuf1 ); - GetFileInformationByHandle( hFile2, &fiBuf2 ); - CloseHandle(hFile1); - CloseHandle(hFile2); - return (fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh && - fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow); -#else - struct stat fileStat1, fileStat2; - if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0) - { - // see if the files are the same file - // check the device inode and size - if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 && - memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 && - fileStat2.st_size == fileStat1.st_size - ) - { - return true; - } - } - return false; -#endif -} - - -// return true if the file exists -bool cmSystemTools::FileExists(const char* filename) -{ - struct stat fs; - if (stat(filename, &fs) != 0) - { - return false; - } - else - { - return true; - } -} - - -// Return a capitalized string (i.e the first letter is uppercased, all other -// are lowercased) -std::string cmSystemTools::Capitalized(const std::string& s) -{ - std::string n; - n.resize(s.size()); - n[0] = toupper(s[0]); - for (size_t i = 1; i < s.size(); i++) - { - n[i] = tolower(s[i]); - } - return n; -} - - -// Return a lower case string -std::string cmSystemTools::LowerCase(const std::string& s) -{ - std::string n; - n.resize(s.size()); - for (size_t i = 0; i < s.size(); i++) - { - n[i] = tolower(s[i]); - } - return n; -} - -// Return a lower case string -std::string cmSystemTools::UpperCase(const std::string& s) -{ - std::string n; - n.resize(s.size()); - for (size_t i = 0; i < s.size(); i++) - { - n[i] = toupper(s[i]); - } - return n; -} - - -// convert windows slashes to unix slashes -void cmSystemTools::ConvertToUnixSlashes(std::string& path) -{ - std::string::size_type pos = 0; - while((pos = path.find('\\', pos)) != std::string::npos) - { - path[pos] = '/'; - pos++; - } - // Remove all // from the path just like most unix shells -#ifndef _WIN32 - int start_find = 0; -#else - // However, on windows if the first characters are both slashes, - // then keep them that way, so that network paths can be handled. - int start_find = 1; -#endif - - while((pos = path.find("//", start_find)) != std::string::npos) - { - cmSystemTools::ReplaceString(path, "//", "/"); - } - - // remove any trailing slash - if(path.size() && path[path.size()-1] == '/') - { - path = path.substr(0, path.size()-1); - } - - // if there is a tilda ~ then replace it with HOME - if(path.find("~") == 0) - { - if (getenv("HOME")) - { - path = std::string(getenv("HOME")) + path.substr(1); - } - } - - // if there is a /tmp_mnt in a path get rid of it! - // stupid sgi's - if(path.find("/tmp_mnt") == 0) - { - path = path.substr(8); - } -} - - -// change // to /, and escape any spaces in the path -std::string cmSystemTools::ConvertToUnixOutputPath(const char* path) -{ - std::string ret = path; - - // remove // except at the beginning might be a cygwin drive - std::string::size_type pos = 1; - while((pos = ret.find("//", pos)) != std::string::npos) - { - ret.erase(pos, 1); - } - // now escape spaces if there is a space in the path - if(ret.find(" ") != std::string::npos) - { - std::string result = ""; - char lastch = 1; - 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 == ' ' && lastch != '\\') - { - result += '\\'; - } - result += *ch; - lastch = *ch; - } - ret = result; - } - return ret; -} - - - -std::string cmSystemTools::EscapeSpaces(const char* str) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - std::string result; - - // if there are spaces - std::string temp = str; - if (temp.find(" ") != std::string::npos && - temp.find("\"")==std::string::npos) - { - result = "\""; - result += str; - result += "\""; - return result; - } - return str; -#else - std::string result = ""; - for(const char* ch = str; *ch != '\0'; ++ch) - { - if(*ch == ' ') - { - result += '\\'; - } - result += *ch; - } - return result; -#endif -} - -std::string cmSystemTools::ConvertToOutputPath(const char* path) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::ConvertToWindowsOutputPath(path); -#else - return cmSystemTools::ConvertToUnixOutputPath(path); -#endif -} - - -// remove double slashes not at the start -std::string cmSystemTools::ConvertToWindowsOutputPath(const char* path) -{ - std::string ret = path; - std::string::size_type pos = 0; - // first convert all of the slashes - while((pos = ret.find('/', pos)) != std::string::npos) - { - ret[pos] = '\\'; - pos++; - } - // check for really small paths - if(ret.size() < 2) - { - return ret; - } - // now clean up a bit and remove double slashes - // Only if it is not the first position in the path which is a network - // path on windows - pos = 1; // start at position 1 - if(ret[0] == '\"') - { - pos = 2; // if the string is already quoted then start at 2 - if(ret.size() < 3) - { - return ret; - } - } - while((pos = ret.find("\\\\", pos)) != std::string::npos) - { - ret.erase(pos, 1); - } - // now double quote the path if it has spaces in it - // and is not already double quoted - if(ret.find(" ") != std::string::npos - && ret[0] != '\"') - { - std::string result; - result = "\"" + ret + "\""; - ret = result; - } - return ret; -} - -std::string cmSystemTools::RemoveEscapes(const char* s) -{ - std::string result = ""; - for(const char* ch = s; *ch; ++ch) - { - if(*ch == '\\' && *(ch+1) != ';') - { - ++ch; - switch (*ch) - { - case '\\': result.insert(result.end(), '\\'); break; - case '"': result.insert(result.end(), '"'); break; - case ' ': result.insert(result.end(), ' '); break; - case 't': result.insert(result.end(), '\t'); break; - case 'n': result.insert(result.end(), '\n'); break; - case 'r': result.insert(result.end(), '\r'); break; - case '0': result.insert(result.end(), '\0'); break; - case '\0': - { - cmSystemTools::Error("Trailing backslash in argument:\n", s); - return result; - } - default: - { - std::string chStr(1, *ch); - cmSystemTools::Error("Invalid escape sequence \\", chStr.c_str(), - "\nin argument ", s); - } - } - } - else - { - result.insert(result.end(), *ch); - } - } - return result; -} - -void cmSystemTools::Error(const char* m1, const char* m2, - const char* m3, const char* m4) -{ - std::string message = "CMake Error: "; - if(m1) - { - message += m1; - } - if(m2) - { - message += m2; - } - if(m3) - { - message += m3; - } - if(m4) - { - message += m4; - } - cmSystemTools::s_ErrorOccured = true; - cmSystemTools::Message(message.c_str(),"Error"); -} - - -void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData) -{ - s_ErrorCallback = f; - s_ErrorCallbackClientData = clientData; -} - -void cmSystemTools::Message(const char* m1, const char *title) -{ - if(s_DisableMessages) - { - return; - } - if(s_ErrorCallback) - { - (*s_ErrorCallback)(m1, title, s_DisableMessages, s_ErrorCallbackClientData); - return; - } - else - { - std::cerr << m1 << std::endl << std::flush; - } - -} - - -bool cmSystemTools::CopyFileIfDifferent(const char* source, - const char* destination) -{ - if(cmSystemTools::FilesDiffer(source, destination)) - { - cmSystemTools::cmCopyFile(source, destination); - return true; - } - return false; -} - - -bool cmSystemTools::FilesDiffer(const char* source, - const char* destination) -{ - struct stat statSource; - if (stat(source, &statSource) != 0) - { - return true; - } - - struct stat statDestination; - if (stat(destination, &statDestination) != 0) - { - return true; - } - - if(statSource.st_size != statDestination.st_size) - { - return true; - } - - if(statSource.st_size == 0) - { - return false; - } - -#if defined(_WIN32) || defined(__CYGWIN__) - std::ifstream finSource(source, - std::ios::binary | std::ios::in); - std::ifstream finDestination(destination, - std::ios::binary | std::ios::in); -#else - std::ifstream finSource(source); - std::ifstream finDestination(destination); -#endif - if(!finSource || !finDestination) - { - return true; - } - - char* source_buf = new char[statSource.st_size]; - char* dest_buf = new char[statSource.st_size]; - - finSource.read(source_buf, statSource.st_size); - finDestination.read(dest_buf, statSource.st_size); - - if(statSource.st_size != static_cast(finSource.gcount()) || - statSource.st_size != static_cast(finDestination.gcount())) - { - cmOStringStream msg; - msg << "FilesDiffer failed to read files (allocated: " - << statSource.st_size << ", read source: " << finSource.gcount() - << ", read dest: " << finDestination.gcount(); - cmSystemTools::Error(msg.str().c_str()); - delete [] source_buf; - delete [] dest_buf; - return false; - } - int ret = memcmp((const void*)source_buf, - (const void*)dest_buf, - statSource.st_size); - - delete [] dest_buf; - delete [] source_buf; - - return ret != 0; -} - - -/** - * Copy a file named by "source" to the file named by "destination". - */ -void cmSystemTools::cmCopyFile(const char* source, - const char* destination) -{ - const int bufferSize = 4096; - char buffer[bufferSize]; - - // If destination is a directory, try to create a file with the same - // name as the source in that directory. - - std::string new_destination; - if(cmSystemTools::FileExists(destination) && - cmSystemTools::FileIsDirectory(destination)) - { - new_destination = destination; - cmSystemTools::ConvertToUnixSlashes(new_destination); - new_destination += '/'; - std::string source_name = source; - new_destination += cmSystemTools::GetFilenameName(source_name); - destination = new_destination.c_str(); - } - - // Create destination directory - - std::string destination_dir = destination; - destination_dir = cmSystemTools::GetFilenamePath(destination_dir); - cmSystemTools::MakeDirectory(destination_dir.c_str()); - - // Open files - -#if defined(_WIN32) || defined(__CYGWIN__) - std::ifstream fin(source, - std::ios::binary | std::ios::in); -#else - std::ifstream fin(source); -#endif - if(!fin) - { - int e = errno; - std::string m = "CopyFile failed to open source file \""; - m += source; - m += "\""; - m += " System Error: "; - m += strerror(e); - cmSystemTools::Error(m.c_str()); - return; - } - -#if defined(_WIN32) || defined(__CYGWIN__) - std::ofstream fout(destination, - std::ios::binary | std::ios::out | std::ios::trunc); -#else - std::ofstream fout(destination, - std::ios::out | std::ios::trunc); -#endif - if(!fout) - { - int e = errno; - std::string m = "CopyFile failed to open destination file \""; - m += destination; - m += "\""; - m += " System Error: "; - m += strerror(e); - cmSystemTools::Error(m.c_str()); - return; - } - - // This copy loop is very sensitive on certain platforms with - // slightly broken stream libraries (like HPUX). Normally, it is - // incorrect to not check the error condition on the fin.read() - // before using the data, but the fin.gcount() will be zero if an - // error occurred. Therefore, the loop should be safe everywhere. - while(fin) - { - fin.read(buffer, bufferSize); - if(fin.gcount()) - { - fout.write(buffer, fin.gcount()); - } - } - - // Make sure the operating system has finished writing the file - // before closing it. This will ensure the file is finished before - // the check below. - fout.flush(); - - fin.close(); - fout.close(); - - // More checks. - struct stat statSource, statDestination; - statSource.st_size = 12345; - statDestination.st_size = 12345; - if(stat(source, &statSource) != 0) - { - int e = errno; - std::string m = "CopyFile failed to stat source file \""; - m += source; - m += "\""; - m += " System Error: "; - m += strerror(e); - cmSystemTools::Error(m.c_str()); - } - else if(stat(destination, &statDestination) != 0) - { - int e = errno; - std::string m = "CopyFile failed to stat destination file \""; - m += source; - m += "\""; - m += " System Error: "; - m += strerror(e); - cmSystemTools::Error(m.c_str()); - } - else if(statSource.st_size != statDestination.st_size) - { - cmOStringStream msg; - msg << "CopyFile failed to copy files: source \"" - << source << "\", size " << statSource.st_size << ", destination \"" - << destination << "\", size " << statDestination.st_size; - cmSystemTools::Error(msg.str().c_str()); - } -} - -// return true if the file exists -long int cmSystemTools::ModifiedTime(const char* filename) -{ - struct stat fs; - if (stat(filename, &fs) != 0) - { - return 0; - } - else - { - return (long int)fs.st_mtime; - } -} - - -void cmSystemTools::ReportLastSystemError(const char* msg) -{ - int e = errno; - std::string m = msg; - m += ": System Error: "; - m += strerror(e); - cmSystemTools::Error(m.c_str()); -} - - -bool cmSystemTools::RemoveFile(const char* source) -{ - return unlink(source) != 0 ? false : true; -} - -bool cmSystemTools::IsOn(const char* val) -{ - if (!val) - { - return false; - } - std::basic_string v = val; - - for(std::basic_string::iterator c = v.begin(); - c != v.end(); c++) - { - *c = toupper(*c); - } - return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y"); -} - -bool cmSystemTools::IsNOTFOUND(const char* val) -{ - cmRegularExpression reg("-NOTFOUND$"); - if(reg.find(val)) - { - return true; - } - return std::string("NOTFOUND") == val; -} - - -bool cmSystemTools::IsOff(const char* val) -{ - if (!val || strlen(val) == 0) - { - return true; - } - std::basic_string v = val; - - for(std::basic_string::iterator c = v.begin(); - c != v.end(); c++) - { - *c = toupper(*c); - } - return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" || - v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE"); -} - - -bool cmSystemTools::RunCommand(const char* command, - std::string& output, - const char* dir, - bool verbose, - int timeout) -{ - int dummy; - return cmSystemTools::RunCommand(command, output, dummy, - dir, verbose, timeout); -} - -#if defined(WIN32) && !defined(__CYGWIN__) -#include "cmWin32ProcessExecution.h" -// use this for shell commands like echo and dir -bool RunCommandViaWin32(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose, - int timeout) -{ -#if defined(__BORLANDC__) - return cmWin32ProcessExecution::BorlandRunCommand(command, dir, output, - retVal, - verbose, timeout, - cmSystemTools::GetRunCommandHideConsole()); -#else // Visual studio - ::SetLastError(ERROR_SUCCESS); - if ( ! command ) - { - cmSystemTools::Error("No command specified"); - return false; - } - - cmWin32ProcessExecution resProc; - if(cmSystemTools::GetRunCommandHideConsole()) - { - resProc.SetHideWindows(true); - } - - if ( cmSystemTools::GetWindows9xComspecSubstitute() ) - { - resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() ); - } - if ( !resProc.StartProcess(command, dir, verbose) ) - { - return false; - } - resProc.Wait(timeout); - output = resProc.GetOutput(); - retVal = resProc.GetExitValue(); - return true; -#endif -} - -// use this for shell commands like echo and dir -bool RunCommandViaSystem(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose) -{ - std::cout << "@@ " << command << std::endl; - - std::string commandInDir; - if(dir) - { - commandInDir = "cd "; - commandInDir += cmSystemTools::ConvertToOutputPath(dir); - commandInDir += " && "; - commandInDir += command; - } - else - { - commandInDir = command; - } - command = commandInDir.c_str(); - std::string commandToFile = command; - commandToFile += " > "; - std::string tempFile; - tempFile += _tempnam(0, "cmake"); - - commandToFile += tempFile; - retVal = system(commandToFile.c_str()); - std::ifstream fin(tempFile.c_str()); - if(!fin) - { - if(verbose) - { - std::string errormsg = "RunCommand produced no output: command: \""; - errormsg += command; - errormsg += "\""; - errormsg += "\nOutput file: "; - errormsg += tempFile; - cmSystemTools::Error(errormsg.c_str()); - } - fin.close(); - cmSystemTools::RemoveFile(tempFile.c_str()); - return false; - } - bool multiLine = false; - std::string line; - while(cmSystemTools::GetLineFromStream(fin, line)) - { - output += line; - if(multiLine) - { - output += "\n"; - } - multiLine = true; - } - fin.close(); - cmSystemTools::RemoveFile(tempFile.c_str()); - return true; -} - -#else // We have popen - -bool RunCommandViaPopen(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose, - int /*timeout*/) -{ - // if only popen worked on windows..... - std::string commandInDir; - if(dir) - { - commandInDir = "cd \""; - commandInDir += dir; - commandInDir += "\" && "; - commandInDir += command; - } - else - { - commandInDir = command; - } - commandInDir += " 2>&1"; - command = commandInDir.c_str(); - const int BUFFER_SIZE = 4096; - char buffer[BUFFER_SIZE]; - if(verbose) - { - std::cout << "running " << command << std::endl; - } - fflush(stdout); - fflush(stderr); - FILE* cpipe = popen(command, "r"); - if(!cpipe) - { - return false; - } - fgets(buffer, BUFFER_SIZE, cpipe); - while(!feof(cpipe)) - { - if(verbose) - { - std::cout << buffer << std::flush; - } - output += buffer; - fgets(buffer, BUFFER_SIZE, cpipe); - } - - retVal = pclose(cpipe); - if (WIFEXITED(retVal)) - { - retVal = WEXITSTATUS(retVal); - return true; - } - if (WIFSIGNALED(retVal)) - { - retVal = WTERMSIG(retVal); - cmOStringStream error; - error << "\nProcess terminated due to "; - switch (retVal) - { -#ifdef SIGKILL - case SIGKILL: - error << "SIGKILL"; - break; -#endif -#ifdef SIGFPE - case SIGFPE: - error << "SIGFPE"; - break; -#endif -#ifdef SIGBUS - case SIGBUS: - error << "SIGBUS"; - break; -#endif -#ifdef SIGSEGV - case SIGSEGV: - error << "SIGSEGV"; - break; -#endif - default: - error << "signal " << retVal; - break; - } - output += error.str(); - } - return false; -} - -#endif // endif WIN32 not CYGWIN - - -// run a command unix uses popen (easy) -// windows uses system and ShortPath -bool cmSystemTools::RunCommand(const char* command, - std::string& output, - int &retVal, - const char* dir, - bool verbose, - int timeout) -{ - if(s_DisableRunCommandOutput) - { - verbose = false; - } - -#if defined(WIN32) && !defined(__CYGWIN__) - // if the command does not start with a quote, then - // try to find the program, and if the program can not be - // found use system to run the command as it must be a built in - // shell command like echo or dir - int count = 0; - if(command[0] == '\"') - { - // count the number of quotes - for(const char* s = command; *s != 0; ++s) - { - if(*s == '\"') - { - count++; - if(count > 2) - { - break; - } - } - } - // if there are more than two double quotes use - // GetShortPathName, the cmd.exe program in windows which - // is used by system fails to execute if there are more than - // one set of quotes in the arguments - if(count > 2) - { - cmRegularExpression quoted("^\"([^\"]*)\"[ \t](.*)"); - if(quoted.find(command)) - { - std::string shortCmd; - std::string cmd = quoted.match(1); - std::string args = quoted.match(2); - if(! cmSystemTools::FileExists(cmd.c_str()) ) - { - shortCmd = cmd; - } - else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) - { - cmSystemTools::Error("GetShortPath failed for " , cmd.c_str()); - return false; - } - shortCmd += " "; - shortCmd += args; - - //return RunCommandViaSystem(shortCmd.c_str(), dir, - // output, retVal, verbose); - //return WindowsRunCommand(shortCmd.c_str(), dir, - //output, retVal, verbose); - return RunCommandViaWin32(shortCmd.c_str(), dir, - output, retVal, verbose, timeout); - } - else - { - cmSystemTools::Error("Could not parse command line with quotes ", - command); - } - } - } - // if there is only one set of quotes or no quotes then just run the command - //return RunCommandViaSystem(command, dir, output, retVal, verbose); - //return WindowsRunCommand(command, dir, output, retVal, verbose); - return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout); -#else - return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout); -#endif + return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" || + v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE"); } -/** - * Find the file the given name. Searches the given path and then - * the system search path. Returns the full path to the file if it is - * found. Otherwise, the empty string is returned. - */ -std::string cmSystemTools::FindFile(const char* name, - const std::vector& userPaths) -{ - // Add the system search path to our path. - std::vector path = userPaths; - cmSystemTools::GetPath(path); - - std::string tryPath; - for(std::vector::const_iterator p = path.begin(); - p != path.end(); ++p) - { - tryPath = *p; - tryPath += "/"; - tryPath += name; - if(cmSystemTools::FileExists(tryPath.c_str()) && - !cmSystemTools::FileIsDirectory(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - } - // Couldn't find the file. - return ""; -} -/** - * Find the executable with the given name. Searches the given path and then - * the system search path. Returns the full path to the executable if it is - * found. Otherwise, the empty string is returned. - */ -std::string cmSystemTools::FindProgram(const char* name, - const std::vector& userPaths, - bool no_system_path) +bool cmSystemTools::RunCommand(const char* command, + std::string& output, + const char* dir, + bool verbose, + int timeout) { - if(!name) - { - return ""; - } - // See if the executable exists as written. - if(cmSystemTools::FileExists(name) && - !cmSystemTools::FileIsDirectory(name)) - { - return cmSystemTools::CollapseFullPath(name); - } - std::string tryPath = name; - tryPath += cmSystemTools::GetExecutableExtension(); - if(cmSystemTools::FileExists(tryPath.c_str()) && - !cmSystemTools::FileIsDirectory(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - - // Add the system search path to our path. - std::vector path = userPaths; - if (!no_system_path) - { - cmSystemTools::GetPath(path); - } - - for(std::vector::const_iterator p = path.begin(); - p != path.end(); ++p) - { - tryPath = *p; - tryPath += "/"; - tryPath += name; - if(cmSystemTools::FileExists(tryPath.c_str()) && - !cmSystemTools::FileIsDirectory(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } -#ifdef _WIN32 - tryPath += ".com"; - if(cmSystemTools::FileExists(tryPath.c_str()) && - !cmSystemTools::FileIsDirectory(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - tryPath = *p; - tryPath += "/"; - tryPath += name; -#endif - tryPath += cmSystemTools::GetExecutableExtension(); - if(cmSystemTools::FileExists(tryPath.c_str()) && - !cmSystemTools::FileIsDirectory(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - } - - // Couldn't find the program. - return ""; + int dummy; + return cmSystemTools::RunCommand(command, output, dummy, + dir, verbose, timeout); } - -/** - * Find the library with the given name. Searches the given path and then - * the system search path. Returns the full path to the library if it is - * found. Otherwise, the empty string is returned. - */ -std::string cmSystemTools::FindLibrary(const char* name, - const std::vector& userPaths) +#if defined(WIN32) && !defined(__CYGWIN__) +#include "cmWin32ProcessExecution.h" +// use this for shell commands like echo and dir +bool RunCommandViaWin32(const char* command, + const char* dir, + std::string& output, + int& retVal, + bool verbose, + int timeout) { - // See if the executable exists as written. - if(cmSystemTools::FileExists(name) && - !cmSystemTools::FileIsDirectory(name)) - { - return cmSystemTools::CollapseFullPath(name); - } - - // Add the system search path to our path. - std::vector path = userPaths; - cmSystemTools::GetPath(path); - - std::string tryPath; - for(std::vector::const_iterator p = path.begin(); - p != path.end(); ++p) - { -#if defined(_WIN32) && !defined(__CYGWIN__) - tryPath = *p; - tryPath += "/"; - tryPath += name; - tryPath += ".lib"; - if(cmSystemTools::FileExists(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } -#else - tryPath = *p; - tryPath += "/lib"; - tryPath += name; - tryPath += ".so"; - if(cmSystemTools::FileExists(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - tryPath = *p; - tryPath += "/lib"; - tryPath += name; - tryPath += ".a"; - if(cmSystemTools::FileExists(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - tryPath = *p; - tryPath += "/lib"; - tryPath += name; - tryPath += ".sl"; - if(cmSystemTools::FileExists(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } - tryPath = *p; - tryPath += "/lib"; - tryPath += name; - tryPath += ".dylib"; - if(cmSystemTools::FileExists(tryPath.c_str())) - { - return cmSystemTools::CollapseFullPath(tryPath.c_str()); - } -#endif - } - - // Couldn't find the library. - return ""; -} - -bool cmSystemTools::FileIsDirectory(const char* name) -{ - struct stat fs; - if(stat(name, &fs) == 0) - { -#if _WIN32 - return ((fs.st_mode & _S_IFDIR) != 0); -#else - return S_ISDIR(fs.st_mode); -#endif - } - else +#if defined(__BORLANDC__) + return cmWin32ProcessExecution::BorlandRunCommand(command, dir, output, + retVal, + verbose, timeout, + cmSystemTools::GetRunCommandHideConsole()); +#else // Visual studio + ::SetLastError(ERROR_SUCCESS); + if ( ! command ) { + cmSystemTools::Error("No command specified"); return false; } -} - -bool cmSystemTools::DoesFileExistWithExtensions( - const char* name, - const std::vector& headerExts) -{ - std::string hname; - for( std::vector::const_iterator ext = headerExts.begin(); - ext != headerExts.end(); ++ext ) + cmWin32ProcessExecution resProc; + if(cmSystemTools::GetRunCommandHideConsole()) { - hname = name; - hname += "."; - hname += *ext; - if(cmSystemTools::FileExists(hname.c_str())) - { - return true; - } + resProc.SetHideWindows(true); } - return false; -} - - - -int cmSystemTools::ChangeDirectory(const char *dir) -{ - return Chdir(dir); -} - -std::string cmSystemTools::GetCurrentWorkingDirectory() -{ - char buf[2048]; - std::string path = Getcwd(buf, 2048); - return path; -} - -/** - * Given the path to a program executable, get the directory part of the path with the - * file stripped off. If there is no directory part, the empty string is returned. - */ -std::string cmSystemTools::GetProgramPath(const char* in_name) -{ - std::string dir, file; - cmSystemTools::SplitProgramPath(in_name, dir, file); - return dir; -} - -/** - * Given the path to a program executable, get the directory part of the path - * with the file stripped off. If there is no directory part, the empty - * string is returned. - */ -void cmSystemTools::SplitProgramPath(const char* in_name, - std::string& dir, - std::string& file, - bool errorReport) -{ - dir = in_name; - file = ""; - cmSystemTools::ConvertToUnixSlashes(dir); - if(!cmSystemTools::FileIsDirectory(dir.c_str())) + if ( cmSystemTools::GetWindows9xComspecSubstitute() ) { - std::string::size_type slashPos = dir.rfind("/"); - if(slashPos != std::string::npos) - { - file = dir.substr(slashPos+1); - dir = dir.substr(0, slashPos); - } - else - { - file = dir; - dir = ""; - } + resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() ); } - if((dir != "") && !cmSystemTools::FileIsDirectory(dir.c_str())) + if ( !resProc.StartProcess(command, dir, verbose) ) { - std::string oldDir = in_name; - cmSystemTools::ConvertToUnixSlashes(oldDir); - if(errorReport) - { - cmSystemTools::Error("Error splitting file name off end of path:\n", - oldDir.c_str(), "\nDirectory not found: ", - dir.c_str()); - } - - dir = in_name; - return; + return false; } + resProc.Wait(timeout); + output = resProc.GetOutput(); + retVal = resProc.GetExitValue(); + return true; +#endif } -/** - * Given a path to a file or directory, convert it to a full path. - * This collapses away relative paths relative to the cwd argument - * (which defaults to the current working directory). The full path - * is returned. - */ -std::string cmSystemTools::CollapseFullPath(const char* in_relative) -{ - return cmSystemTools::CollapseFullPath(in_relative, 0); -} +// use this for shell commands like echo and dir +bool RunCommandViaSystem(const char* command, + const char* dir, + std::string& output, + int& retVal, + bool verbose) +{ + std::cout << "@@ " << command << std::endl; -std::string cmSystemTools::CollapseFullPath(const char* in_relative, - const char* in_base) -{ - std::string dir, file; - cmSystemTools::SplitProgramPath(in_relative, dir, file, false); - - // Save original working directory. - std::string orig = cmSystemTools::GetCurrentWorkingDirectory(); - - // Change to base of relative path. - if(in_base) - { - Chdir(in_base); - } - -#ifdef _WIN32 - // Follow relative path. - if(dir != "") - { - Chdir(dir.c_str()); - } - - // Get the resulting directory. - std::string newDir = cmSystemTools::GetCurrentWorkingDirectory(); - - // Add the file back on to the directory. - cmSystemTools::ConvertToUnixSlashes(newDir); -#else -# ifdef MAXPATHLEN - char resolved_name[MAXPATHLEN]; -# else -# ifdef PATH_MAX - char resolved_name[PATH_MAX]; -# else - char resolved_name[5024]; -# endif -# endif - - // Resolve relative path. - std::string newDir; - if(dir != "") + std::string commandInDir; + if(dir) { - realpath(dir.c_str(), resolved_name); - newDir = resolved_name; + commandInDir = "cd "; + commandInDir += cmSystemTools::ConvertToOutputPath(dir); + commandInDir += " && "; + commandInDir += command; } else { - newDir = cmSystemTools::GetCurrentWorkingDirectory(); - } -#endif - - // Restore original working directory. - Chdir(orig.c_str()); - - // Construct and return the full path. - std::string newPath = newDir; - if(file != "") - { - newPath += "/"; - newPath += file; + commandInDir = command; } - return newPath; -} + command = commandInDir.c_str(); + std::string commandToFile = command; + commandToFile += " > "; + std::string tempFile; + tempFile += _tempnam(0, "cmake"); -bool cmSystemTools::Split(const char* str, std::vector& lines) -{ - std::string data(str); - std::string::size_type lpos = 0; - while(lpos < data.length()) + commandToFile += tempFile; + retVal = system(commandToFile.c_str()); + std::ifstream fin(tempFile.c_str()); + if(!fin) { - std::string::size_type rpos = data.find_first_of("\n", lpos); - if(rpos == std::string::npos) - { - // Line ends at end of string without a newline. - lines.push_back(data.substr(lpos)); - return false; - } - if((rpos > lpos) && (data[rpos-1] == '\r')) + if(verbose) { - // Line ends in a "\r\n" pair, remove both characters. - lines.push_back(data.substr(lpos, (rpos-1)-lpos)); + std::string errormsg = "RunCommand produced no output: command: \""; + errormsg += command; + errormsg += "\""; + errormsg += "\nOutput file: "; + errormsg += tempFile; + cmSystemTools::Error(errormsg.c_str()); } - else + fin.close(); + cmSystemTools::RemoveFile(tempFile.c_str()); + return false; + } + bool multiLine = false; + std::string line; + while(cmSystemTools::GetLineFromStream(fin, line)) + { + output += line; + if(multiLine) { - // Line ends in a "\n", remove the character. - lines.push_back(data.substr(lpos, rpos-lpos)); + output += "\n"; } - lpos = rpos+1; + multiLine = true; } + fin.close(); + cmSystemTools::RemoveFile(tempFile.c_str()); return true; } -/** - * Return path of a full filename (no trailing slashes). - * Warning: returned path is converted to Unix slashes format. - */ -std::string cmSystemTools::GetFilenamePath(const std::string& filename) +#else // We have popen + +bool RunCommandViaPopen(const char* command, + const char* dir, + std::string& output, + int& retVal, + bool verbose, + int /*timeout*/) { - std::string fn = filename; - cmSystemTools::ConvertToUnixSlashes(fn); - - std::string::size_type slash_pos = fn.rfind("/"); - if(slash_pos != std::string::npos) + // if only popen worked on windows..... + std::string commandInDir; + if(dir) { - return fn.substr(0, slash_pos); + commandInDir = "cd \""; + commandInDir += dir; + commandInDir += "\" && "; + commandInDir += command; } else { - return ""; - } -} - - -/** - * Return file name of a full filename (i.e. file name without path). - */ -std::string cmSystemTools::GetFilenameName(const std::string& filename) -{ - std::string fn = filename; - cmSystemTools::ConvertToUnixSlashes(fn); - - std::string::size_type slash_pos = fn.rfind("/"); - if(slash_pos != std::string::npos) - { - return fn.substr(slash_pos + 1); + commandInDir = command; } - else + commandInDir += " 2>&1"; + command = commandInDir.c_str(); + const int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE]; + if(verbose) { - return filename; + std::cout << "running " << command << std::endl; } -} - - -/** - * Return file extension of a full filename (dot included). - * Warning: this is the longest extension (for example: .tar.gz) - */ -std::string cmSystemTools::GetFilenameExtension(const std::string& filename) -{ - std::string name = cmSystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.find("."); - if(dot_pos != std::string::npos) + fflush(stdout); + fflush(stderr); + FILE* cpipe = popen(command, "r"); + if(!cpipe) { - return name.substr(dot_pos); + return false; } - else + fgets(buffer, BUFFER_SIZE, cpipe); + while(!feof(cpipe)) { - return ""; + if(verbose) + { + std::cout << buffer << std::flush; + } + output += buffer; + fgets(buffer, BUFFER_SIZE, cpipe); } -} -/** - * Return file extension of a full filename (dot included). - * Warning: this is the shortest extension (for example: .tar.gz) - */ -std::string -cmSystemTools::GetFilenameLastExtension(const std::string& filename) -{ - std::string name = cmSystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.rfind("."); - if(dot_pos != std::string::npos) + retVal = pclose(cpipe); + if (WIFEXITED(retVal)) { - return name.substr(dot_pos); + retVal = WEXITSTATUS(retVal); + return true; } - else + if (WIFSIGNALED(retVal)) { - return ""; + retVal = WTERMSIG(retVal); + cmOStringStream error; + error << "\nProcess terminated due to "; + switch (retVal) + { +#ifdef SIGKILL + case SIGKILL: + error << "SIGKILL"; + break; +#endif +#ifdef SIGFPE + case SIGFPE: + error << "SIGFPE"; + break; +#endif +#ifdef SIGBUS + case SIGBUS: + error << "SIGBUS"; + break; +#endif +#ifdef SIGSEGV + case SIGSEGV: + error << "SIGSEGV"; + break; +#endif + default: + error << "signal " << retVal; + break; + } + output += error.str(); } + return false; } +#endif // endif WIN32 not CYGWIN + -/** - * Return file name without extension of a full filename (i.e. without path). - * Warning: it considers the longest extension (for example: .tar.gz) - */ -std::string cmSystemTools::GetFilenameWithoutExtension(const std::string& filename) +// run a command unix uses popen (easy) +// windows uses system and ShortPath +bool cmSystemTools::RunCommand(const char* command, + std::string& output, + int &retVal, + const char* dir, + bool verbose, + int timeout) { - std::string name = cmSystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.find("."); - if(dot_pos != std::string::npos) + if(s_DisableRunCommandOutput) { - return name.substr(0, dot_pos); + verbose = false; } - else + +#if defined(WIN32) && !defined(__CYGWIN__) + // if the command does not start with a quote, then + // try to find the program, and if the program can not be + // found use system to run the command as it must be a built in + // shell command like echo or dir + int count = 0; + if(command[0] == '\"') { - return name; + // count the number of quotes + for(const char* s = command; *s != 0; ++s) + { + if(*s == '\"') + { + count++; + if(count > 2) + { + break; + } + } + } + // if there are more than two double quotes use + // GetShortPathName, the cmd.exe program in windows which + // is used by system fails to execute if there are more than + // one set of quotes in the arguments + if(count > 2) + { + cmRegularExpression quoted("^\"([^\"]*)\"[ \t](.*)"); + if(quoted.find(command)) + { + std::string shortCmd; + std::string cmd = quoted.match(1); + std::string args = quoted.match(2); + if(! cmSystemTools::FileExists(cmd.c_str()) ) + { + shortCmd = cmd; + } + else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) + { + cmSystemTools::Error("GetShortPath failed for " , cmd.c_str()); + return false; + } + shortCmd += " "; + shortCmd += args; + + //return RunCommandViaSystem(shortCmd.c_str(), dir, + // output, retVal, verbose); + //return WindowsRunCommand(shortCmd.c_str(), dir, + //output, retVal, verbose); + return RunCommandViaWin32(shortCmd.c_str(), dir, + output, retVal, verbose, timeout); + } + else + { + cmSystemTools::Error("Could not parse command line with quotes ", + command); + } + } } + // if there is only one set of quotes or no quotes then just run the command + //return RunCommandViaSystem(command, dir, output, retVal, verbose); + //return WindowsRunCommand(command, dir, output, retVal, verbose); + return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout); +#else + return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout); +#endif } - -/** - * Return file name without extension of a full filename (i.e. without path). - * Warning: it considers the last extension (for example: removes .gz - * from .tar.gz) - */ -std::string -cmSystemTools::GetFilenameWithoutLastExtension(const std::string& filename) +bool cmSystemTools::DoesFileExistWithExtensions( + const char* name, + const std::vector& headerExts) { - std::string name = cmSystemTools::GetFilenameName(filename); - std::string::size_type dot_pos = name.rfind("."); - if(dot_pos != std::string::npos) - { - return name.substr(0, dot_pos); - } - else + std::string hname; + + for( std::vector::const_iterator ext = headerExts.begin(); + ext != headerExts.end(); ++ext ) { - return name; + hname = name; + hname += "."; + hname += *ext; + if(cmSystemTools::FileExists(hname.c_str())) + { + return true; + } } + return false; } -bool cmSystemTools::FileIsFullPath(const char* in_name) +bool cmSystemTools::cmCopyFile(const char* source, const char* destination) { - std::string name = in_name; -#if defined(_WIN32) - // On Windows, the name must be at least two characters long. - if(name.length() < 2) - { - return false; - } - if(name[1] == ':') - { - return true; - } - if(name[0] == '\\') - { - return true; - } -#else - // On UNIX, the name must be at least one character long. - if(name.length() < 1) - { - return false; - } -#endif - // On UNIX, the name must begin in a '/'. - // On Windows, if the name begins in a '/', then it is a full - // network path. - if(name[0] == '/') - { - return true; - } - return false; + return SystemTools::CopyFileAlways(source, destination); } void cmSystemTools::Glob(const char *directory, const char *regexp, std::vector& files) { - cmDirectory d; + cmsys::Directory d; cmRegularExpression reg(regexp); if (d.Load(directory)) @@ -2083,7 +641,7 @@ void cmSystemTools::GlobDirs(const char *fullPath, std::string startPath = path.substr(0, pos); std::string finishPath = path.substr(pos+2); - cmDirectory d; + cmsys::Directory d; if (d.Load(startPath.c_str())) { for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) @@ -2204,64 +762,6 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, } } -bool cmSystemTools::GetShortPath(const char* path, std::string& shortPath) -{ -#if defined(WIN32) && !defined(__CYGWIN__) - const int size = int(strlen(path)) +1; // size of return - char *buffer = new char[size]; // create a buffer - char *tempPath = new char[size]; // create a buffer - int ret; - - // if the path passed in has quotes around it, first remove the quotes - if (path[0] == '"' && path[strlen(path)-1] == '"') - { - strcpy(tempPath,path+1); - tempPath[strlen(tempPath)-1] = '\0'; - } - else - { - strcpy(tempPath,path); - } - - buffer[0] = 0; - ret = GetShortPathName(tempPath, buffer, size); - - if(buffer[0] == 0 || ret > size) - { - if(ret < size) - { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - cmSystemTools::Error((LPCTSTR)lpMsgBuf); - LocalFree( lpMsgBuf ); - } - cmSystemTools::Error("Unable to get a short path: ", path); - delete [] tempPath; - return false; - } - else - { - shortPath = buffer; - delete [] buffer; - delete [] tempPath; - return true; - } -#else - shortPath = path; - return true; -#endif -} - bool cmSystemTools::SimpleGlob(const std::string& glob, std::vector& files, int type /* = 0 */) @@ -2280,7 +780,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, } bool res = false; - cmDirectory d; + cmsys::Directory d; if (d.Load(path.c_str())) { for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) @@ -2367,133 +867,17 @@ cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext) return cmSystemTools::UNKNOWN_FILE_FORMAT; } - -void cmSystemTools::SplitProgramFromArgs(const char* path, - std::string& program, std::string& args) -{ - if(cmSystemTools::FileExists(path)) - { - program = path; - args = ""; - return; - } - std::vector e; - std::string findProg = cmSystemTools::FindProgram(path, e); - if(findProg.size()) - { - program = findProg; - args = ""; - return; - } - std::string dir = path; - std::string::size_type spacePos = dir.rfind(' '); - if(spacePos == std::string::npos) - { - program = ""; - args = ""; - return; - } - while(spacePos != std::string::npos) - { - std::string tryProg = dir.substr(0, spacePos); - if(cmSystemTools::FileExists(tryProg.c_str())) - { - program = tryProg; - args = dir.substr(spacePos, dir.size()-spacePos); - return; - } - findProg = cmSystemTools::FindProgram(tryProg.c_str(), e); - if(findProg.size()) - { - program = findProg; - args = dir.substr(spacePos, dir.size()-spacePos); - return; - } - spacePos = dir.rfind(' ', spacePos--); - } - program = ""; - args = ""; -} - -std::string cmSystemTools::GetCurrentDateTime(const char* format) -{ - char buf[1024]; - time_t t; - time(&t); - strftime(buf, sizeof(buf), format, localtime(&t)); - return buf; -} - -std::string cmSystemTools::MakeCindentifier(const char* s) -{ - std::string str(s); - if (str.find_first_of("0123456789") == 0) - { - str = "_" + str; - } - - std::string permited_chars("_" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"); - std::string::size_type pos = 0; - while ((pos = str.find_first_not_of(permited_chars, pos)) != std::string::npos) - { - str[pos] = '_'; - } - return str; -} - -// Due to a buggy stream library on the HP and another on Mac OSX, we -// need this very carefully written version of getline. Returns true -// if any data were read before the end-of-file was reached. -bool cmSystemTools::GetLineFromStream(std::istream& is, std::string& line) +bool cmSystemTools::Split(const char* s, std::vector& l) { - const int bufferSize = 1024; - char buffer[bufferSize]; - line = ""; - bool haveData = false; - - // If no characters are read from the stream, the end of file has - // been reached. - while((is.getline(buffer, bufferSize), is.gcount() > 0)) + std::vector temp; + if(!SystemTools::Split(s, temp)) { - haveData = true; - line.append(buffer); - - // If newline character was read, the gcount includes the - // character, but the buffer does not. The end of line has been - // reached. - if(strlen(buffer) < static_cast(is.gcount())) - { - break; - } - - // The fail bit may be set. Clear it. - is.clear(is.rdstate() & ~std::ios::failbit); + return false; } - return haveData; -} - -#if defined(_MSC_VER) && defined(_DEBUG) -# include -# include -# include -static int cmSystemToolsDebugReport(int, char* message, int*) -{ - fprintf(stderr, message); - exit(1); - return 0; -} -void cmSystemTools::EnableMSVCDebugHook() -{ - if(getenv("DART_TEST_FROM_DART")) + for(std::vector::const_iterator i = temp.begin(); + i != temp.end(); ++i) { - _CrtSetReportHook(cmSystemToolsDebugReport); + l.push_back(*i); } + return true; } -#else -void cmSystemTools::EnableMSVCDebugHook() -{ -} -#endif diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 51d9c41..fc484a6 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -19,47 +19,17 @@ #include "cmStandardIncludes.h" +#include + /** \class cmSystemTools * \brief A collection of useful functions for CMake. * * cmSystemTools is a class that provides helper functions * for the CMake build system. */ -class cmSystemTools +class cmSystemTools: public cmsys::SystemTools { public: - /** - * Replace symbols in str that are not valid in C identifiers as - * defined by the 1999 standard, ie. anything except [A-Za-z0-9_]. - * They are replaced with `_' and if the first character is a digit - * then an underscore is prepended. Note that this can produce - * identifiers that the standard reserves (_[A-Z].* and __.*). - */ - static std::string MakeCindentifier(const char* s); - - /** - * Make a new directory if it is not there. This function - * can make a full path even if none of the directories existed - * prior to calling this function. - */ - static bool MakeDirectory(const char* path); - - /** - * Get current time as a double. On certain platforms this will - * return higher resolution than seconds: - * (1) gettimeofday() -- resolution in microseconds - * (2) ftime() -- resolution in milliseconds - * (3) time() -- resolution in seconds - */ - static double GetTime(); - - /** - * Replace replace all occurances of the string in - * the source string. - */ - static void ReplaceString(std::string& source, - const char* replace, - const char* with); /** Expand out any arguements in the vector that have ; separated * strings into multiple arguements. A new vector is created @@ -71,47 +41,11 @@ public: std::vector& argsOut); /** - * Read a registry value - */ - static bool ReadRegistryValue(const char *key, std::string &value); - - /** - * Write a registry value - */ - static bool WriteRegistryValue(const char *key, const char *value); - - /** - * Delete a registry value - */ - static bool DeleteRegistryValue(const char *key); - - /** * Look for and replace registry values in a string */ static void ExpandRegistryValues(std::string& source); /** - * Return a capitalized string (i.e the first letter is uppercased, all other - * are lowercased). - */ - static std::string Capitalized(const std::string&); - - /** - * Return a lower case string - */ - static std::string LowerCase(const std::string&); - - /** - * Return a lower case string - */ - static std::string UpperCase(const std::string&); - - /** - * Replace Windows file system slashes with Unix-style slashes. - */ - static void ConvertToUnixSlashes(std::string& path); - - /** * Platform independent escape spaces, unix uses backslash, * windows double quotes the string. */ @@ -119,15 +53,6 @@ public: ///! Escape quotes in a string. static std::string EscapeQuotes(const char* str); - - /** - * For windows this calles ConvertToWindowsOutputPath and for unix - * it calls ConvertToUnixOutputPath - */ - static std::string ConvertToOutputPath(const char*); - - ///! Return true if a file exists in the current directory. - static bool FileExists(const char* filename); /** * Given a string, replace any escape sequences with the corresponding @@ -135,19 +60,6 @@ public: */ static std::string RemoveEscapes(const char*); - - /** - * Add the paths from the environment variable PATH to the - * string vector passed in. - */ - static void GetPath(std::vector& path); - - /** - * Get the file extension (including ".") needed for an executable - * on the current platform ("" for unix, ".exe" for Windows). - */ - static const char* GetExecutableExtension(); - typedef void (*ErrorCallback)(const char*, const char*, bool&, void*); /** * Set the function used by GUI's to display error messages @@ -191,26 +103,6 @@ public: cmSystemTools::s_ErrorOccured = false; } - /** - * Copy the source file to the destination file only - * if the two files differ. - */ - static bool CopyFileIfDifferent(const char* source, - const char* destination); - - ///! Compare the contents of two files. Return true if different. - static bool FilesDiffer(const char* source, - const char* destination); - ///! return true if the two files are the same file - static bool SameFile(const char* file1, const char* file2); - - ///! Copy a file. - static void cmCopyFile(const char* source, - const char* destination); - - ///! Remove a file. - static bool RemoveFile(const char* source); - /** * does a string indicate a true or on value ? This is not the same * as ifdef. @@ -229,22 +121,6 @@ public: ///! Return true if value is NOTFOUND or ends in -NOTFOUND. static bool IsNOTFOUND(const char* value); - ///! Find a file in the system PATH, with optional extra paths. - static std::string FindFile(const char* name, - const std::vector& path= std::vector()); - - ///! Find an executable in the system PATH, with optional extra paths. - static std::string FindProgram(const char* name, - const std::vector& path = std::vector(), - bool no_system_path = false); - - ///! Find a library in the system PATH, with optional extra paths. - static std::string FindLibrary(const char* name, - const std::vector& path); - - ///! return true if the file is a directory. - static bool FileIsDirectory(const char* name); - static bool DoesFileExistWithExtensions( const char *name, const std::vector& sourceExts); @@ -265,43 +141,8 @@ public: static bool SimpleGlob(const std::string& glob, std::vector& files, int type = 0); - static std::string GetCurrentWorkingDirectory(); - static std::string GetProgramPath(const char*); - static void SplitProgramPath(const char* in_name, - std::string& dir, - std::string& file, - bool errorReport = true); - static std::string CollapseFullPath(const char* in_relative); - static std::string CollapseFullPath(const char* in_relative, - const char* in_base); - - ///! return path of a full filename (no trailing slashes). - static std::string GetFilenamePath(const std::string&); - - - ///! return file name of a full filename (i.e. file name without path). - static std::string GetFilenameName(const std::string&); - - ///! Split a program from its arguments and handle spaces in the paths. - static void SplitProgramFromArgs(const char* path, - std::string& program, std::string& args); - - ///! return file extension of a full filename (dot included). - static std::string GetFilenameExtension(const std::string&); - - ///! return file extension of a full filename (dot included). - static std::string GetFilenameLastExtension(const std::string&); - - ///! return file name without extension of a full filename. - static std::string GetFilenameWithoutExtension(const std::string&); - - ///! return file name without its last (shortest) extension. - static std::string GetFilenameWithoutLastExtension(const std::string&); - - /** Return whether the path represents a full path (not relative). */ - static bool FileIsFullPath(const char*); - - static long int ModifiedTime(const char* filename); + ///! Copy a file. + static bool cmCopyFile(const char* source, const char* destination); /** * Run an executable command and put the stdout in output. @@ -319,13 +160,7 @@ public: bool verbose = true, int timeout = 0); static bool RunCommand(const char* command, std::string& output, int &retVal, const char* directory = 0, - bool verbose = true, int timeout = 0); - - ///! for windows return the short path for the given path, unix just a pass through - static bool GetShortPath(const char* path, std::string& result); - - ///! change directory the the directory specified - static int ChangeDirectory(const char* dir); + bool verbose = true, int timeout = 0); static void EnableMessages() { s_DisableMessages = false; } static void DisableMessages() { s_DisableMessages = true; } @@ -333,10 +168,6 @@ public: static void EnableRunCommandOutput() {s_DisableRunCommandOutput = false; } static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; } - /** Split a string on its newlines into multiple lines. Returns - false only if the last line stored had no newline. */ - static bool Split(const char* s, std::vector& l); - /** * Come constants for different file formats. */ @@ -360,8 +191,6 @@ public: */ static FileFormat GetFileFormat(const char* ext); - static std::string GetCurrentDateTime(const char* format); - /** * On Windows 9x we need a comspec (command.com) substitute to run * programs correctly. This string has to be constant available @@ -380,35 +209,9 @@ public: */ static void ReportLastSystemError(const char* m); - /** When building DEBUG with MSVC, this enables a hook that prevents - * error dialogs from popping up if the program is being run from - * DART. - */ - static void EnableMSVCDebugHook(); - - /** - * Read line from file. Make sure to get everything. Due to a buggy stream - * library on the HP and another on Mac OSX, we need this very carefully - * written version of getline. Returns true if any data were read before the - * end-of-file was reached. - */ - static bool GetLineFromStream(std::istream& istr, std::string& line); - -protected: - // these two functions can be called from ConvertToOutputPath - /** - * Convert the path to a string that can be used in a unix makefile. - * double slashes are removed, and spaces are escaped. - */ - static std::string ConvertToUnixOutputPath(const char*); - - /** - * Convert the path to string that can be used in a windows project or - * makefile. Double slashes are removed if they are not at the start of - * the string, the slashes are converted to windows style backslashes, and - * if there are spaces in the string it is double quoted. - */ - static std::string ConvertToWindowsOutputPath(const char*); + /** Split a string on its newlines into multiple lines. Returns + false only if the last line stored had no newline. */ + static bool Split(const char* s, std::vector& l); private: static bool s_RunCommandHideConsole; diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index e2848da..107e0c9 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/Source/cmTryCompileCommand.cxx @@ -18,6 +18,8 @@ #include "cmCacheManager.h" #include "cmListFileCache.h" +#include + int cmTryCompileCommand::CoreTryCompileCode( cmMakefile *mf, std::vector const& argv, bool clean) { @@ -263,7 +265,7 @@ void cmTryCompileCommand::CleanupFiles(const char* binDir) return; } - cmDirectory dir; + cmsys::Directory dir; dir.Load(binDir); size_t fileNum; for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) diff --git a/Tests/Complex/Executable/CMakeLists.txt b/Tests/Complex/Executable/CMakeLists.txt index 2011feb..fd51ff2 100644 --- a/Tests/Complex/Executable/CMakeLists.txt +++ b/Tests/Complex/Executable/CMakeLists.txt @@ -6,6 +6,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTEST_CXX_FLAGS") # Link to CMake lib LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source) +LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source/kwsys) # Use LINK_LIBRARIES instead of TARGET_LINK_LIBRARIES to SET(COMPLEX_LIBS CMakeTestLibrary;CMakeTestLibraryShared;CMakeTestCLibraryShared) LINK_LIBRARIES(${COMPLEX_LIBS}) @@ -13,9 +14,9 @@ LINK_LIBRARIES(${COMPLEX_LIBS}) ADD_EXECUTABLE(complex complex) IF (UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib ${CMAKE_DL_LIBS}) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys ${CMAKE_DL_LIBS}) ELSE(UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys) IF (NOT BORLAND) TARGET_LINK_LIBRARIES(complex rpcrt4.lib) ENDIF(NOT BORLAND) diff --git a/Tests/ComplexOneConfig/Executable/CMakeLists.txt b/Tests/ComplexOneConfig/Executable/CMakeLists.txt index 2011feb..fd51ff2 100644 --- a/Tests/ComplexOneConfig/Executable/CMakeLists.txt +++ b/Tests/ComplexOneConfig/Executable/CMakeLists.txt @@ -6,6 +6,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTEST_CXX_FLAGS") # Link to CMake lib LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source) +LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source/kwsys) # Use LINK_LIBRARIES instead of TARGET_LINK_LIBRARIES to SET(COMPLEX_LIBS CMakeTestLibrary;CMakeTestLibraryShared;CMakeTestCLibraryShared) LINK_LIBRARIES(${COMPLEX_LIBS}) @@ -13,9 +14,9 @@ LINK_LIBRARIES(${COMPLEX_LIBS}) ADD_EXECUTABLE(complex complex) IF (UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib ${CMAKE_DL_LIBS}) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys ${CMAKE_DL_LIBS}) ELSE(UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys) IF (NOT BORLAND) TARGET_LINK_LIBRARIES(complex rpcrt4.lib) ENDIF(NOT BORLAND) diff --git a/Tests/ComplexRelativePaths/Executable/CMakeLists.txt b/Tests/ComplexRelativePaths/Executable/CMakeLists.txt index 2011feb..fd51ff2 100644 --- a/Tests/ComplexRelativePaths/Executable/CMakeLists.txt +++ b/Tests/ComplexRelativePaths/Executable/CMakeLists.txt @@ -6,6 +6,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTEST_CXX_FLAGS") # Link to CMake lib LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source) +LINK_DIRECTORIES(${Complex_BINARY_DIR}/../../Source/kwsys) # Use LINK_LIBRARIES instead of TARGET_LINK_LIBRARIES to SET(COMPLEX_LIBS CMakeTestLibrary;CMakeTestLibraryShared;CMakeTestCLibraryShared) LINK_LIBRARIES(${COMPLEX_LIBS}) @@ -13,9 +14,9 @@ LINK_LIBRARIES(${COMPLEX_LIBS}) ADD_EXECUTABLE(complex complex) IF (UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib ${CMAKE_DL_LIBS}) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys ${CMAKE_DL_LIBS}) ELSE(UNIX) - TARGET_LINK_LIBRARIES(complex CMakeLib) + TARGET_LINK_LIBRARIES(complex CMakeLib cmsys) IF (NOT BORLAND) TARGET_LINK_LIBRARIES(complex rpcrt4.lib) ENDIF(NOT BORLAND) diff --git a/bootstrap b/bootstrap index 9afc733..8165ffa 100755 --- a/bootstrap +++ b/bootstrap @@ -33,7 +33,6 @@ CMAKE_SOURCES="\ cmRegularExpression \ cmSourceFile \ cmSystemTools \ - cmDirectory \ cmGlobalUnixMakefileGenerator \ cmLocalUnixMakefileGenerator \ cmCommands \ @@ -44,6 +43,24 @@ CMAKE_SOURCES="\ cmVariableWatch \ cmSourceGroup" +KWSYS_SOURCES="\ + Directory \ + RegularExpression \ + SystemTools" + +KWSYS_FILES="\ + Directory.hxx \ + Process.h \ + RegularExpression.hxx \ + StandardIncludes.hxx \ + SystemTools.hxx" + +KWSYS_STD_FILES=" + fstream \ + iosfwd \ + iostream \ + sstream" + cmake_system=`uname` cmake_source_dir=`echo $0 | sed -n '/\//{s/\/[^\/]*$//;p;}'` @@ -117,6 +134,8 @@ cmake_replace_string () mv -f "${OUTFILE}.tmp" "${OUTFILE}" fi fi + else + cmake_error "Cannot find file ${INFILE}" fi } @@ -251,6 +270,16 @@ if [ ! -d "${cmake_bootstrap_dir}" ]; then fi cd "${cmake_bootstrap_dir}" +[ -d "cmsys" ] || mkdir "cmsys" +if [ ! -d "cmsys" ]; then + cmake_error "Cannot create directory ${cmake_bootstrap_dir}/cmsys" +fi + +[ -d "cmsys/std" ] || mkdir "cmsys/std" +if [ ! -d "cmsys/std" ]; then + cmake_error "Cannot create directory ${cmake_bootstrap_dir}/cmsys/std" +fi + # Delete all the bootstrap files rm -f "${cmake_bootstrap_dir}/cmake_bootstrap.log" @@ -406,9 +435,12 @@ cmake_report cmConfigure.h.tmp " */" # Test for STD namespace if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags}" "${cmake_source_dir}/Modules/TestForSTDNamespace.cxx" >> cmake_bootstrap.log 2>&1; then cmake_report cmConfigure.h.tmp "/* #undef CMAKE_NO_STD_NAMESPACE */" + cmake_report cmConfigure.h.tmp "#define cmsys_std std" echo "${cmake_cxx_compiler} has STD namespace" else cmake_report cmConfigure.h.tmp "#define CMAKE_NO_STD_NAMESPACE 1" + cmake_report cmConfigure.h.tmp "#define KWSYS_NO_STD_NAMESPACE" + cmake_report cmConfigure.h.tmp "#define cmsys_std" echo "${cmake_cxx_compiler} does not have STD namespace" fi @@ -418,6 +450,8 @@ if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags}" "${cmake_source_di echo "${cmake_cxx_compiler} has ANSI stream headers" else cmake_report cmConfigure.h.tmp "#define CMAKE_NO_ANSI_STREAM_HEADERS 1" + cmake_report cmConfigure.h.tmp "#define KWSYS_NO_ANSI_STREAM_HEADERS 1" + cmake_report cmConfigure.h.tmp "#define cmsys_NO_ANSI_STREAM_HEADERS" echo "${cmake_cxx_compiler} does not have ANSI stream headers" fi @@ -432,6 +466,8 @@ if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags}" "${TMPFILE}.cxx" > echo "${cmake_cxx_compiler} has ANSI string streams" else cmake_report cmConfigure.h.tmp "#define CMAKE_NO_ANSI_STRING_STREAM 1" + cmake_report cmConfigure.h.tmp "#define KWSYS_NO_ANSI_STRING_STREAM 1" + cmake_report cmConfigure.h.tmp "#define cmsys_NO_ANSI_STRING_STREAM 1" echo "${cmake_cxx_compiler} does not have ANSI string streams" fi rm -f "${TMPFILE}.cxx" @@ -444,6 +480,11 @@ else cmake_report cmConfigure.h.tmp "#define CMAKE_NO_ANSI_FOR_SCOPE 1" echo "${cmake_cxx_compiler} does not have ANSI for scoping" fi +cmake_report cmConfigure.h.tmp "/* Defined if std namespace is the GCC hack. */" +cmake_report cmConfigure.h.tmp "#if defined(__GNUC__) && (__GNUC__ < 3)" +cmake_report cmConfigure.h.tmp "# define cmsys_FAKE_STD_NAMESPACE" +cmake_report cmConfigure.h.tmp "#endif" +cmake_report cmConfigure.h.tmp "#define kwsys_std cmsys_std" # Write CMake version for a in MAJOR MINOR PATCH; do @@ -458,12 +499,29 @@ if diff cmConfigure.h cmConfigure.h.tmp > /dev/null 2> /dev/null; then rm -f cmConfigure.h.tmp else mv -f cmConfigure.h.tmp cmConfigure.h + cp cmConfigure.h cmsys/Configure.hxx fi +# Prepare KWSYS +for a in ${KWSYS_FILES}; do + cmake_replace_string "${cmake_source_dir}/Source/kwsys/${a}.in" \ + "${cmake_bootstrap_dir}/cmsys/${a}" KWSYS_NAMESPACE cmsys +done +for a in ${KWSYS_STD_FILES}; do + cmake_replace_string "${cmake_source_dir}/Source/kwsys/kwsys_std_${a}.h.in" \ + "${cmake_bootstrap_dir}/cmsys/std/${a}" KWSYS_NAMESPACE cmsys +done +cmake_replace_string "${cmake_source_dir}/Source/kwsys/kwsys_std.h.in" \ + "${cmake_bootstrap_dir}/cmsys/std/stl.h.in" KWSYS_NAMESPACE cmsys +for a in string vector; do + cmake_replace_string "${cmake_bootstrap_dir}/cmsys/std/stl.h.in" \ + "${cmake_bootstrap_dir}/cmsys/std/${a}" KWSYS_STL_HEADER ${a} +done + # Generate Makefile dep="cmConfigure.h `cmake_escape \"${cmake_source_dir}\"`/Source/*.h" objs="" -for a in ${CMAKE_SOURCES}; do +for a in ${CMAKE_SOURCES} ${KWSYS_SOURCES}; do objs="${objs} ${a}.o" done @@ -483,6 +541,11 @@ for a in ${CMAKE_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done +for a in ${KWSYS_SOURCES}; do + src=`cmake_escape "${cmake_source_dir}/Source/kwsys/${a}.cxx"` + echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" + echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -I`cmake_escape \"${cmake_bootstrap_dir}/cmsys\"` -DKWSYS_NAMESPACE=cmsys -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" +done # Write prefix to Bootstrap.cmk/InitialConfigureFlags.cmake echo "SET (CMAKE_CONFIGURE_INSTALL_PREFIX \"${cmake_prefix_dir}\" CACHE PATH \"Install path prefix, prepended onto install directories, For CMake this will always override CMAKE_INSTALL_PREFIX in the cache.\")" > "${cmake_bootstrap_dir}/InitialConfigureFlags.cmake" -- cgit v0.12