ENH: move EstimateFormatLength to kwsys
[cmake.git] / Source / kwsys / SystemTools.cxx
blob40a93869c941843f3c749f6051c1982098f51708
1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: SystemTools.cxx,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(SystemTools.hxx)
16 #include KWSYS_HEADER(Directory.hxx)
18 #include KWSYS_HEADER(ios/iostream)
19 #include KWSYS_HEADER(ios/fstream)
20 #include KWSYS_HEADER(ios/sstream)
22 #ifdef _MSC_VER
23 # pragma warning (disable: 4786)
24 #endif
26 #include <ctype.h>
27 #include <errno.h>
28 #ifdef __QNX__
29 # include <malloc.h> /* for malloc/free on QNX */
30 #endif
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <time.h>
37 // support for realpath call
38 #ifndef _WIN32
39 #include <limits.h>
40 #include <sys/param.h>
41 #include <sys/wait.h>
42 #include <sys/ioctl.h>
43 #include <unistd.h>
44 #include <termios.h>
45 #endif
47 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__))
48 #include <io.h>
49 #include <windows.h>
50 #include <direct.h>
51 #define _unlink unlink
52 inline int Mkdir(const char* dir)
54 return _mkdir(dir);
56 inline int Rmdir(const char* dir)
58 return _rmdir(dir);
60 inline const char* Getcwd(char* buf, unsigned int len)
62 return _getcwd(buf, len);
64 inline int Chdir(const char* dir)
66 #if defined(__BORLANDC__)
67 return chdir(dir);
68 #else
69 return _chdir(dir);
70 #endif
72 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
74 char *ptemp;
75 char fullpath[MAX_PATH];
76 if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
78 resolved_path = fullpath;
79 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
82 #else
83 #include <sys/types.h>
84 #include <fcntl.h>
85 #include <unistd.h>
86 inline int Mkdir(const char* dir)
88 return mkdir(dir, 00777);
90 inline int Rmdir(const char* dir)
92 return rmdir(dir);
94 inline const char* Getcwd(char* buf, unsigned int len)
96 return getcwd(buf, len);
98 inline int Chdir(const char* dir)
100 return chdir(dir);
102 inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
104 # ifdef MAXPATHLEN
105 char resolved_name[MAXPATHLEN];
106 # else
107 # ifdef PATH_MAX
108 char resolved_name[PATH_MAX];
109 # else
110 char resolved_name[5024];
111 # endif //PATH_MAX
112 # endif //MAXPATHLEN
114 realpath(path, resolved_name);
115 resolved_path = resolved_name;
117 #endif
119 #if !defined(_WIN32) && defined(__COMO__)
120 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
121 extern "C"
123 extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
124 extern int pclose (FILE *__stream) __THROW;
125 extern char *realpath (__const char *__restrict __name,
126 char *__restrict __resolved) __THROW;
127 extern char *strdup (__const char *__s) __THROW;
128 extern int putenv (char *__string) __THROW;
130 #endif
132 /* Implement floattime() for various platforms */
133 // Taken from Python 2.1.3
135 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
136 # include <sys/timeb.h>
137 # define HAVE_FTIME
138 # if defined( __BORLANDC__)
139 # define FTIME ftime
140 # define TIMEB timeb
141 # else // Visual studio?
142 # define FTIME _ftime
143 # define TIMEB _timeb
144 # endif
145 #elif defined( __CYGWIN__ ) || defined( __linux__ )
146 # include <sys/time.h>
147 # include <time.h>
148 # define HAVE_GETTIMEOFDAY
149 #endif
151 namespace KWSYS_NAMESPACE
154 class SystemToolsTranslationMap :
155 public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
159 double
160 SystemTools::GetTime(void)
162 /* There are three ways to get the time:
163 (1) gettimeofday() -- resolution in microseconds
164 (2) ftime() -- resolution in milliseconds
165 (3) time() -- resolution in seconds
166 In all cases the return value is a float in seconds.
167 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
168 fail, so we fall back on ftime() or time().
169 Note: clock resolution does not imply clock accuracy! */
170 #ifdef HAVE_GETTIMEOFDAY
172 struct timeval t;
173 #ifdef GETTIMEOFDAY_NO_TZ
174 if (gettimeofday(&t) == 0)
175 return (double)t.tv_sec + t.tv_usec*0.000001;
176 #else /* !GETTIMEOFDAY_NO_TZ */
177 if (gettimeofday(&t, (struct timezone *)NULL) == 0)
178 return (double)t.tv_sec + t.tv_usec*0.000001;
179 #endif /* !GETTIMEOFDAY_NO_TZ */
181 #endif /* !HAVE_GETTIMEOFDAY */
183 #if defined(HAVE_FTIME)
184 struct TIMEB t;
185 ::FTIME(&t);
186 return (double)t.time + (double)t.millitm * (double)0.001;
187 #else /* !HAVE_FTIME */
188 time_t secs;
189 time(&secs);
190 return (double)secs;
191 #endif /* !HAVE_FTIME */
195 // adds the elements of the env variable path to the arg passed in
196 void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
198 #if defined(_WIN32) && !defined(__CYGWIN__)
199 const char* pathSep = ";";
200 #else
201 const char* pathSep = ":";
202 #endif
203 if(!env)
205 env = "PATH";
207 const char* cpathEnv = SystemTools::GetEnv(env);
208 if ( !cpathEnv )
210 return;
213 kwsys_stl::string pathEnv = cpathEnv;
215 // A hack to make the below algorithm work.
216 if(pathEnv[pathEnv.length()-1] != ':')
218 pathEnv += pathSep;
220 kwsys_stl::string::size_type start =0;
221 bool done = false;
222 while(!done)
224 kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
225 if(endpos != kwsys_stl::string::npos)
227 path.push_back(pathEnv.substr(start, endpos-start));
228 start = endpos+1;
230 else
232 done = true;
235 for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
236 i != path.end(); ++i)
238 SystemTools::ConvertToUnixSlashes(*i);
242 const char* SystemTools::GetEnv(const char* key)
244 return getenv(key);
247 bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
249 const char* v = getenv(key);
250 if(v)
252 result = v;
253 return true;
255 else
257 return false;
261 const char* SystemTools::GetExecutableExtension()
263 #if defined(_WIN32) || defined(__CYGWIN__)
264 return ".exe";
265 #else
266 return "";
267 #endif
271 bool SystemTools::MakeDirectory(const char* path)
273 if(SystemTools::FileExists(path))
275 return true;
277 kwsys_stl::string dir = path;
278 if(dir.size() == 0)
280 return false;
282 SystemTools::ConvertToUnixSlashes(dir);
284 kwsys_stl::string::size_type pos = dir.find(':');
285 if(pos == kwsys_stl::string::npos)
287 pos = 0;
289 kwsys_stl::string topdir;
290 while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
292 topdir = dir.substr(0, pos);
293 Mkdir(topdir.c_str());
294 pos++;
296 if(dir[dir.size()-1] == '/')
298 topdir = dir.substr(0, dir.size());
300 else
302 topdir = dir;
304 if(Mkdir(topdir.c_str()) != 0)
306 // There is a bug in the Borland Run time library which makes MKDIR
307 // return EACCES when it should return EEXISTS
308 // if it is some other error besides directory exists
309 // then return false
310 if( (errno != EEXIST)
311 #ifdef __BORLANDC__
312 && (errno != EACCES)
313 #endif
316 return false;
319 return true;
323 // replace replace with with as many times as it shows up in source.
324 // write the result into source.
325 void SystemTools::ReplaceString(kwsys_stl::string& source,
326 const char* replace,
327 const char* with)
329 const char *src = source.c_str();
330 char *searchPos = const_cast<char *>(strstr(src,replace));
332 // get out quick if string is not found
333 if (!searchPos)
335 return;
338 // perform replacements until done
339 size_t replaceSize = strlen(replace);
340 char *orig = strdup(src);
341 char *currentPos = orig;
342 searchPos = searchPos - src + orig;
344 // initialize the result
345 source.erase(source.begin(),source.end());
348 *searchPos = '\0';
349 source += currentPos;
350 currentPos = searchPos + replaceSize;
351 // replace
352 source += with;
353 searchPos = strstr(currentPos,replace);
355 while (searchPos);
357 // copy any trailing text
358 source += currentPos;
359 free(orig);
362 // Read a registry value.
363 // Example :
364 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
365 // => will return the data of the "default" value of the key
366 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
367 // => will return the data of the "Root" value of the key
369 #if defined(_WIN32) && !defined(__CYGWIN__)
370 bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value)
373 kwsys_stl::string primary = key;
374 kwsys_stl::string second;
375 kwsys_stl::string valuename;
377 size_t start = primary.find("\\");
378 if (start == kwsys_stl::string::npos)
380 return false;
383 size_t valuenamepos = primary.find(";");
384 if (valuenamepos != kwsys_stl::string::npos)
386 valuename = primary.substr(valuenamepos+1);
389 second = primary.substr(start+1, valuenamepos-start-1);
390 primary = primary.substr(0, start);
392 HKEY primaryKey = HKEY_CURRENT_USER;
393 if (primary == "HKEY_CURRENT_USER")
395 primaryKey = HKEY_CURRENT_USER;
397 if (primary == "HKEY_CURRENT_CONFIG")
399 primaryKey = HKEY_CURRENT_CONFIG;
401 if (primary == "HKEY_CLASSES_ROOT")
403 primaryKey = HKEY_CLASSES_ROOT;
405 if (primary == "HKEY_LOCAL_MACHINE")
407 primaryKey = HKEY_LOCAL_MACHINE;
409 if (primary == "HKEY_USERS")
411 primaryKey = HKEY_USERS;
414 HKEY hKey;
415 if(RegOpenKeyEx(primaryKey,
416 second.c_str(),
418 KEY_READ,
419 &hKey) != ERROR_SUCCESS)
421 return false;
423 else
425 DWORD dwType, dwSize;
426 dwSize = 1023;
427 char data[1024];
428 if(RegQueryValueEx(hKey,
429 (LPTSTR)valuename.c_str(),
430 NULL,
431 &dwType,
432 (BYTE *)data,
433 &dwSize) == ERROR_SUCCESS)
435 if (dwType == REG_SZ)
437 value = data;
438 RegCloseKey(hKey);
439 return true;
443 return false;
445 #else
446 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &)
448 return false;
450 #endif
453 // Write a registry value.
454 // Example :
455 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
456 // => will set the data of the "default" value of the key
457 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
458 // => will set the data of the "Root" value of the key
460 #if defined(_WIN32) && !defined(__CYGWIN__)
461 bool SystemTools::WriteRegistryValue(const char *key, const char *value)
463 kwsys_stl::string primary = key;
464 kwsys_stl::string second;
465 kwsys_stl::string valuename;
467 size_t start = primary.find("\\");
468 if (start == kwsys_stl::string::npos)
470 return false;
473 size_t valuenamepos = primary.find(";");
474 if (valuenamepos != kwsys_stl::string::npos)
476 valuename = primary.substr(valuenamepos+1);
479 second = primary.substr(start+1, valuenamepos-start-1);
480 primary = primary.substr(0, start);
482 HKEY primaryKey = HKEY_CURRENT_USER;
483 if (primary == "HKEY_CURRENT_USER")
485 primaryKey = HKEY_CURRENT_USER;
487 if (primary == "HKEY_CURRENT_CONFIG")
489 primaryKey = HKEY_CURRENT_CONFIG;
491 if (primary == "HKEY_CLASSES_ROOT")
493 primaryKey = HKEY_CLASSES_ROOT;
495 if (primary == "HKEY_LOCAL_MACHINE")
497 primaryKey = HKEY_LOCAL_MACHINE;
499 if (primary == "HKEY_USERS")
501 primaryKey = HKEY_USERS;
504 HKEY hKey;
505 DWORD dwDummy;
506 if(RegCreateKeyEx(primaryKey,
507 second.c_str(),
510 REG_OPTION_NON_VOLATILE,
511 KEY_WRITE,
512 NULL,
513 &hKey,
514 &dwDummy) != ERROR_SUCCESS)
516 return false;
519 if(RegSetValueEx(hKey,
520 (LPTSTR)valuename.c_str(),
522 REG_SZ,
523 (CONST BYTE *)value,
524 (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
526 return true;
528 return false;
530 #else
531 bool SystemTools::WriteRegistryValue(const char *, const char *)
533 return false;
535 #endif
537 // Delete a registry value.
538 // Example :
539 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
540 // => will delete the data of the "default" value of the key
541 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
542 // => will delete the data of the "Root" value of the key
544 #if defined(_WIN32) && !defined(__CYGWIN__)
545 bool SystemTools::DeleteRegistryValue(const char *key)
547 kwsys_stl::string primary = key;
548 kwsys_stl::string second;
549 kwsys_stl::string valuename;
551 size_t start = primary.find("\\");
552 if (start == kwsys_stl::string::npos)
554 return false;
557 size_t valuenamepos = primary.find(";");
558 if (valuenamepos != kwsys_stl::string::npos)
560 valuename = primary.substr(valuenamepos+1);
563 second = primary.substr(start+1, valuenamepos-start-1);
564 primary = primary.substr(0, start);
566 HKEY primaryKey = HKEY_CURRENT_USER;
567 if (primary == "HKEY_CURRENT_USER")
569 primaryKey = HKEY_CURRENT_USER;
571 if (primary == "HKEY_CURRENT_CONFIG")
573 primaryKey = HKEY_CURRENT_CONFIG;
575 if (primary == "HKEY_CLASSES_ROOT")
577 primaryKey = HKEY_CLASSES_ROOT;
579 if (primary == "HKEY_LOCAL_MACHINE")
581 primaryKey = HKEY_LOCAL_MACHINE;
583 if (primary == "HKEY_USERS")
585 primaryKey = HKEY_USERS;
588 HKEY hKey;
589 if(RegOpenKeyEx(primaryKey,
590 second.c_str(),
592 KEY_WRITE,
593 &hKey) != ERROR_SUCCESS)
595 return false;
597 else
599 if(RegDeleteValue(hKey,
600 (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
602 RegCloseKey(hKey);
603 return true;
606 return false;
608 #else
609 bool SystemTools::DeleteRegistryValue(const char *)
611 return false;
613 #endif
615 bool SystemTools::SameFile(const char* file1, const char* file2)
617 #ifdef _WIN32
618 HANDLE hFile1, hFile2;
620 hFile1 = CreateFile( file1,
621 GENERIC_READ,
622 FILE_SHARE_READ ,
623 NULL,
624 OPEN_EXISTING,
625 FILE_FLAG_BACKUP_SEMANTICS,
626 NULL
628 hFile2 = CreateFile( file2,
629 GENERIC_READ,
630 FILE_SHARE_READ,
631 NULL,
632 OPEN_EXISTING,
633 FILE_FLAG_BACKUP_SEMANTICS,
634 NULL
636 if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
638 if(hFile1 != INVALID_HANDLE_VALUE)
640 CloseHandle(hFile1);
642 if(hFile2 != INVALID_HANDLE_VALUE)
644 CloseHandle(hFile2);
646 return false;
649 BY_HANDLE_FILE_INFORMATION fiBuf1;
650 BY_HANDLE_FILE_INFORMATION fiBuf2;
651 GetFileInformationByHandle( hFile1, &fiBuf1 );
652 GetFileInformationByHandle( hFile2, &fiBuf2 );
653 CloseHandle(hFile1);
654 CloseHandle(hFile2);
655 return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
656 fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
657 fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
658 #else
659 struct stat fileStat1, fileStat2;
660 if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
662 // see if the files are the same file
663 // check the device inode and size
664 if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
665 memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
666 fileStat2.st_size == fileStat1.st_size
669 return true;
672 return false;
673 #endif
677 // return true if the file exists
678 bool SystemTools::FileExists(const char* filename)
680 #ifdef _MSC_VER
681 # define access _access
682 #endif
683 #ifndef R_OK
684 # define R_OK 04
685 #endif
686 if ( access(filename, R_OK) != 0 )
688 return false;
690 else
692 return true;
697 bool SystemTools::FileTimeCompare(const char* f1, const char* f2,
698 int* result)
700 // Default to same time.
701 *result = 0;
702 #if !defined(_WIN32) || defined(__CYGWIN__)
703 // POSIX version. Use stat function to get file modification time.
704 struct stat s1;
705 if(stat(f1, &s1) != 0)
707 return false;
709 struct stat s2;
710 if(stat(f2, &s2) != 0)
712 return false;
714 # if KWSYS_STAT_HAS_ST_MTIM
715 // Compare using nanosecond resolution.
716 if(s1.st_mtim.tv_sec < s2.st_mtim.tv_sec)
718 *result = -1;
720 else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec)
722 *result = 1;
724 else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec)
726 *result = -1;
728 else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec)
730 *result = 1;
732 # else
733 // Compare using 1 second resolution.
734 if(s1.st_mtime < s2.st_mtime)
736 *result = -1;
738 else if(s1.st_mtime > s2.st_mtime)
740 *result = 1;
742 # endif
743 #else
744 // Windows version. Create file handles and get the modification times.
745 HANDLE hf1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ,
746 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
747 NULL);
748 if(hf1 == INVALID_HANDLE_VALUE)
750 return false;
752 FILETIME tf1;
753 if(!GetFileTime(hf1, 0, 0, &tf1))
755 CloseHandle(hf1);
756 return false;
758 CloseHandle(hf1);
759 HANDLE hf2 = CreateFile(f2, GENERIC_READ, FILE_SHARE_READ,
760 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
761 NULL);
762 if(hf2 == INVALID_HANDLE_VALUE)
764 return false;
766 FILETIME tf2;
767 if(!GetFileTime(hf2, 0, 0, &tf2))
769 CloseHandle(hf2);
770 return false;
772 CloseHandle(hf2);
774 // Compare the file times using resolution provided by system call.
775 *result = (int)CompareFileTime(&tf1, &tf2);
776 #endif
777 return true;
781 // Return a capitalized string (i.e the first letter is uppercased, all other
782 // are lowercased)
783 kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
785 kwsys_stl::string n;
786 if(s.size() == 0)
788 return n;
790 n.resize(s.size());
791 n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
792 for (size_t i = 1; i < s.size(); i++)
794 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
796 return n;
799 // Return capitalized words
800 kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s)
802 kwsys_stl::string n(s);
803 for (size_t i = 0; i < s.size(); i++)
805 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
807 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
810 return n;
813 // Return uncapitalized words
814 kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s)
816 kwsys_stl::string n(s);
817 for (size_t i = 0; i < s.size(); i++)
819 if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1])))
821 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
824 return n;
827 kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords(
828 const kwsys_stl::string& s)
830 kwsys_stl::string n;
831 if (s.size())
833 n.reserve(s.size());
834 n += s[0];
835 for (size_t i = 1; i < s.size(); i++)
837 if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1]))
839 n += ' ';
841 n += s[i];
844 return n;
847 char* SystemTools::AppendStrings(const char* str1, const char* str2)
849 if (!str1)
851 return SystemTools::DuplicateString(str2);
853 if (!str2)
855 return SystemTools::DuplicateString(str1);
857 size_t len1 = strlen(str1);
858 char *newstr = new char[len1 + strlen(str2) + 1];
859 if (!newstr)
861 return 0;
863 strcpy(newstr, str1);
864 strcat(newstr + len1, str2);
865 return newstr;
868 char* SystemTools::AppendStrings(
869 const char* str1, const char* str2, const char* str3)
871 if (!str1)
873 return SystemTools::AppendStrings(str2, str3);
875 if (!str2)
877 return SystemTools::AppendStrings(str1, str3);
879 if (!str3)
881 return SystemTools::AppendStrings(str1, str2);
884 size_t len1 = strlen(str1), len2 = strlen(str2);
885 char *newstr = new char[len1 + len2 + strlen(str3) + 1];
886 if (!newstr)
888 return 0;
890 strcpy(newstr, str1);
891 strcat(newstr + len1, str2);
892 strcat(newstr + len1 + len2, str3);
893 return newstr;
896 // Return a lower case string
897 kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
899 kwsys_stl::string n;
900 n.resize(s.size());
901 for (size_t i = 0; i < s.size(); i++)
903 n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
905 return n;
908 // Return a lower case string
909 kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
911 kwsys_stl::string n;
912 n.resize(s.size());
913 for (size_t i = 0; i < s.size(); i++)
915 n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
917 return n;
920 // Count char in string
921 size_t SystemTools::CountChar(const char* str, char c)
923 size_t count = 0;
925 if (str)
927 while (*str)
929 if (*str == c)
931 ++count;
933 ++str;
936 return count;
939 // Remove chars in string
940 char* SystemTools::RemoveChars(const char* str, const char *toremove)
942 if (!str)
944 return NULL;
946 char *clean_str = new char [strlen(str) + 1];
947 char *ptr = clean_str;
948 while (*str)
950 const char *str2 = toremove;
951 while (*str2 && *str != *str2)
953 ++str2;
955 if (!*str2)
957 *ptr++ = *str;
959 ++str;
961 *ptr = '\0';
962 return clean_str;
965 // Remove chars in string
966 char* SystemTools::RemoveCharsButUpperHex(const char* str)
968 if (!str)
970 return 0;
972 char *clean_str = new char [strlen(str) + 1];
973 char *ptr = clean_str;
974 while (*str)
976 if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'H'))
978 *ptr++ = *str;
980 ++str;
982 *ptr = '\0';
983 return clean_str;
986 // Replace chars in string
987 char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement)
989 if (str)
991 char *ptr = str;
992 while (*ptr)
994 const char *ptr2 = toreplace;
995 while (*ptr2)
997 if (*ptr == *ptr2)
999 *ptr = replacement;
1001 ++ptr2;
1003 ++ptr;
1006 return str;
1009 // Returns if string starts with another string
1010 bool SystemTools::StringStartsWith(const char* str1, const char* str2)
1012 if (!str1 || !str2)
1014 return false;
1016 size_t len1 = strlen(str1), len2 = strlen(str2);
1017 return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false;
1020 // Returns if string ends with another string
1021 bool SystemTools::StringEndsWith(const char* str1, const char* str2)
1023 if (!str1 || !str2)
1025 return false;
1027 size_t len1 = strlen(str1), len2 = strlen(str2);
1028 return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false;
1031 // Returns a pointer to the last occurence of str2 in str1
1032 const char* SystemTools::FindLastString(const char* str1, const char* str2)
1034 if (!str1 || !str2)
1036 return NULL;
1039 size_t len1 = strlen(str1), len2 = strlen(str2);
1040 if (len1 >= len2)
1042 const char *ptr = str1 + len1 - len2;
1045 if (!strncmp(ptr, str2, len2))
1047 return ptr;
1049 } while (ptr-- != str1);
1052 return NULL;
1055 // Duplicate string
1056 char* SystemTools::DuplicateString(const char* str)
1058 if (str)
1060 char *newstr = new char [strlen(str) + 1];
1061 return strcpy(newstr, str);
1063 return NULL;
1066 // Return a cropped string
1067 kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
1068 size_t max_len)
1070 if (!s.size() || max_len == 0 || max_len >= s.size())
1072 return s;
1075 kwsys_stl::string n;
1076 n.reserve(max_len);
1078 size_t middle = max_len / 2;
1080 n += s.substr(0, middle);
1081 n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos);
1083 if (max_len > 2)
1085 n[middle] = '.';
1086 if (max_len > 3)
1088 n[middle - 1] = '.';
1089 if (max_len > 4)
1091 n[middle + 1] = '.';
1096 return n;
1099 //----------------------------------------------------------------------------
1100 int SystemTools::EstimateFormatLength(const char *format, va_list ap)
1102 if (!format)
1104 return 0;
1107 // Quick-hack attempt at estimating the length of the string.
1108 // Should never under-estimate.
1110 // Start with the length of the format string itself.
1112 int length = strlen(format);
1114 // Increase the length for every argument in the format.
1116 const char* cur = format;
1117 while(*cur)
1119 if(*cur++ == '%')
1121 // Skip "%%" since it doesn't correspond to a va_arg.
1122 if(*cur != '%')
1124 while(!int(isalpha(*cur)))
1126 ++cur;
1128 switch (*cur)
1130 case 's':
1132 // Check the length of the string.
1133 char* s = va_arg(ap, char*);
1134 if(s)
1136 length += strlen(s);
1138 } break;
1139 case 'e':
1140 case 'f':
1141 case 'g':
1143 // Assume the argument contributes no more than 64 characters.
1144 length += 64;
1146 // Eat the argument.
1147 static_cast<void>(va_arg(ap, double));
1148 } break;
1149 default:
1151 // Assume the argument contributes no more than 64 characters.
1152 length += 64;
1154 // Eat the argument.
1155 static_cast<void>(va_arg(ap, int));
1156 } break;
1160 // Move past the characters just tested.
1161 ++cur;
1165 return length;
1168 // convert windows slashes to unix slashes
1169 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
1171 kwsys_stl::string::size_type pos = 0;
1172 while((pos = path.find('\\', pos)) != kwsys_stl::string::npos)
1174 // make sure we don't convert an escaped space to a unix slash
1175 if(pos < path.size()-1)
1177 if(path[pos+1] != ' ')
1179 path[pos] = '/';
1182 pos++;
1184 // Remove all // from the path just like most unix shells
1185 int start_find;
1187 #ifdef _WIN32
1188 // However, on windows if the first characters are both slashes,
1189 // then keep them that way, so that network paths can be handled.
1190 start_find = 1;
1191 #else
1192 start_find = 0;
1193 #endif
1195 while((pos = path.find("//", start_find)) != kwsys_stl::string::npos)
1197 SystemTools::ReplaceString(path, "//", "/");
1200 // remove any trailing slash
1201 if(path.size() > 1 && path[path.size()-1] == '/')
1203 path = path.substr(0, path.size()-1);
1206 // if there is a tilda ~ then replace it with HOME
1207 if(path.find("~") == 0)
1209 if (getenv("HOME"))
1211 path = kwsys_stl::string(getenv("HOME")) + path.substr(1);
1216 // change // to /, and escape any spaces in the path
1217 kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
1219 kwsys_stl::string ret = path;
1221 // remove // except at the beginning might be a cygwin drive
1222 kwsys_stl::string::size_type pos = 1;
1223 while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
1225 ret.erase(pos, 1);
1227 // now escape spaces if there is a space in the path
1228 if(ret.find(" ") != kwsys_stl::string::npos)
1230 kwsys_stl::string result = "";
1231 char lastch = 1;
1232 for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
1234 // if it is already escaped then don't try to escape it again
1235 if(*ch == ' ' && lastch != '\\')
1237 result += '\\';
1239 result += *ch;
1240 lastch = *ch;
1242 ret = result;
1244 return ret;
1247 kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
1249 #if defined(_WIN32) && !defined(__CYGWIN__)
1250 return SystemTools::ConvertToWindowsOutputPath(path);
1251 #else
1252 return SystemTools::ConvertToUnixOutputPath(path);
1253 #endif
1256 // remove double slashes not at the start
1257 kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
1259 kwsys_stl::string ret = path;
1260 kwsys_stl::string::size_type pos = 0;
1261 // first convert all of the slashes
1262 while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
1264 ret[pos] = '\\';
1265 pos++;
1267 // check for really small paths
1268 if(ret.size() < 2)
1270 return ret;
1272 // now clean up a bit and remove double slashes
1273 // Only if it is not the first position in the path which is a network
1274 // path on windows
1275 pos = 1; // start at position 1
1276 if(ret[0] == '\"')
1278 pos = 2; // if the string is already quoted then start at 2
1279 if(ret.size() < 3)
1281 return ret;
1284 while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
1286 ret.erase(pos, 1);
1288 // now double quote the path if it has spaces in it
1289 // and is not already double quoted
1290 if(ret.find(" ") != kwsys_stl::string::npos
1291 && ret[0] != '\"')
1293 kwsys_stl::string result;
1294 result = "\"" + ret + "\"";
1295 ret = result;
1297 return ret;
1300 bool SystemTools::CopyFileIfDifferent(const char* source,
1301 const char* destination)
1303 if(SystemTools::FilesDiffer(source, destination))
1305 return SystemTools::CopyFileAlways(source, destination);
1307 return true;
1311 bool SystemTools::FilesDiffer(const char* source,
1312 const char* destination)
1314 struct stat statSource;
1315 if (stat(source, &statSource) != 0)
1317 return true;
1320 struct stat statDestination;
1321 if (stat(destination, &statDestination) != 0)
1323 return true;
1326 if(statSource.st_size != statDestination.st_size)
1328 return true;
1331 if(statSource.st_size == 0)
1333 return false;
1336 #if defined(_WIN32) || defined(__CYGWIN__)
1337 kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
1338 kwsys_ios::ios::in));
1339 kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
1340 kwsys_ios::ios::in));
1341 #else
1342 kwsys_ios::ifstream finSource(source);
1343 kwsys_ios::ifstream finDestination(destination);
1344 #endif
1345 if(!finSource || !finDestination)
1347 return true;
1350 char* source_buf = new char[statSource.st_size];
1351 char* dest_buf = new char[statSource.st_size];
1353 finSource.read(source_buf, statSource.st_size);
1354 finDestination.read(dest_buf, statSource.st_size);
1356 if(statSource.st_size != static_cast<long>(finSource.gcount()) ||
1357 statSource.st_size != static_cast<long>(finDestination.gcount()))
1359 // Failed to read files.
1360 delete [] source_buf;
1361 delete [] dest_buf;
1362 return true;
1364 int ret = memcmp((const void*)source_buf,
1365 (const void*)dest_buf,
1366 statSource.st_size);
1368 delete [] dest_buf;
1369 delete [] source_buf;
1371 return ret != 0;
1376 * Copy a file named by "source" to the file named by "destination".
1378 bool SystemTools::CopyFileAlways(const char* source, const char* destination)
1380 // If files are the same do not copy
1381 if ( SystemTools::SameFile(source, destination) )
1383 return true;
1386 mode_t perm = 0;
1387 bool perms = SystemTools::GetPermissions(source, perm);
1389 const int bufferSize = 4096;
1390 char buffer[bufferSize];
1392 // If destination is a directory, try to create a file with the same
1393 // name as the source in that directory.
1395 kwsys_stl::string new_destination;
1396 if(SystemTools::FileExists(destination) &&
1397 SystemTools::FileIsDirectory(destination))
1399 new_destination = destination;
1400 SystemTools::ConvertToUnixSlashes(new_destination);
1401 new_destination += '/';
1402 kwsys_stl::string source_name = source;
1403 new_destination += SystemTools::GetFilenameName(source_name);
1404 destination = new_destination.c_str();
1407 // Create destination directory
1409 kwsys_stl::string destination_dir = destination;
1410 destination_dir = SystemTools::GetFilenamePath(destination_dir);
1411 SystemTools::MakeDirectory(destination_dir.c_str());
1413 // Open files
1415 #if defined(_WIN32) || defined(__CYGWIN__)
1416 kwsys_ios::ifstream fin(source,
1417 kwsys_ios::ios::binary | kwsys_ios::ios::in);
1418 #else
1419 kwsys_ios::ifstream fin(source);
1420 #endif
1421 if(!fin)
1423 return false;
1426 // try and remove the destination file so that read only destination files
1427 // can be written to.
1428 // If the remove fails continue so that files in read only directories
1429 // that do not allow file removal can be modified.
1430 SystemTools::RemoveFile(destination);
1432 #if defined(_WIN32) || defined(__CYGWIN__)
1433 kwsys_ios::ofstream fout(destination,
1434 kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1435 #else
1436 kwsys_ios::ofstream fout(destination,
1437 kwsys_ios::ios::out | kwsys_ios::ios::trunc);
1438 #endif
1439 if(!fout)
1441 return false;
1444 // This copy loop is very sensitive on certain platforms with
1445 // slightly broken stream libraries (like HPUX). Normally, it is
1446 // incorrect to not check the error condition on the fin.read()
1447 // before using the data, but the fin.gcount() will be zero if an
1448 // error occurred. Therefore, the loop should be safe everywhere.
1449 while(fin)
1451 fin.read(buffer, bufferSize);
1452 if(fin.gcount())
1454 fout.write(buffer, fin.gcount());
1458 // Make sure the operating system has finished writing the file
1459 // before closing it. This will ensure the file is finished before
1460 // the check below.
1461 fout.flush();
1463 fin.close();
1464 fout.close();
1466 // More checks.
1467 struct stat statSource, statDestination;
1468 statSource.st_size = 12345;
1469 statDestination.st_size = 12345;
1470 if(stat(source, &statSource) != 0)
1472 return false;
1474 else if(stat(destination, &statDestination) != 0)
1476 return false;
1478 else if(statSource.st_size != statDestination.st_size)
1480 return false;
1482 if ( perms )
1484 if ( !SystemTools::SetPermissions(destination, perm) )
1486 return false;
1489 return true;
1493 * Copy a directory content from "source" directory to the directory named by
1494 * "destination".
1496 bool SystemTools::CopyADirectory(const char* source, const char* destination)
1498 Directory dir;
1499 dir.Load(source);
1500 size_t fileNum;
1501 if ( !SystemTools::MakeDirectory(destination) )
1503 return false;
1505 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
1507 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
1508 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
1510 kwsys_stl::string fullPath = source;
1511 fullPath += "/";
1512 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1513 if(SystemTools::FileIsDirectory(fullPath.c_str()))
1515 kwsys_stl::string fullDestPath = destination;
1516 fullDestPath += "/";
1517 fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1518 if (!SystemTools::CopyADirectory(fullPath.c_str(), fullDestPath.c_str()))
1520 return false;
1523 else
1525 if(!SystemTools::CopyFileAlways(fullPath.c_str(), destination))
1527 return false;
1533 return true;
1537 // return size of file; also returns zero if no file exists
1538 unsigned long SystemTools::FileLength(const char* filename)
1540 struct stat fs;
1541 if (stat(filename, &fs) != 0)
1543 return 0;
1545 else
1547 return static_cast<unsigned long>(fs.st_size);
1551 int SystemTools::Strucmp(const char *s1, const char *s2)
1553 // lifted from Graphvis http://www.graphviz.org
1554 while ((*s1 != '\0')
1555 && (tolower(*s1) == tolower(*s2)))
1557 s1++;
1558 s2++;
1561 return tolower(*s1) - tolower(*s2);
1565 // return file's modified time
1566 long int SystemTools::ModifiedTime(const char* filename)
1568 struct stat fs;
1569 if (stat(filename, &fs) != 0)
1571 return 0;
1573 else
1575 return (long int)fs.st_mtime;
1579 // return file's creation time
1580 long int SystemTools::CreationTime(const char* filename)
1582 struct stat fs;
1583 if (stat(filename, &fs) != 0)
1585 return 0;
1587 else
1589 return fs.st_ctime >= 0 ? (long int)fs.st_ctime : 0;
1593 bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt)
1595 if (!str || !tmt || strlen(str) < 12)
1597 return false;
1600 struct tm tmt2;
1602 // __DATE__
1603 // The compilation date of the current source file. The date is a string
1604 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1605 // dates generated by the library function asctime declared in TIME.H.
1607 // index: 012345678901
1608 // format: Mmm dd yyyy
1609 // example: Dec 19 2003
1611 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1613 char buffer[12];
1614 strcpy(buffer, str);
1616 buffer[3] = 0;
1617 char *ptr = strstr(month_names, buffer);
1618 if (!ptr)
1620 return false;
1623 int month = (ptr - month_names) / 3;
1624 int day = atoi(buffer + 4);
1625 int year = atoi(buffer + 7);
1627 tmt2.tm_isdst = -1;
1628 tmt2.tm_hour = 0;
1629 tmt2.tm_min = 0;
1630 tmt2.tm_sec = 0;
1631 tmt2.tm_wday = 0;
1632 tmt2.tm_yday = 0;
1633 tmt2.tm_mday = day;
1634 tmt2.tm_mon = month;
1635 tmt2.tm_year = year - 1900;
1637 *tmt = mktime(&tmt2);
1638 return true;
1641 bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt)
1643 if (!str || !tmt || strlen(str) < 27)
1645 return false;
1648 struct tm tmt2;
1650 // __TIMESTAMP__
1651 // The date and time of the last modification of the current source file,
1652 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
1653 /// where Ddd is the abbreviated day of the week and Date is an integer
1654 // from 1 to 31.
1656 // index: 0123456789
1657 // 0123456789
1658 // 0123456789
1659 // format: Ddd Mmm Date hh:mm:ss yyyy
1660 // example: Fri Dec 19 14:34:58 2003
1662 static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1664 char buffer[27];
1665 strcpy(buffer, str);
1667 buffer[7] = 0;
1668 char *ptr = strstr(month_names, buffer + 4);
1669 if (!ptr)
1671 return false;
1674 int month = (ptr - month_names) / 3;
1675 int day = atoi(buffer + 8);
1676 int hour = atoi(buffer + 11);
1677 int min = atoi(buffer + 14);
1678 int sec = atoi(buffer + 17);
1679 int year = atoi(buffer + 20);
1681 tmt2.tm_isdst = -1;
1682 tmt2.tm_hour = hour;
1683 tmt2.tm_min = min;
1684 tmt2.tm_sec = sec;
1685 tmt2.tm_wday = 0;
1686 tmt2.tm_yday = 0;
1687 tmt2.tm_mday = day;
1688 tmt2.tm_mon = month;
1689 tmt2.tm_year = year - 1900;
1691 *tmt = mktime(&tmt2);
1692 return true;
1695 kwsys_stl::string SystemTools::GetLastSystemError()
1697 int e = errno;
1698 return strerror(e);
1701 bool SystemTools::RemoveFile(const char* source)
1703 #ifdef _WIN32
1704 mode_t mode;
1705 if ( !SystemTools::GetPermissions(source, mode) )
1707 return false;
1709 /* Win32 unlink is stupid --- it fails if the file is read-only */
1710 SystemTools::SetPermissions(source, S_IWRITE);
1711 #endif
1712 bool res = unlink(source) != 0 ? false : true;
1713 #ifdef _WIN32
1714 if ( !res )
1716 SystemTools::SetPermissions(source, mode);
1718 #endif
1719 return res;
1722 bool SystemTools::RemoveADirectory(const char* source)
1724 Directory dir;
1725 dir.Load(source);
1726 size_t fileNum;
1727 for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
1729 if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
1730 strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
1732 kwsys_stl::string fullPath = source;
1733 fullPath += "/";
1734 fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
1735 if(SystemTools::FileIsDirectory(fullPath.c_str()))
1737 if (!SystemTools::RemoveADirectory(fullPath.c_str()))
1739 return false;
1742 else
1744 if(!SystemTools::RemoveFile(fullPath.c_str()))
1746 return false;
1752 return (Rmdir(source) == 0);
1756 * Find the file the given name. Searches the given path and then
1757 * the system search path. Returns the full path to the file if it is
1758 * found. Otherwise, the empty string is returned.
1760 kwsys_stl::string SystemTools
1761 ::FindFile(const char* name,
1762 const kwsys_stl::vector<kwsys_stl::string>& userPaths)
1764 // Add the system search path to our path first
1765 kwsys_stl::vector<kwsys_stl::string> path;
1766 SystemTools::GetPath(path, "CMAKE_FILE_PATH");
1767 SystemTools::GetPath(path);
1768 // now add the additional paths
1769 path.insert(path.end(), userPaths.begin(), userPaths.end());
1770 // now look for the file
1771 kwsys_stl::string tryPath;
1772 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
1773 p != path.end(); ++p)
1775 tryPath = *p;
1776 tryPath += "/";
1777 tryPath += name;
1778 if(SystemTools::FileExists(tryPath.c_str()) &&
1779 !SystemTools::FileIsDirectory(tryPath.c_str()))
1781 return SystemTools::CollapseFullPath(tryPath.c_str());
1784 // Couldn't find the file.
1785 return "";
1789 * Find the executable with the given name. Searches the given path and then
1790 * the system search path. Returns the full path to the executable if it is
1791 * found. Otherwise, the empty string is returned.
1793 kwsys_stl::string SystemTools::FindProgram(
1794 const char* name,
1795 const kwsys_stl::vector<kwsys_stl::string>& userPaths,
1796 bool no_system_path)
1798 if(!name)
1800 return "";
1802 // See if the executable exists as written.
1803 if(SystemTools::FileExists(name) &&
1804 !SystemTools::FileIsDirectory(name))
1806 return SystemTools::CollapseFullPath(name);
1808 kwsys_stl::string tryPath = name;
1809 tryPath += SystemTools::GetExecutableExtension();
1810 if(SystemTools::FileExists(tryPath.c_str()) &&
1811 !SystemTools::FileIsDirectory(tryPath.c_str()))
1813 return SystemTools::CollapseFullPath(tryPath.c_str());
1815 kwsys_stl::vector<kwsys_stl::string> path;
1816 SystemTools::GetPath(path, "CMAKE_PROGRAM_PATH");
1817 // Add the system search path to our path.
1818 if (!no_system_path)
1820 SystemTools::GetPath(path);
1823 // now add the additional paths
1824 path.insert(path.end(), userPaths.begin(), userPaths.end());
1826 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
1827 p != path.end(); ++p)
1829 tryPath = *p;
1830 tryPath += "/";
1831 tryPath += name;
1832 if(SystemTools::FileExists(tryPath.c_str()) &&
1833 !SystemTools::FileIsDirectory(tryPath.c_str()))
1835 return SystemTools::CollapseFullPath(tryPath.c_str());
1837 #ifdef _WIN32
1838 tryPath += ".com";
1839 if(SystemTools::FileExists(tryPath.c_str()) &&
1840 !SystemTools::FileIsDirectory(tryPath.c_str()))
1842 return SystemTools::CollapseFullPath(tryPath.c_str());
1844 tryPath = *p;
1845 tryPath += "/";
1846 tryPath += name;
1847 #endif
1848 tryPath += SystemTools::GetExecutableExtension();
1849 if(SystemTools::FileExists(tryPath.c_str()) &&
1850 !SystemTools::FileIsDirectory(tryPath.c_str()))
1852 return SystemTools::CollapseFullPath(tryPath.c_str());
1856 // Couldn't find the program.
1857 return "";
1862 * Find the library with the given name. Searches the given path and then
1863 * the system search path. Returns the full path to the library if it is
1864 * found. Otherwise, the empty string is returned.
1866 kwsys_stl::string SystemTools
1867 ::FindLibrary(const char* name,
1868 const kwsys_stl::vector<kwsys_stl::string>& userPaths)
1870 // See if the executable exists as written.
1871 if(SystemTools::FileExists(name) &&
1872 !SystemTools::FileIsDirectory(name))
1874 return SystemTools::CollapseFullPath(name);
1877 // Add the system search path to our path.
1878 kwsys_stl::vector<kwsys_stl::string> path;
1879 SystemTools::GetPath(path);
1880 // now add the additional paths
1881 path.insert(path.end(), userPaths.begin(), userPaths.end());
1882 kwsys_stl::string tryPath;
1883 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
1884 p != path.end(); ++p)
1886 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
1887 tryPath = *p;
1888 tryPath += "/";
1889 tryPath += name;
1890 tryPath += ".lib";
1891 if(SystemTools::FileExists(tryPath.c_str())
1892 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1894 return SystemTools::CollapseFullPath(tryPath.c_str());
1896 #else
1897 tryPath = *p;
1898 tryPath += "/lib";
1899 tryPath += name;
1900 tryPath += ".so";
1901 if(SystemTools::FileExists(tryPath.c_str())
1902 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1904 return SystemTools::CollapseFullPath(tryPath.c_str());
1906 tryPath = *p;
1907 tryPath += "/lib";
1908 tryPath += name;
1909 tryPath += ".a";
1910 if(SystemTools::FileExists(tryPath.c_str())
1911 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1913 return SystemTools::CollapseFullPath(tryPath.c_str());
1915 tryPath = *p;
1916 tryPath += "/lib";
1917 tryPath += name;
1918 tryPath += ".sl";
1919 if(SystemTools::FileExists(tryPath.c_str())
1920 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1922 return SystemTools::CollapseFullPath(tryPath.c_str());
1924 tryPath = *p;
1925 tryPath += "/lib";
1926 tryPath += name;
1927 tryPath += ".dylib";
1928 if(SystemTools::FileExists(tryPath.c_str())
1929 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1931 return SystemTools::CollapseFullPath(tryPath.c_str());
1933 tryPath = *p;
1934 tryPath += "/lib";
1935 tryPath += name;
1936 tryPath += ".dll";
1937 if(SystemTools::FileExists(tryPath.c_str())
1938 && !SystemTools::FileIsDirectory(tryPath.c_str()))
1940 return SystemTools::CollapseFullPath(tryPath.c_str());
1942 #endif
1945 // Couldn't find the library.
1946 return "";
1949 bool SystemTools::FileIsDirectory(const char* name)
1951 struct stat fs;
1952 if(stat(name, &fs) == 0)
1954 #if _WIN32
1955 return ((fs.st_mode & _S_IFDIR) != 0);
1956 #else
1957 return S_ISDIR(fs.st_mode);
1958 #endif
1960 else
1962 return false;
1966 int SystemTools::ChangeDirectory(const char *dir)
1968 return Chdir(dir);
1971 kwsys_stl::string SystemTools::GetCurrentWorkingDirectory()
1973 char buf[2048];
1974 const char* cwd = Getcwd(buf, 2048);
1975 kwsys_stl::string path;
1976 if ( cwd )
1978 path = cwd;
1981 return SystemTools::CollapseFullPath(path.c_str());
1984 kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
1986 kwsys_stl::string dir, file;
1987 SystemTools::SplitProgramPath(in_name, dir, file);
1988 return dir;
1991 bool SystemTools::SplitProgramPath(const char* in_name,
1992 kwsys_stl::string& dir,
1993 kwsys_stl::string& file,
1994 bool)
1996 dir = in_name;
1997 file = "";
1998 SystemTools::ConvertToUnixSlashes(dir);
2000 if(!SystemTools::FileIsDirectory(dir.c_str()))
2002 kwsys_stl::string::size_type slashPos = dir.rfind("/");
2003 if(slashPos != kwsys_stl::string::npos)
2005 file = dir.substr(slashPos+1);
2006 dir = dir.substr(0, slashPos);
2008 else
2010 file = dir;
2011 dir = "";
2014 if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
2016 kwsys_stl::string oldDir = in_name;
2017 SystemTools::ConvertToUnixSlashes(oldDir);
2018 dir = in_name;
2019 return false;
2021 return true;
2024 bool SystemTools::FindProgramPath(const char* argv0,
2025 kwsys_stl::string& pathOut,
2026 kwsys_stl::string& errorMsg,
2027 const char* exeName,
2028 const char* buildDir,
2029 const char* installPrefix )
2031 kwsys_stl::vector<kwsys_stl::string> failures;
2032 kwsys_stl::string self = argv0;
2033 SystemTools::ConvertToUnixSlashes(self);
2034 failures.push_back(argv0);
2035 self = SystemTools::FindProgram(self.c_str());
2036 if(!SystemTools::FileExists(self.c_str()))
2038 if(buildDir)
2040 kwsys_stl::string intdir = ".";
2041 #ifdef CMAKE_INTDIR
2042 intdir = CMAKE_INTDIR;
2043 #endif
2044 self = buildDir;
2045 self += "/bin/";
2046 self += intdir;
2047 self += "/";
2048 self += exeName;
2049 self += SystemTools::GetExecutableExtension();
2052 if(installPrefix)
2054 if(!SystemTools::FileExists(self.c_str()))
2056 failures.push_back(self);
2057 self = installPrefix;
2058 self += "/bin/";
2059 self += exeName;
2062 if(!SystemTools::FileExists(self.c_str()))
2064 failures.push_back(self);
2065 kwsys_ios::ostringstream msg;
2066 msg << "Can not find the command line program " << exeName << "\n";
2067 msg << " argv[0] = \"" << argv0 << "\"\n";
2068 msg << " Attempted paths:\n";
2069 kwsys_stl::vector<kwsys_stl::string>::iterator i;
2070 for(i=failures.begin(); i != failures.end(); ++i)
2072 msg << " \"" << i->c_str() << "\"\n";
2074 errorMsg = msg.str();
2075 return false;
2077 pathOut = self;
2078 return true;
2082 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
2084 return SystemTools::CollapseFullPath(in_relative, 0);
2087 void SystemTools::AddTranslationPath(const char * a, const char * b)
2089 kwsys_stl::string path_a = a;
2090 kwsys_stl::string path_b = b;
2091 SystemTools::ConvertToUnixSlashes(path_a);
2092 SystemTools::ConvertToUnixSlashes(path_b);
2093 // First check this is a directory path, since we don't want the table to
2094 // grow too fat
2095 if( SystemTools::FileIsDirectory( path_a.c_str() ) )
2097 // Make sure the path is a full path and does not contain no '..'
2098 if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
2099 == kwsys_stl::string::npos )
2101 // Before inserting make sure path ends with '/'
2102 if(path_a.size() && path_a[path_a.size() -1] != '/')
2104 path_a += '/';
2106 if(path_b.size() && path_b[path_b.size() -1] != '/')
2108 path_b += '/';
2110 if( !(path_a == path_b) )
2112 SystemTools::TranslationMap->insert(
2113 SystemToolsTranslationMap::value_type(path_a, path_b));
2119 void SystemTools::AddKeepPath(const char* dir)
2121 kwsys_stl::string cdir = SystemTools::CollapseFullPath(dir);
2122 SystemTools::AddTranslationPath(cdir.c_str(), dir);
2125 void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
2127 // Do not translate paths that are too short to have meaningful
2128 // translations.
2129 if(path.size() < 2)
2131 return;
2134 // Always add a trailing slash before translation. It does not
2135 // matter if this adds an extra slash, but we do not want to
2136 // translate part of a directory (like the foo part of foo-dir).
2137 path += "/";
2139 // In case a file was specified we still have to go through this:
2140 // Now convert any path found in the table back to the one desired:
2141 kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
2142 for(it = SystemTools::TranslationMap->begin();
2143 it != SystemTools::TranslationMap->end();
2144 ++it )
2146 // We need to check of the path is a substring of the other path
2147 if(path.find( it->first ) == 0)
2149 path = path.replace( 0, it->first.size(), it->second);
2153 // Remove the trailing slash we added before.
2154 path.erase(path.end()-1, path.end());
2157 void
2158 SystemToolsAppendComponents(
2159 kwsys_stl::vector<kwsys_stl::string>& out_components,
2160 kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
2161 kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
2163 for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
2164 i != last; ++i)
2166 if(*i == "..")
2168 if(out_components.begin() != out_components.end())
2170 out_components.erase(out_components.end()-1, out_components.end());
2173 else if(*i != "." && *i != "")
2175 out_components.push_back(*i);
2180 kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
2181 const char* in_base)
2183 // Collect the output path components.
2184 kwsys_stl::vector<kwsys_stl::string> out_components;
2186 // Split the input path components.
2187 kwsys_stl::vector<kwsys_stl::string> path_components;
2188 SystemTools::SplitPath(in_path, path_components);
2190 // If the input path is relative, start with a base path.
2191 if(path_components[0].length() == 0)
2193 kwsys_stl::vector<kwsys_stl::string> base_components;
2194 if(in_base)
2196 // Use the given base path.
2197 SystemTools::SplitPath(in_base, base_components);
2199 else
2201 // Use the current working directory as a base path.
2202 char buf[2048];
2203 if(const char* cwd = Getcwd(buf, 2048))
2205 SystemTools::SplitPath(cwd, base_components);
2207 else
2209 // ??
2213 // Append base path components to the output path.
2214 out_components.push_back(base_components[0]);
2215 SystemToolsAppendComponents(out_components,
2216 base_components.begin()+1,
2217 base_components.end());
2220 // Append input path components to the output path.
2221 SystemToolsAppendComponents(out_components,
2222 path_components.begin(),
2223 path_components.end());
2225 // Transform the path back to a string.
2226 kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
2228 // Update the translation table with this potentially new path.
2229 SystemTools::AddTranslationPath(newPath.c_str(), in_path);
2230 SystemTools::CheckTranslationPath(newPath);
2232 // Return the reconstructed path.
2233 return newPath;
2236 //----------------------------------------------------------------------------
2237 void SystemTools::SplitPath(const char* p,
2238 kwsys_stl::vector<kwsys_stl::string>& components)
2240 components.clear();
2241 // Identify the root component.
2242 const char* c = p;
2243 if(c[0] == '/' && c[1] == '/')
2245 // Network path.
2246 components.push_back("//");
2247 c += 2;
2249 else if(c[0] == '/')
2251 // Unix path.
2252 components.push_back("/");
2253 c += 1;
2255 else if(c[0] && c[1] == ':' && c[2] == '/')
2257 // Windows path.
2258 kwsys_stl::string root = "_:/";
2259 root[0] = c[0];
2260 components.push_back(root);
2261 c += 3;
2263 else if(c[0] && c[1] == ':')
2265 // Path relative to a windows drive working directory.
2266 kwsys_stl::string root = "_:";
2267 root[0] = c[0];
2268 components.push_back(root);
2269 c += 2;
2271 else
2273 // Relative path.
2274 components.push_back("");
2277 // Parse the remaining components.
2278 const char* first = c;
2279 const char* last = first;
2280 for(;*last; ++last)
2282 if(*last == '/')
2284 // End of a component. Save it.
2285 components.push_back(kwsys_stl::string(first, last-first));
2286 first = last+1;
2290 // Save the last component unless there were no components.
2291 if(last != c)
2293 components.push_back(kwsys_stl::string(first, last-first));
2297 //----------------------------------------------------------------------------
2298 kwsys_stl::string
2299 SystemTools::JoinPath(const kwsys_stl::vector<kwsys_stl::string>& components)
2301 kwsys_stl::string result;
2302 if(components.size() > 0)
2304 result += components[0];
2306 if(components.size() > 1)
2308 result += components[1];
2310 for(unsigned int i=2; i < components.size(); ++i)
2312 result += "/";
2313 result += components[i];
2315 return result;
2318 //----------------------------------------------------------------------------
2319 bool SystemTools::ComparePath(const char* c1, const char* c2)
2321 #if defined(_WIN32) || defined(__APPLE__)
2322 return SystemTools::Strucmp(c1, c2) == 0;
2323 #else
2324 return strcmp(c1, c2) == 0;
2325 #endif
2328 bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
2330 kwsys_stl::string data(str);
2331 kwsys_stl::string::size_type lpos = 0;
2332 while(lpos < data.length())
2334 kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
2335 if(rpos == kwsys_stl::string::npos)
2337 // Line ends at end of string without a newline.
2338 lines.push_back(data.substr(lpos));
2339 return false;
2341 if((rpos > lpos) && (data[rpos-1] == '\r'))
2343 // Line ends in a "\r\n" pair, remove both characters.
2344 lines.push_back(data.substr(lpos, (rpos-1)-lpos));
2346 else
2348 // Line ends in a "\n", remove the character.
2349 lines.push_back(data.substr(lpos, rpos-lpos));
2351 lpos = rpos+1;
2353 return true;
2357 * Return path of a full filename (no trailing slashes).
2358 * Warning: returned path is converted to Unix slashes format.
2360 kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
2362 kwsys_stl::string fn = filename;
2363 SystemTools::ConvertToUnixSlashes(fn);
2365 kwsys_stl::string::size_type slash_pos = fn.rfind("/");
2366 if(slash_pos != kwsys_stl::string::npos)
2368 return fn.substr(0, slash_pos);
2370 else
2372 return "";
2378 * Return file name of a full filename (i.e. file name without path).
2380 kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
2382 kwsys_stl::string fn = filename;
2383 SystemTools::ConvertToUnixSlashes(fn);
2385 kwsys_stl::string::size_type slash_pos = fn.rfind("/");
2386 if(slash_pos != kwsys_stl::string::npos)
2388 return fn.substr(slash_pos + 1);
2390 else
2392 return filename;
2398 * Return file extension of a full filename (dot included).
2399 * Warning: this is the longest extension (for example: .tar.gz)
2401 kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
2403 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
2404 kwsys_stl::string::size_type dot_pos = name.find(".");
2405 if(dot_pos != kwsys_stl::string::npos)
2407 return name.substr(dot_pos);
2409 else
2411 return "";
2416 * Return file extension of a full filename (dot included).
2417 * Warning: this is the shortest extension (for example: .tar.gz)
2419 kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
2421 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
2422 kwsys_stl::string::size_type dot_pos = name.rfind(".");
2423 if(dot_pos != kwsys_stl::string::npos)
2425 return name.substr(dot_pos);
2427 else
2429 return "";
2434 * Return file name without extension of a full filename (i.e. without path).
2435 * Warning: it considers the longest extension (for example: .tar.gz)
2437 kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
2439 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
2440 kwsys_stl::string::size_type dot_pos = name.find(".");
2441 if(dot_pos != kwsys_stl::string::npos)
2443 return name.substr(0, dot_pos);
2445 else
2447 return name;
2453 * Return file name without extension of a full filename (i.e. without path).
2454 * Warning: it considers the last extension (for example: removes .gz
2455 * from .tar.gz)
2457 kwsys_stl::string
2458 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
2460 kwsys_stl::string name = SystemTools::GetFilenameName(filename);
2461 kwsys_stl::string::size_type dot_pos = name.rfind(".");
2462 if(dot_pos != kwsys_stl::string::npos)
2464 return name.substr(0, dot_pos);
2466 else
2468 return name;
2472 bool SystemTools::FileHasSignature(const char *filename,
2473 const char *signature,
2474 long offset)
2476 if (!filename || !signature)
2478 return false;
2481 FILE *fp;
2482 fp = fopen(filename, "rb");
2483 if (!fp)
2485 return false;
2488 fseek(fp, offset, SEEK_SET);
2490 bool res = false;
2491 size_t signature_len = strlen(signature);
2492 char *buffer = new char [signature_len];
2494 if (fread(buffer, 1, signature_len, fp) == signature_len)
2496 res = (!strncmp(buffer, signature, signature_len) ? true : false);
2499 delete [] buffer;
2501 fclose(fp);
2502 return res;
2505 bool SystemTools::LocateFileInDir(const char *filename,
2506 const char *dir,
2507 kwsys_stl::string& filename_found,
2508 int try_filename_dirs)
2510 if (!filename || !dir)
2512 return false;
2515 // Get the basename of 'filename'
2517 kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename);
2519 // Check if 'dir' is really a directory
2520 // If win32 and matches something like C:, accept it as a dir
2522 kwsys_stl::string real_dir;
2523 if (!SystemTools::FileIsDirectory(dir))
2525 #if _WIN32
2526 size_t dir_len = strlen(dir);
2527 if (dir_len < 2 || dir[dir_len - 1] != ':')
2529 #endif
2530 real_dir = SystemTools::GetFilenamePath(dir);
2531 dir = real_dir.c_str();
2532 #if _WIN32
2534 #endif
2537 // Try to find the file in 'dir'
2539 bool res = false;
2540 if (filename_base.size() && dir)
2542 size_t dir_len = strlen(dir);
2543 int need_slash =
2544 (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\');
2546 kwsys_stl::string temp = dir;
2547 if (need_slash)
2549 temp += "/";
2551 temp += filename_base;
2553 if (SystemTools::FileExists(filename_found.c_str()))
2555 res = true;
2556 filename_found = temp;
2559 // If not found, we can try harder by appending part of the file to
2560 // to the directory to look inside.
2561 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
2562 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
2564 else if (try_filename_dirs)
2566 kwsys_stl::string filename_dir(filename);
2567 kwsys_stl::string filename_dir_base;
2568 kwsys_stl::string filename_dir_bases;
2571 filename_dir = SystemTools::GetFilenamePath(filename_dir);
2572 filename_dir_base = SystemTools::GetFilenameName(filename_dir);
2573 #if _WIN32
2574 if (!filename_dir_base.size() ||
2575 filename_dir_base[filename_dir_base.size() - 1] == ':')
2576 #else
2577 if (!filename_dir_base.size())
2578 #endif
2580 break;
2583 filename_dir_bases = filename_dir_base + "/" + filename_dir_bases;
2585 temp = dir;
2586 if (need_slash)
2588 temp += "/";
2590 temp += filename_dir_bases;
2592 res = SystemTools::LocateFileInDir(
2593 filename_base.c_str(), temp.c_str(), filename_found, 0);
2595 } while (!res && filename_dir_base.size());
2599 return res;
2602 bool SystemTools::FileIsFullPath(const char* in_name)
2604 kwsys_stl::string name = in_name;
2605 #if defined(_WIN32) || defined(__CYGWIN__)
2606 // On Windows, the name must be at least two characters long.
2607 if(name.length() < 2)
2609 return false;
2611 if(name[1] == ':')
2613 return true;
2615 if(name[0] == '\\')
2617 return true;
2619 #else
2620 // On UNIX, the name must be at least one character long.
2621 if(name.length() < 1)
2623 return false;
2625 #endif
2626 // On UNIX, the name must begin in a '/'.
2627 // On Windows, if the name begins in a '/', then it is a full
2628 // network path.
2629 if(name[0] == '/')
2631 return true;
2633 return false;
2636 bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
2638 #if defined(WIN32) && !defined(__CYGWIN__)
2639 const int size = int(strlen(path)) +1; // size of return
2640 char *buffer = new char[size]; // create a buffer
2641 char *tempPath = new char[size]; // create a buffer
2642 int ret;
2644 // if the path passed in has quotes around it, first remove the quotes
2645 if (path[0] == '"' && path[strlen(path)-1] == '"')
2647 strcpy(tempPath,path+1);
2648 tempPath[strlen(tempPath)-1] = '\0';
2650 else
2652 strcpy(tempPath,path);
2655 buffer[0] = 0;
2656 ret = GetShortPathName(tempPath, buffer, size);
2658 if(buffer[0] == 0 || ret > size)
2660 delete [] buffer;
2661 delete [] tempPath;
2662 return false;
2664 else
2666 shortPath = buffer;
2667 delete [] buffer;
2668 delete [] tempPath;
2669 return true;
2671 #else
2672 shortPath = path;
2673 return true;
2674 #endif
2677 void SystemTools::SplitProgramFromArgs(const char* path,
2678 kwsys_stl::string& program, kwsys_stl::string& args)
2680 // see if this is a full path to a program
2681 // if so then set program to path and args to nothing
2682 if(SystemTools::FileExists(path))
2684 program = path;
2685 args = "";
2686 return;
2688 // Try to find the program in the path, note the program
2689 // may have spaces in its name so we have to look for it
2690 kwsys_stl::vector<kwsys_stl::string> e;
2691 kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
2692 if(findProg.size())
2694 program = findProg;
2695 args = "";
2696 return;
2699 // Now try and peel off space separated chunks from the end of the string
2700 // so the largest path possible is found allowing for spaces in the path
2701 kwsys_stl::string dir = path;
2702 kwsys_stl::string::size_type spacePos = dir.rfind(' ');
2703 while(spacePos != kwsys_stl::string::npos)
2705 kwsys_stl::string tryProg = dir.substr(0, spacePos);
2706 // See if the file exists
2707 if(SystemTools::FileExists(tryProg.c_str()))
2709 program = tryProg;
2710 // remove trailing spaces from program
2711 kwsys_stl::string::size_type pos = program.size()-1;
2712 while(program[pos] == ' ')
2714 program.erase(pos);
2715 pos--;
2717 args = dir.substr(spacePos, dir.size()-spacePos);
2718 return;
2720 // Now try and find the the program in the path
2721 findProg = SystemTools::FindProgram(tryProg.c_str(), e);
2722 if(findProg.size())
2724 program = findProg;
2725 // remove trailing spaces from program
2726 kwsys_stl::string::size_type pos = program.size()-1;
2727 while(program[pos] == ' ')
2729 program.erase(pos);
2730 pos--;
2732 args = dir.substr(spacePos, dir.size()-spacePos);
2733 return;
2735 // move past the space for the next search
2736 spacePos--;
2737 spacePos = dir.rfind(' ', spacePos);
2740 program = "";
2741 args = "";
2744 kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
2746 char buf[1024];
2747 time_t t;
2748 time(&t);
2749 strftime(buf, sizeof(buf), format, localtime(&t));
2750 return buf;
2753 kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
2755 kwsys_stl::string str(s);
2756 if (str.find_first_of("0123456789") == 0)
2758 str = "_" + str;
2761 kwsys_stl::string permited_chars("_"
2762 "abcdefghijklmnopqrstuvwxyz"
2763 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2764 "0123456789");
2765 kwsys_stl::string::size_type pos = 0;
2766 while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
2768 str[pos] = '_';
2770 return str;
2773 // Due to a buggy stream library on the HP and another on Mac OSX, we
2774 // need this very carefully written version of getline. Returns true
2775 // if any data were read before the end-of-file was reached.
2776 bool SystemTools::GetLineFromStream(kwsys_ios::istream& is, kwsys_stl::string& line,
2777 bool *has_newline /* = 0 */)
2779 const int bufferSize = 1024;
2780 char buffer[bufferSize];
2781 line = "";
2782 bool haveData = false;
2783 if ( has_newline )
2785 *has_newline = false;
2788 // If no characters are read from the stream, the end of file has
2789 // been reached.
2790 while((is.getline(buffer, bufferSize), is.gcount() > 0))
2792 haveData = true;
2793 line.append(buffer);
2795 // If newline character was read, the gcount includes the
2796 // character, but the buffer does not. The end of line has been
2797 // reached.
2798 if(strlen(buffer) < static_cast<size_t>(is.gcount()))
2800 if ( has_newline )
2802 *has_newline = true;
2804 break;
2807 // The fail bit may be set. Clear it.
2808 is.clear(is.rdstate() & ~kwsys_ios::ios::failbit);
2810 return haveData;
2813 int SystemTools::GetTerminalWidth()
2815 int width = -1;
2816 #ifndef _WIN32
2817 struct winsize ws;
2818 char *columns; /* Unix98 environment variable */
2819 if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
2821 width = ws.ws_col;
2823 if(!isatty(STDOUT_FILENO))
2825 width = -1;
2827 columns = getenv("COLUMNS");
2828 if(columns && *columns)
2830 long t;
2831 char *endptr;
2832 t = strtol(columns, &endptr, 0);
2833 if(endptr && !*endptr && (t>0) && (t<1000))
2835 width = (int)t;
2838 if ( width < 9 )
2840 width = -1;
2842 #endif
2843 return width;
2846 bool SystemTools::GetPermissions(const char* file, mode_t& mode)
2848 if ( !file )
2850 return false;
2853 struct stat st;
2854 if ( stat(file, &st) < 0 )
2856 return false;
2858 mode = st.st_mode;
2859 return true;
2862 bool SystemTools::SetPermissions(const char* file, mode_t mode)
2864 if ( !file )
2866 return false;
2868 if ( !SystemTools::FileExists(file) )
2870 return false;
2872 if ( chmod(file, mode) < 0 )
2874 return false;
2877 return true;
2880 kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir)
2882 if ( !fileOrDir || !*fileOrDir )
2884 return "";
2886 kwsys_stl::string res = fileOrDir;
2887 SystemTools::ConvertToUnixSlashes(res);
2888 kwsys_stl::string::size_type cc = res.size()-1;
2889 if ( res[cc] == '/' )
2891 cc --;
2893 for ( ; cc > 0; cc -- )
2895 if ( res[cc] == '/' )
2897 break;
2900 return res.substr(0, cc);
2903 bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
2905 kwsys_stl::string subdir = cSubdir;
2906 kwsys_stl::string dir = cDir;
2907 SystemTools::ConvertToUnixSlashes(dir);
2908 kwsys_stl::string path = subdir;
2911 path = SystemTools::GetParentDirectory(path.c_str());
2912 if ( dir == path )
2914 return true;
2917 while ( path.size() > dir.size() );
2918 return false;
2921 kwsys_stl::string SystemTools::FileExistsInParentDirectories(const char* fname,
2922 const char* directory, const char* toplevel)
2924 kwsys_stl::string file = fname;
2925 SystemTools::ConvertToUnixSlashes(file);
2926 kwsys_stl::string dir = directory;
2927 SystemTools::ConvertToUnixSlashes(dir);
2928 while ( !dir.empty() )
2930 kwsys_stl::string path = dir + "/" + file;
2931 if ( SystemTools::FileExists(path.c_str()) )
2933 return path;
2935 if ( dir.size() < strlen(toplevel) )
2937 break;
2939 dir = SystemTools::GetParentDirectory(dir.c_str());
2941 return "";
2944 void SystemTools::Delay(unsigned int msec)
2946 #ifdef _WIN32
2947 Sleep(msec);
2948 #else
2949 usleep(msec * 1000);
2950 #endif
2953 // These must NOT be initialized. Default initialization to zero is
2954 // necessary.
2955 unsigned int SystemToolsManagerCount;
2956 SystemToolsTranslationMap *SystemTools::TranslationMap;
2958 // SystemToolsManager manages the SystemTools singleton.
2959 // SystemToolsManager should be included in any translation unit
2960 // that will use SystemTools or that implements the singleton
2961 // pattern. It makes sure that the SystemTools singleton is created
2962 // before and destroyed after all other singletons in CMake.
2964 SystemToolsManager::SystemToolsManager()
2966 if(++SystemToolsManagerCount == 1)
2968 SystemTools::ClassInitialize();
2972 SystemToolsManager::~SystemToolsManager()
2974 if(--SystemToolsManagerCount == 0)
2976 SystemTools::ClassFinalize();
2980 void SystemTools::ClassInitialize()
2982 // Allocate the translation map first.
2983 SystemTools::TranslationMap = new SystemToolsTranslationMap;
2985 // Add some special translation paths for unix. These are not added
2986 // for windows because drive letters need to be maintained. Also,
2987 // there are not sym-links and mount points on windows anyway.
2988 #if !defined(_WIN32) || defined(__CYGWIN__)
2989 // Work-around an SGI problem by always adding this mapping:
2990 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
2991 // The tmp path is frequently a logical path so always keep it:
2992 SystemTools::AddKeepPath("/tmp/");
2994 // If the current working directory is a logical path then keep the
2995 // logical name.
2996 if(const char* pwd = getenv("PWD"))
2998 char buf[2048];
2999 if(const char* cwd = Getcwd(buf, 2048))
3001 kwsys_stl::string pwd_path;
3002 Realpath(pwd, pwd_path);
3003 if(cwd == pwd_path && strcmp(cwd, pwd) != 0)
3005 // The current working directory is a logical path. Split
3006 // both the logical and physical paths into their components.
3007 kwsys_stl::vector<kwsys_stl::string> cwd_components;
3008 kwsys_stl::vector<kwsys_stl::string> pwd_components;
3009 SystemTools::SplitPath(cwd, cwd_components);
3010 SystemTools::SplitPath(pwd, pwd_components);
3012 // Remove the common ending of the paths to leave only the
3013 // part that changes under the logical mapping.
3014 kwsys_stl::vector<kwsys_stl::string>::iterator ic = cwd_components.end();
3015 kwsys_stl::vector<kwsys_stl::string>::iterator ip = pwd_components.end();
3016 for(;ip != pwd_components.begin() && ic != cwd_components.begin() &&
3017 *(ip-1) == *(ic-1); --ip,--ic);
3018 cwd_components.erase(ic, cwd_components.end());
3019 pwd_components.erase(ip, pwd_components.end());
3021 // Reconstruct the string versions of the part of the path
3022 // that changed.
3023 kwsys_stl::string cwd_changed = SystemTools::JoinPath(cwd_components);
3024 kwsys_stl::string pwd_changed = SystemTools::JoinPath(pwd_components);
3026 // Add the translation to keep the logical path name.
3027 if(!cwd_changed.empty() && !pwd_changed.empty())
3029 SystemTools::AddTranslationPath(cwd_changed.c_str(),
3030 pwd_changed.c_str());
3035 #endif
3038 void SystemTools::ClassFinalize()
3040 delete SystemTools::TranslationMap;
3044 } // namespace KWSYS_NAMESPACE
3046 #if defined(_MSC_VER) && defined(_DEBUG)
3047 # include <crtdbg.h>
3048 # include <stdio.h>
3049 # include <stdlib.h>
3050 namespace KWSYS_NAMESPACE
3053 static int SystemToolsDebugReport(int, char* message, int*)
3055 fprintf(stderr, message);
3056 exit(1);
3058 void SystemTools::EnableMSVCDebugHook()
3060 if(getenv("DART_TEST_FROM_DART"))
3062 _CrtSetReportHook(SystemToolsDebugReport);
3066 } // namespace KWSYS_NAMESPACE
3067 #else
3068 namespace KWSYS_NAMESPACE
3070 void SystemTools::EnableMSVCDebugHook() {}
3071 } // namespace KWSYS_NAMESPACE
3072 #endif