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 // Work-around CMake dependency scanning limitation. This must
23 // duplicate the above list of headers.
25 # include "SystemTools.hxx.in"
26 # include "Directory.hxx.in"
27 # include "kwsys_ios_iostream.h.in"
28 # include "kwsys_ios_fstream.h.in"
29 # include "kwsys_ios_sstream.h.in"
33 # pragma warning (disable: 4786)
36 #if defined(__sgi) && !defined(__GNUC__)
37 # pragma set woff 1375 /* base class destructor not virtual */
43 # include <malloc.h> /* for malloc/free on QNX */
51 // support for realpath call
54 #include <sys/param.h>
56 #include <sys/ioctl.h>
61 // Windows API. Some parts used even on cygwin.
66 // This is a hack to prevent warnings about these functions being
67 // declared but not referenced.
68 #if defined(__sgi) && !defined(__GNUC__)
69 # include <sys/termios.h>
70 namespace KWSYS_NAMESPACE
77 Ref1
= sizeof(cfgetospeed(0)),
78 Ref2
= sizeof(cfgetispeed(0)),
79 Ref3
= sizeof(tcgetattr(0, 0)),
80 Ref4
= sizeof(tcsetattr(0, 0, 0)),
81 Ref5
= sizeof(cfsetospeed(0,0)),
82 Ref6
= sizeof(cfsetispeed(0,0))
88 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__))
91 #define _unlink unlink
92 inline int Mkdir(const char* dir
)
96 inline int Rmdir(const char* dir
)
100 inline const char* Getcwd(char* buf
, unsigned int len
)
102 return _getcwd(buf
, len
);
104 inline int Chdir(const char* dir
)
106 #if defined(__BORLANDC__)
112 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
115 char fullpath
[MAX_PATH
];
116 if( GetFullPathName(path
, sizeof(fullpath
), fullpath
, &ptemp
) )
118 resolved_path
= fullpath
;
119 KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path
);
123 #include <sys/types.h>
126 inline int Mkdir(const char* dir
)
128 return mkdir(dir
, 00777);
130 inline int Rmdir(const char* dir
)
134 inline const char* Getcwd(char* buf
, unsigned int len
)
136 return getcwd(buf
, len
);
138 inline int Chdir(const char* dir
)
142 inline void Realpath(const char *path
, kwsys_stl::string
& resolved_path
)
145 char resolved_name
[MAXPATHLEN
];
148 char resolved_name
[PATH_MAX
];
150 char resolved_name
[5024];
154 realpath(path
, resolved_name
);
155 resolved_path
= resolved_name
;
159 #if !defined(_WIN32) && defined(__COMO__)
160 // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
163 extern FILE *popen (__const
char *__command
, __const
char *__modes
) __THROW
;
164 extern int pclose (FILE *__stream
) __THROW
;
165 extern char *realpath (__const
char *__restrict __name
,
166 char *__restrict __resolved
) __THROW
;
167 extern char *strdup (__const
char *__s
) __THROW
;
168 extern int putenv (char *__string
) __THROW
;
172 /* Implement floattime() for various platforms */
173 // Taken from Python 2.1.3
175 #if defined( _WIN32 ) && !defined( __CYGWIN__ )
176 # include <sys/timeb.h>
178 # if defined( __BORLANDC__)
181 # else // Visual studio?
182 # define FTIME _ftime
183 # define TIMEB _timeb
185 #elif defined( __CYGWIN__ ) || defined( __linux__ )
186 # include <sys/time.h>
188 # define HAVE_GETTIMEOFDAY
191 namespace KWSYS_NAMESPACE
194 class SystemToolsTranslationMap
:
195 public kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>
200 SystemTools::GetTime(void)
202 /* There are three ways to get the time:
203 (1) gettimeofday() -- resolution in microseconds
204 (2) ftime() -- resolution in milliseconds
205 (3) time() -- resolution in seconds
206 In all cases the return value is a float in seconds.
207 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
208 fail, so we fall back on ftime() or time().
209 Note: clock resolution does not imply clock accuracy! */
210 #ifdef HAVE_GETTIMEOFDAY
213 #ifdef GETTIMEOFDAY_NO_TZ
214 if (gettimeofday(&t
) == 0)
215 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
216 #else /* !GETTIMEOFDAY_NO_TZ */
217 if (gettimeofday(&t
, (struct timezone
*)NULL
) == 0)
218 return (double)t
.tv_sec
+ t
.tv_usec
*0.000001;
219 #endif /* !GETTIMEOFDAY_NO_TZ */
221 #endif /* !HAVE_GETTIMEOFDAY */
223 #if defined(HAVE_FTIME)
226 return (double)t
.time
+ (double)t
.millitm
* (double)0.001;
227 #else /* !HAVE_FTIME */
231 #endif /* !HAVE_FTIME */
235 // adds the elements of the env variable path to the arg passed in
236 void SystemTools::GetPath(kwsys_stl::vector
<kwsys_stl::string
>& path
, const char* env
)
238 #if defined(_WIN32) && !defined(__CYGWIN__)
239 const char* pathSep
= ";";
241 const char* pathSep
= ":";
247 const char* cpathEnv
= SystemTools::GetEnv(env
);
253 kwsys_stl::string pathEnv
= cpathEnv
;
255 // A hack to make the below algorithm work.
256 if(pathEnv
[pathEnv
.length()-1] != ':')
260 kwsys_stl::string::size_type start
=0;
264 kwsys_stl::string::size_type endpos
= pathEnv
.find(pathSep
, start
);
265 if(endpos
!= kwsys_stl::string::npos
)
267 path
.push_back(pathEnv
.substr(start
, endpos
-start
));
275 for(kwsys_stl::vector
<kwsys_stl::string
>::iterator i
= path
.begin();
276 i
!= path
.end(); ++i
)
278 SystemTools::ConvertToUnixSlashes(*i
);
282 const char* SystemTools::GetEnv(const char* key
)
287 bool SystemTools::GetEnv(const char* key
, kwsys_stl::string
& result
)
289 const char* v
= getenv(key
);
301 const char* SystemTools::GetExecutableExtension()
303 #if defined(_WIN32) || defined(__CYGWIN__)
311 bool SystemTools::MakeDirectory(const char* path
)
313 if(SystemTools::FileExists(path
))
317 kwsys_stl::string dir
= path
;
322 SystemTools::ConvertToUnixSlashes(dir
);
324 kwsys_stl::string::size_type pos
= dir
.find(':');
325 if(pos
== kwsys_stl::string::npos
)
329 kwsys_stl::string topdir
;
330 while((pos
= dir
.find('/', pos
)) != kwsys_stl::string::npos
)
332 topdir
= dir
.substr(0, pos
);
333 Mkdir(topdir
.c_str());
336 if(dir
[dir
.size()-1] == '/')
338 topdir
= dir
.substr(0, dir
.size());
344 if(Mkdir(topdir
.c_str()) != 0)
346 // There is a bug in the Borland Run time library which makes MKDIR
347 // return EACCES when it should return EEXISTS
348 // if it is some other error besides directory exists
350 if( (errno
!= EEXIST
)
363 // replace replace with with as many times as it shows up in source.
364 // write the result into source.
365 void SystemTools::ReplaceString(kwsys_stl::string
& source
,
369 const char *src
= source
.c_str();
370 char *searchPos
= const_cast<char *>(strstr(src
,replace
));
372 // get out quick if string is not found
378 // perform replacements until done
379 size_t replaceSize
= strlen(replace
);
380 char *orig
= strdup(src
);
381 char *currentPos
= orig
;
382 searchPos
= searchPos
- src
+ orig
;
384 // initialize the result
385 source
.erase(source
.begin(),source
.end());
389 source
+= currentPos
;
390 currentPos
= searchPos
+ replaceSize
;
393 searchPos
= strstr(currentPos
,replace
);
397 // copy any trailing text
398 source
+= currentPos
;
402 // Read a registry value.
404 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
405 // => will return the data of the "default" value of the key
406 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
407 // => will return the data of the "Root" value of the key
409 #if defined(_WIN32) && !defined(__CYGWIN__)
410 bool SystemTools::ReadRegistryValue(const char *key
, kwsys_stl::string
&value
)
413 kwsys_stl::string primary
= key
;
414 kwsys_stl::string second
;
415 kwsys_stl::string valuename
;
417 size_t start
= primary
.find("\\");
418 if (start
== kwsys_stl::string::npos
)
423 size_t valuenamepos
= primary
.find(";");
424 if (valuenamepos
!= kwsys_stl::string::npos
)
426 valuename
= primary
.substr(valuenamepos
+1);
429 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
430 primary
= primary
.substr(0, start
);
432 HKEY primaryKey
= HKEY_CURRENT_USER
;
433 if (primary
== "HKEY_CURRENT_USER")
435 primaryKey
= HKEY_CURRENT_USER
;
437 if (primary
== "HKEY_CURRENT_CONFIG")
439 primaryKey
= HKEY_CURRENT_CONFIG
;
441 if (primary
== "HKEY_CLASSES_ROOT")
443 primaryKey
= HKEY_CLASSES_ROOT
;
445 if (primary
== "HKEY_LOCAL_MACHINE")
447 primaryKey
= HKEY_LOCAL_MACHINE
;
449 if (primary
== "HKEY_USERS")
451 primaryKey
= HKEY_USERS
;
455 if(RegOpenKeyEx(primaryKey
,
459 &hKey
) != ERROR_SUCCESS
)
465 DWORD dwType
, dwSize
;
468 if(RegQueryValueEx(hKey
,
469 (LPTSTR
)valuename
.c_str(),
473 &dwSize
) == ERROR_SUCCESS
)
475 if (dwType
== REG_SZ
)
486 bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string
&)
493 // Write a registry value.
495 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
496 // => will set the data of the "default" value of the key
497 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
498 // => will set the data of the "Root" value of the key
500 #if defined(_WIN32) && !defined(__CYGWIN__)
501 bool SystemTools::WriteRegistryValue(const char *key
, const char *value
)
503 kwsys_stl::string primary
= key
;
504 kwsys_stl::string second
;
505 kwsys_stl::string valuename
;
507 size_t start
= primary
.find("\\");
508 if (start
== kwsys_stl::string::npos
)
513 size_t valuenamepos
= primary
.find(";");
514 if (valuenamepos
!= kwsys_stl::string::npos
)
516 valuename
= primary
.substr(valuenamepos
+1);
519 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
520 primary
= primary
.substr(0, start
);
522 HKEY primaryKey
= HKEY_CURRENT_USER
;
523 if (primary
== "HKEY_CURRENT_USER")
525 primaryKey
= HKEY_CURRENT_USER
;
527 if (primary
== "HKEY_CURRENT_CONFIG")
529 primaryKey
= HKEY_CURRENT_CONFIG
;
531 if (primary
== "HKEY_CLASSES_ROOT")
533 primaryKey
= HKEY_CLASSES_ROOT
;
535 if (primary
== "HKEY_LOCAL_MACHINE")
537 primaryKey
= HKEY_LOCAL_MACHINE
;
539 if (primary
== "HKEY_USERS")
541 primaryKey
= HKEY_USERS
;
546 if(RegCreateKeyEx(primaryKey
,
550 REG_OPTION_NON_VOLATILE
,
554 &dwDummy
) != ERROR_SUCCESS
)
559 if(RegSetValueEx(hKey
,
560 (LPTSTR
)valuename
.c_str(),
564 (DWORD
)(strlen(value
) + 1)) == ERROR_SUCCESS
)
571 bool SystemTools::WriteRegistryValue(const char *, const char *)
577 // Delete a registry value.
579 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
580 // => will delete the data of the "default" value of the key
581 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
582 // => will delete the data of the "Root" value of the key
584 #if defined(_WIN32) && !defined(__CYGWIN__)
585 bool SystemTools::DeleteRegistryValue(const char *key
)
587 kwsys_stl::string primary
= key
;
588 kwsys_stl::string second
;
589 kwsys_stl::string valuename
;
591 size_t start
= primary
.find("\\");
592 if (start
== kwsys_stl::string::npos
)
597 size_t valuenamepos
= primary
.find(";");
598 if (valuenamepos
!= kwsys_stl::string::npos
)
600 valuename
= primary
.substr(valuenamepos
+1);
603 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
604 primary
= primary
.substr(0, start
);
606 HKEY primaryKey
= HKEY_CURRENT_USER
;
607 if (primary
== "HKEY_CURRENT_USER")
609 primaryKey
= HKEY_CURRENT_USER
;
611 if (primary
== "HKEY_CURRENT_CONFIG")
613 primaryKey
= HKEY_CURRENT_CONFIG
;
615 if (primary
== "HKEY_CLASSES_ROOT")
617 primaryKey
= HKEY_CLASSES_ROOT
;
619 if (primary
== "HKEY_LOCAL_MACHINE")
621 primaryKey
= HKEY_LOCAL_MACHINE
;
623 if (primary
== "HKEY_USERS")
625 primaryKey
= HKEY_USERS
;
629 if(RegOpenKeyEx(primaryKey
,
633 &hKey
) != ERROR_SUCCESS
)
639 if(RegDeleteValue(hKey
,
640 (LPTSTR
)valuename
.c_str()) == ERROR_SUCCESS
)
649 bool SystemTools::DeleteRegistryValue(const char *)
655 bool SystemTools::SameFile(const char* file1
, const char* file2
)
658 HANDLE hFile1
, hFile2
;
660 hFile1
= CreateFile( file1
,
665 FILE_FLAG_BACKUP_SEMANTICS
,
668 hFile2
= CreateFile( file2
,
673 FILE_FLAG_BACKUP_SEMANTICS
,
676 if( hFile1
== INVALID_HANDLE_VALUE
|| hFile2
== INVALID_HANDLE_VALUE
)
678 if(hFile1
!= INVALID_HANDLE_VALUE
)
682 if(hFile2
!= INVALID_HANDLE_VALUE
)
689 BY_HANDLE_FILE_INFORMATION fiBuf1
;
690 BY_HANDLE_FILE_INFORMATION fiBuf2
;
691 GetFileInformationByHandle( hFile1
, &fiBuf1
);
692 GetFileInformationByHandle( hFile2
, &fiBuf2
);
695 return (fiBuf1
.dwVolumeSerialNumber
== fiBuf2
.dwVolumeSerialNumber
&&
696 fiBuf1
.nFileIndexHigh
== fiBuf2
.nFileIndexHigh
&&
697 fiBuf1
.nFileIndexLow
== fiBuf2
.nFileIndexLow
);
699 struct stat fileStat1
, fileStat2
;
700 if (stat(file1
, &fileStat1
) == 0 && stat(file2
, &fileStat2
) == 0)
702 // see if the files are the same file
703 // check the device inode and size
704 if(memcmp(&fileStat2
.st_dev
, &fileStat1
.st_dev
, sizeof(fileStat1
.st_dev
)) == 0 &&
705 memcmp(&fileStat2
.st_ino
, &fileStat1
.st_ino
, sizeof(fileStat1
.st_ino
)) == 0 &&
706 fileStat2
.st_size
== fileStat1
.st_size
717 // return true if the file exists
718 bool SystemTools::FileExists(const char* filename
)
721 # define access _access
726 if ( access(filename
, R_OK
) != 0 )
737 bool SystemTools::FileTimeCompare(const char* f1
, const char* f2
,
740 // Default to same time.
742 #if !defined(_WIN32) || defined(__CYGWIN__)
743 // POSIX version. Use stat function to get file modification time.
745 if(stat(f1
, &s1
) != 0)
750 if(stat(f2
, &s2
) != 0)
754 # if KWSYS_STAT_HAS_ST_MTIM
755 // Compare using nanosecond resolution.
756 if(s1
.st_mtim
.tv_sec
< s2
.st_mtim
.tv_sec
)
760 else if(s1
.st_mtim
.tv_sec
> s2
.st_mtim
.tv_sec
)
764 else if(s1
.st_mtim
.tv_nsec
< s2
.st_mtim
.tv_nsec
)
768 else if(s1
.st_mtim
.tv_nsec
> s2
.st_mtim
.tv_nsec
)
773 // Compare using 1 second resolution.
774 if(s1
.st_mtime
< s2
.st_mtime
)
778 else if(s1
.st_mtime
> s2
.st_mtime
)
784 // Windows version. Create file handles and get the modification times.
785 HANDLE hf1
= CreateFile(f1
, GENERIC_READ
, FILE_SHARE_READ
,
786 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
788 if(hf1
== INVALID_HANDLE_VALUE
)
793 if(!GetFileTime(hf1
, 0, 0, &tf1
))
799 HANDLE hf2
= CreateFile(f2
, GENERIC_READ
, FILE_SHARE_READ
,
800 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
802 if(hf2
== INVALID_HANDLE_VALUE
)
807 if(!GetFileTime(hf2
, 0, 0, &tf2
))
814 // Compare the file times using resolution provided by system call.
815 *result
= (int)CompareFileTime(&tf1
, &tf2
);
821 // Return a capitalized string (i.e the first letter is uppercased, all other
823 kwsys_stl::string
SystemTools::Capitalized(const kwsys_stl::string
& s
)
831 n
[0] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[0]));
832 for (size_t i
= 1; i
< s
.size(); i
++)
834 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
839 // Return capitalized words
840 kwsys_stl::string
SystemTools::CapitalizedWords(const kwsys_stl::string
& s
)
842 kwsys_stl::string
n(s
);
843 for (size_t i
= 0; i
< s
.size(); i
++)
845 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
847 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
853 // Return uncapitalized words
854 kwsys_stl::string
SystemTools::UnCapitalizedWords(const kwsys_stl::string
& s
)
856 kwsys_stl::string
n(s
);
857 for (size_t i
= 0; i
< s
.size(); i
++)
859 if (isalpha(s
[i
]) && (i
== 0 || isspace(s
[i
- 1])))
861 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
867 kwsys_stl::string
SystemTools::AddSpaceBetweenCapitalizedWords(
868 const kwsys_stl::string
& s
)
875 for (size_t i
= 1; i
< s
.size(); i
++)
877 if (isupper(s
[i
]) && !isspace(s
[i
- 1]) && !isupper(s
[i
- 1]))
887 char* SystemTools::AppendStrings(const char* str1
, const char* str2
)
891 return SystemTools::DuplicateString(str2
);
895 return SystemTools::DuplicateString(str1
);
897 size_t len1
= strlen(str1
);
898 char *newstr
= new char[len1
+ strlen(str2
) + 1];
903 strcpy(newstr
, str1
);
904 strcat(newstr
+ len1
, str2
);
908 char* SystemTools::AppendStrings(
909 const char* str1
, const char* str2
, const char* str3
)
913 return SystemTools::AppendStrings(str2
, str3
);
917 return SystemTools::AppendStrings(str1
, str3
);
921 return SystemTools::AppendStrings(str1
, str2
);
924 size_t len1
= strlen(str1
), len2
= strlen(str2
);
925 char *newstr
= new char[len1
+ len2
+ strlen(str3
) + 1];
930 strcpy(newstr
, str1
);
931 strcat(newstr
+ len1
, str2
);
932 strcat(newstr
+ len1
+ len2
, str3
);
936 // Return a lower case string
937 kwsys_stl::string
SystemTools::LowerCase(const kwsys_stl::string
& s
)
941 for (size_t i
= 0; i
< s
.size(); i
++)
943 n
[i
] = static_cast<kwsys_stl::string::value_type
>(tolower(s
[i
]));
948 // Return a lower case string
949 kwsys_stl::string
SystemTools::UpperCase(const kwsys_stl::string
& s
)
953 for (size_t i
= 0; i
< s
.size(); i
++)
955 n
[i
] = static_cast<kwsys_stl::string::value_type
>(toupper(s
[i
]));
960 // Count char in string
961 size_t SystemTools::CountChar(const char* str
, char c
)
979 // Remove chars in string
980 char* SystemTools::RemoveChars(const char* str
, const char *toremove
)
986 char *clean_str
= new char [strlen(str
) + 1];
987 char *ptr
= clean_str
;
990 const char *str2
= toremove
;
991 while (*str2
&& *str
!= *str2
)
1005 // Remove chars in string
1006 char* SystemTools::RemoveCharsButUpperHex(const char* str
)
1012 char *clean_str
= new char [strlen(str
) + 1];
1013 char *ptr
= clean_str
;
1016 if ((*str
>= '0' && *str
<= '9') || (*str
>= 'A' && *str
<= 'H'))
1026 // Replace chars in string
1027 char* SystemTools::ReplaceChars(char* str
, const char *toreplace
, char replacement
)
1034 const char *ptr2
= toreplace
;
1049 // Returns if string starts with another string
1050 bool SystemTools::StringStartsWith(const char* str1
, const char* str2
)
1056 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1057 return len1
>= len2
&& !strncmp(str1
, str2
, len2
) ? true : false;
1060 // Returns if string ends with another string
1061 bool SystemTools::StringEndsWith(const char* str1
, const char* str2
)
1067 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1068 return len1
>= len2
&& !strncmp(str1
+ (len1
- len2
), str2
, len2
) ? true : false;
1071 // Returns a pointer to the last occurence of str2 in str1
1072 const char* SystemTools::FindLastString(const char* str1
, const char* str2
)
1079 size_t len1
= strlen(str1
), len2
= strlen(str2
);
1082 const char *ptr
= str1
+ len1
- len2
;
1085 if (!strncmp(ptr
, str2
, len2
))
1089 } while (ptr
-- != str1
);
1096 char* SystemTools::DuplicateString(const char* str
)
1100 char *newstr
= new char [strlen(str
) + 1];
1101 return strcpy(newstr
, str
);
1106 // Return a cropped string
1107 kwsys_stl::string
SystemTools::CropString(const kwsys_stl::string
& s
,
1110 if (!s
.size() || max_len
== 0 || max_len
>= s
.size())
1115 kwsys_stl::string n
;
1118 size_t middle
= max_len
/ 2;
1120 n
+= s
.substr(0, middle
);
1121 n
+= s
.substr(s
.size() - (max_len
- middle
), kwsys_stl::string::npos
);
1128 n
[middle
- 1] = '.';
1131 n
[middle
+ 1] = '.';
1139 //----------------------------------------------------------------------------
1140 int SystemTools::EstimateFormatLength(const char *format
, va_list ap
)
1147 // Quick-hack attempt at estimating the length of the string.
1148 // Should never under-estimate.
1150 // Start with the length of the format string itself.
1152 int length
= strlen(format
);
1154 // Increase the length for every argument in the format.
1156 const char* cur
= format
;
1161 // Skip "%%" since it doesn't correspond to a va_arg.
1164 while(!int(isalpha(*cur
)))
1172 // Check the length of the string.
1173 char* s
= va_arg(ap
, char*);
1176 length
+= strlen(s
);
1183 // Assume the argument contributes no more than 64 characters.
1186 // Eat the argument.
1187 static_cast<void>(va_arg(ap
, double));
1191 // Assume the argument contributes no more than 64 characters.
1194 // Eat the argument.
1195 static_cast<void>(va_arg(ap
, int));
1200 // Move past the characters just tested.
1208 kwsys_stl::string
SystemTools::EscapeChars(
1210 const char *chars_to_escape
,
1213 kwsys_stl::string n
;
1216 if (!chars_to_escape
| !*chars_to_escape
)
1222 n
.reserve(strlen(str
));
1225 const char *ptr
= chars_to_escape
;
1243 // convert windows slashes to unix slashes
1244 void SystemTools::ConvertToUnixSlashes(kwsys_stl::string
& path
)
1246 const char* pathCString
= path
.c_str();
1247 bool hasDoubleSlash
= false;
1249 const char* pos0
= pathCString
;
1250 const char* pos1
= pathCString
+1;
1251 for (kwsys_stl::string::size_type pos
= 0; *pos0
; ++ pos
)
1253 // make sure we don't convert an escaped space to a unix slash
1254 if ( *pos0
== '\\' && *pos1
!= ' ' )
1259 // Also, reuse the loop to check for slash followed by another slash
1260 if ( !hasDoubleSlash
&& *pos1
&&
1261 *pos1
== '/' && *(pos1
+1) == '/' )
1264 // However, on windows if the first characters are both slashes,
1265 // then keep them that way, so that network paths can be handled.
1268 hasDoubleSlash
= true;
1271 hasDoubleSlash
= true;
1279 if ( hasDoubleSlash
)
1281 SystemTools::ReplaceString(path
, "//", "/");
1284 // remove any trailing slash
1287 // if there is a tilda ~ then replace it with HOME
1288 pathCString
= path
.c_str();
1289 if(*pathCString
== '~')
1291 const char* homeEnv
= SystemTools::GetEnv("HOME");
1294 path
.replace(0,1,homeEnv
);
1298 pathCString
= path
.c_str();
1299 if (*(pathCString
+(path
.size()-1)) == '/')
1301 path
= path
.substr(0, path
.size()-1);
1307 // change // to /, and escape any spaces in the path
1308 kwsys_stl::string
SystemTools::ConvertToUnixOutputPath(const char* path
)
1310 kwsys_stl::string ret
= path
;
1312 // remove // except at the beginning might be a cygwin drive
1313 kwsys_stl::string::size_type pos
=0;
1314 while((pos
= ret
.find("//", pos
)) != kwsys_stl::string::npos
)
1318 // now escape spaces if there is a space in the path
1319 if(ret
.find(" ") != kwsys_stl::string::npos
)
1321 kwsys_stl::string result
= "";
1323 for(const char* ch
= ret
.c_str(); *ch
!= '\0'; ++ch
)
1325 // if it is already escaped then don't try to escape it again
1326 if(*ch
== ' ' && lastch
!= '\\')
1338 kwsys_stl::string
SystemTools::ConvertToOutputPath(const char* path
)
1340 #if defined(_WIN32) && !defined(__CYGWIN__)
1341 return SystemTools::ConvertToWindowsOutputPath(path
);
1343 return SystemTools::ConvertToUnixOutputPath(path
);
1347 // remove double slashes not at the start
1348 kwsys_stl::string
SystemTools::ConvertToWindowsOutputPath(const char* path
)
1350 kwsys_stl::string ret
;
1351 // make it big enough for all of path and double quotes
1352 ret
.reserve(strlen(path
)+3);
1353 // put path into the string
1355 kwsys_stl::string::size_type pos
= 0;
1356 // first convert all of the slashes
1357 while((pos
= ret
.find('/', pos
)) != kwsys_stl::string::npos
)
1362 // check for really small paths
1367 // now clean up a bit and remove double slashes
1368 // Only if it is not the first position in the path which is a network
1370 pos
= 1; // start at position 1
1373 pos
= 2; // if the string is already quoted then start at 2
1379 while((pos
= ret
.find("\\\\", pos
)) != kwsys_stl::string::npos
)
1383 // now double quote the path if it has spaces in it
1384 // and is not already double quoted
1385 if(ret
.find(' ') != kwsys_stl::string::npos
1388 ret
.insert(static_cast<kwsys_stl::string::size_type
>(0),
1389 static_cast<kwsys_stl::string::size_type
>(1), '\"');
1390 ret
.append(1, '\"');
1395 bool SystemTools::CopyFileIfDifferent(const char* source
,
1396 const char* destination
)
1398 if(SystemTools::FilesDiffer(source
, destination
))
1400 return SystemTools::CopyFileAlways(source
, destination
);
1406 bool SystemTools::FilesDiffer(const char* source
,
1407 const char* destination
)
1409 struct stat statSource
;
1410 if (stat(source
, &statSource
) != 0)
1415 struct stat statDestination
;
1416 if (stat(destination
, &statDestination
) != 0)
1421 if(statSource
.st_size
!= statDestination
.st_size
)
1426 if(statSource
.st_size
== 0)
1431 #if defined(_WIN32) || defined(__CYGWIN__)
1432 kwsys_ios::ifstream
finSource(source
, (kwsys_ios::ios::binary
|
1433 kwsys_ios::ios::in
));
1434 kwsys_ios::ifstream
finDestination(destination
, (kwsys_ios::ios::binary
|
1435 kwsys_ios::ios::in
));
1437 kwsys_ios::ifstream
finSource(source
);
1438 kwsys_ios::ifstream
finDestination(destination
);
1440 if(!finSource
|| !finDestination
)
1445 char* source_buf
= new char[statSource
.st_size
];
1446 char* dest_buf
= new char[statSource
.st_size
];
1448 finSource
.read(source_buf
, statSource
.st_size
);
1449 finDestination
.read(dest_buf
, statSource
.st_size
);
1451 if(statSource
.st_size
!= static_cast<long>(finSource
.gcount()) ||
1452 statSource
.st_size
!= static_cast<long>(finDestination
.gcount()))
1454 // Failed to read files.
1455 delete [] source_buf
;
1459 int ret
= memcmp((const void*)source_buf
,
1460 (const void*)dest_buf
,
1461 statSource
.st_size
);
1464 delete [] source_buf
;
1471 * Copy a file named by "source" to the file named by "destination".
1473 bool SystemTools::CopyFileAlways(const char* source
, const char* destination
)
1475 // If files are the same do not copy
1476 if ( SystemTools::SameFile(source
, destination
) )
1482 bool perms
= SystemTools::GetPermissions(source
, perm
);
1484 const int bufferSize
= 4096;
1485 char buffer
[bufferSize
];
1487 // If destination is a directory, try to create a file with the same
1488 // name as the source in that directory.
1490 kwsys_stl::string new_destination
;
1491 if(SystemTools::FileExists(destination
) &&
1492 SystemTools::FileIsDirectory(destination
))
1494 new_destination
= destination
;
1495 SystemTools::ConvertToUnixSlashes(new_destination
);
1496 new_destination
+= '/';
1497 kwsys_stl::string source_name
= source
;
1498 new_destination
+= SystemTools::GetFilenameName(source_name
);
1499 destination
= new_destination
.c_str();
1502 // Create destination directory
1504 kwsys_stl::string destination_dir
= destination
;
1505 destination_dir
= SystemTools::GetFilenamePath(destination_dir
);
1506 SystemTools::MakeDirectory(destination_dir
.c_str());
1510 #if defined(_WIN32) || defined(__CYGWIN__)
1511 kwsys_ios::ifstream
fin(source
,
1512 kwsys_ios::ios::binary
| kwsys_ios::ios::in
);
1514 kwsys_ios::ifstream
fin(source
);
1521 // try and remove the destination file so that read only destination files
1522 // can be written to.
1523 // If the remove fails continue so that files in read only directories
1524 // that do not allow file removal can be modified.
1525 SystemTools::RemoveFile(destination
);
1527 #if defined(_WIN32) || defined(__CYGWIN__)
1528 kwsys_ios::ofstream
fout(destination
,
1529 kwsys_ios::ios::binary
| kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1531 kwsys_ios::ofstream
fout(destination
,
1532 kwsys_ios::ios::out
| kwsys_ios::ios::trunc
);
1539 // This copy loop is very sensitive on certain platforms with
1540 // slightly broken stream libraries (like HPUX). Normally, it is
1541 // incorrect to not check the error condition on the fin.read()
1542 // before using the data, but the fin.gcount() will be zero if an
1543 // error occurred. Therefore, the loop should be safe everywhere.
1546 fin
.read(buffer
, bufferSize
);
1549 fout
.write(buffer
, fin
.gcount());
1553 // Make sure the operating system has finished writing the file
1554 // before closing it. This will ensure the file is finished before
1562 struct stat statSource
, statDestination
;
1563 statSource
.st_size
= 12345;
1564 statDestination
.st_size
= 12345;
1565 if(stat(source
, &statSource
) != 0)
1569 else if(stat(destination
, &statDestination
) != 0)
1573 else if(statSource
.st_size
!= statDestination
.st_size
)
1579 if ( !SystemTools::SetPermissions(destination
, perm
) )
1588 * Copy a directory content from "source" directory to the directory named by
1591 bool SystemTools::CopyADirectory(const char* source
, const char* destination
)
1596 if ( !SystemTools::MakeDirectory(destination
) )
1600 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1602 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1603 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1605 kwsys_stl::string fullPath
= source
;
1607 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1608 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1610 kwsys_stl::string fullDestPath
= destination
;
1611 fullDestPath
+= "/";
1612 fullDestPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1613 if (!SystemTools::CopyADirectory(fullPath
.c_str(), fullDestPath
.c_str()))
1620 if(!SystemTools::CopyFileAlways(fullPath
.c_str(), destination
))
1632 // return size of file; also returns zero if no file exists
1633 unsigned long SystemTools::FileLength(const char* filename
)
1636 if (stat(filename
, &fs
) != 0)
1642 return static_cast<unsigned long>(fs
.st_size
);
1646 int SystemTools::Strucmp(const char *s1
, const char *s2
)
1648 // lifted from Graphvis http://www.graphviz.org
1649 while ((*s1
!= '\0')
1650 && (tolower(*s1
) == tolower(*s2
)))
1656 return tolower(*s1
) - tolower(*s2
);
1660 // return file's modified time
1661 long int SystemTools::ModifiedTime(const char* filename
)
1664 if (stat(filename
, &fs
) != 0)
1670 return (long int)fs
.st_mtime
;
1674 // return file's creation time
1675 long int SystemTools::CreationTime(const char* filename
)
1678 if (stat(filename
, &fs
) != 0)
1684 return fs
.st_ctime
>= 0 ? (long int)fs
.st_ctime
: 0;
1688 bool SystemTools::ConvertDateMacroString(const char *str
, time_t *tmt
)
1690 if (!str
|| !tmt
|| strlen(str
) < 12)
1698 // The compilation date of the current source file. The date is a string
1699 // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
1700 // dates generated by the library function asctime declared in TIME.H.
1702 // index: 012345678901
1703 // format: Mmm dd yyyy
1704 // example: Dec 19 2003
1706 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1709 strcpy(buffer
, str
);
1712 char *ptr
= strstr(month_names
, buffer
);
1718 int month
= (ptr
- month_names
) / 3;
1719 int day
= atoi(buffer
+ 4);
1720 int year
= atoi(buffer
+ 7);
1729 tmt2
.tm_mon
= month
;
1730 tmt2
.tm_year
= year
- 1900;
1732 *tmt
= mktime(&tmt2
);
1736 bool SystemTools::ConvertTimeStampMacroString(const char *str
, time_t *tmt
)
1738 if (!str
|| !tmt
|| strlen(str
) < 27)
1746 // The date and time of the last modification of the current source file,
1747 // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
1748 /// where Ddd is the abbreviated day of the week and Date is an integer
1751 // index: 0123456789
1754 // format: Ddd Mmm Date hh:mm:ss yyyy
1755 // example: Fri Dec 19 14:34:58 2003
1757 static char month_names
[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
1760 strcpy(buffer
, str
);
1763 char *ptr
= strstr(month_names
, buffer
+ 4);
1769 int month
= (ptr
- month_names
) / 3;
1770 int day
= atoi(buffer
+ 8);
1771 int hour
= atoi(buffer
+ 11);
1772 int min
= atoi(buffer
+ 14);
1773 int sec
= atoi(buffer
+ 17);
1774 int year
= atoi(buffer
+ 20);
1777 tmt2
.tm_hour
= hour
;
1783 tmt2
.tm_mon
= month
;
1784 tmt2
.tm_year
= year
- 1900;
1786 *tmt
= mktime(&tmt2
);
1790 kwsys_stl::string
SystemTools::GetLastSystemError()
1796 bool SystemTools::RemoveFile(const char* source
)
1800 if ( !SystemTools::GetPermissions(source
, mode
) )
1804 /* Win32 unlink is stupid --- it fails if the file is read-only */
1805 SystemTools::SetPermissions(source
, S_IWRITE
);
1807 bool res
= unlink(source
) != 0 ? false : true;
1811 SystemTools::SetPermissions(source
, mode
);
1817 bool SystemTools::RemoveADirectory(const char* source
)
1822 for (fileNum
= 0; fileNum
< dir
.GetNumberOfFiles(); ++fileNum
)
1824 if (strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".") &&
1825 strcmp(dir
.GetFile(static_cast<unsigned long>(fileNum
)),".."))
1827 kwsys_stl::string fullPath
= source
;
1829 fullPath
+= dir
.GetFile(static_cast<unsigned long>(fileNum
));
1830 if(SystemTools::FileIsDirectory(fullPath
.c_str()))
1832 if (!SystemTools::RemoveADirectory(fullPath
.c_str()))
1839 if(!SystemTools::RemoveFile(fullPath
.c_str()))
1847 return (Rmdir(source
) == 0);
1851 * Find the file the given name. Searches the given path and then
1852 * the system search path. Returns the full path to the file if it is
1853 * found. Otherwise, the empty string is returned.
1855 kwsys_stl::string SystemTools
1856 ::FindFile(const char* name
,
1857 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
1859 // Add the system search path to our path first
1860 kwsys_stl::vector
<kwsys_stl::string
> path
;
1861 SystemTools::GetPath(path
, "CMAKE_FILE_PATH");
1862 SystemTools::GetPath(path
);
1863 // now add the additional paths
1864 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1865 // now look for the file
1866 kwsys_stl::string tryPath
;
1867 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1868 p
!= path
.end(); ++p
)
1873 if(SystemTools::FileExists(tryPath
.c_str()) &&
1874 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1876 return SystemTools::CollapseFullPath(tryPath
.c_str());
1879 // Couldn't find the file.
1884 * Find the executable with the given name. Searches the given path and then
1885 * the system search path. Returns the full path to the executable if it is
1886 * found. Otherwise, the empty string is returned.
1888 kwsys_stl::string
SystemTools::FindProgram(
1890 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
,
1891 bool no_system_path
)
1897 // See if the executable exists as written.
1898 if(SystemTools::FileExists(name
) &&
1899 !SystemTools::FileIsDirectory(name
))
1901 return SystemTools::CollapseFullPath(name
);
1903 kwsys_stl::string tryPath
= name
;
1904 tryPath
+= SystemTools::GetExecutableExtension();
1905 if(SystemTools::FileExists(tryPath
.c_str()) &&
1906 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1908 return SystemTools::CollapseFullPath(tryPath
.c_str());
1910 kwsys_stl::vector
<kwsys_stl::string
> path
;
1911 SystemTools::GetPath(path
, "CMAKE_PROGRAM_PATH");
1912 // Add the system search path to our path.
1913 if (!no_system_path
)
1915 SystemTools::GetPath(path
);
1918 // now add the additional paths
1919 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1921 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1922 p
!= path
.end(); ++p
)
1927 if(SystemTools::FileExists(tryPath
.c_str()) &&
1928 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1930 return SystemTools::CollapseFullPath(tryPath
.c_str());
1934 if(SystemTools::FileExists(tryPath
.c_str()) &&
1935 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1937 return SystemTools::CollapseFullPath(tryPath
.c_str());
1943 tryPath
+= SystemTools::GetExecutableExtension();
1944 if(SystemTools::FileExists(tryPath
.c_str()) &&
1945 !SystemTools::FileIsDirectory(tryPath
.c_str()))
1947 return SystemTools::CollapseFullPath(tryPath
.c_str());
1951 // Couldn't find the program.
1957 * Find the library with the given name. Searches the given path and then
1958 * the system search path. Returns the full path to the library if it is
1959 * found. Otherwise, the empty string is returned.
1961 kwsys_stl::string SystemTools
1962 ::FindLibrary(const char* name
,
1963 const kwsys_stl::vector
<kwsys_stl::string
>& userPaths
)
1965 // See if the executable exists as written.
1966 if(SystemTools::FileExists(name
) &&
1967 !SystemTools::FileIsDirectory(name
))
1969 return SystemTools::CollapseFullPath(name
);
1972 // Add the system search path to our path.
1973 kwsys_stl::vector
<kwsys_stl::string
> path
;
1974 SystemTools::GetPath(path
);
1975 // now add the additional paths
1976 path
.insert(path
.end(), userPaths
.begin(), userPaths
.end());
1977 kwsys_stl::string tryPath
;
1978 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator p
= path
.begin();
1979 p
!= path
.end(); ++p
)
1981 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
1986 if(SystemTools::FileExists(tryPath
.c_str())
1987 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1989 return SystemTools::CollapseFullPath(tryPath
.c_str());
1996 if(SystemTools::FileExists(tryPath
.c_str())
1997 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
1999 return SystemTools::CollapseFullPath(tryPath
.c_str());
2005 if(SystemTools::FileExists(tryPath
.c_str())
2006 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2008 return SystemTools::CollapseFullPath(tryPath
.c_str());
2014 if(SystemTools::FileExists(tryPath
.c_str())
2015 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2017 return SystemTools::CollapseFullPath(tryPath
.c_str());
2022 tryPath
+= ".dylib";
2023 if(SystemTools::FileExists(tryPath
.c_str())
2024 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2026 return SystemTools::CollapseFullPath(tryPath
.c_str());
2032 if(SystemTools::FileExists(tryPath
.c_str())
2033 && !SystemTools::FileIsDirectory(tryPath
.c_str()))
2035 return SystemTools::CollapseFullPath(tryPath
.c_str());
2040 // Couldn't find the library.
2044 bool SystemTools::FileIsDirectory(const char* name
)
2047 if(stat(name
, &fs
) == 0)
2050 return ((fs
.st_mode
& _S_IFDIR
) != 0);
2052 return S_ISDIR(fs
.st_mode
);
2061 int SystemTools::ChangeDirectory(const char *dir
)
2066 kwsys_stl::string
SystemTools::GetCurrentWorkingDirectory(bool collapse
)
2069 const char* cwd
= Getcwd(buf
, 2048);
2070 kwsys_stl::string path
;
2077 return SystemTools::CollapseFullPath(path
.c_str());
2082 kwsys_stl::string
SystemTools::GetProgramPath(const char* in_name
)
2084 kwsys_stl::string dir
, file
;
2085 SystemTools::SplitProgramPath(in_name
, dir
, file
);
2089 bool SystemTools::SplitProgramPath(const char* in_name
,
2090 kwsys_stl::string
& dir
,
2091 kwsys_stl::string
& file
,
2096 SystemTools::ConvertToUnixSlashes(dir
);
2098 if(!SystemTools::FileIsDirectory(dir
.c_str()))
2100 kwsys_stl::string::size_type slashPos
= dir
.rfind("/");
2101 if(slashPos
!= kwsys_stl::string::npos
)
2103 file
= dir
.substr(slashPos
+1);
2104 dir
= dir
.substr(0, slashPos
);
2112 if(!(dir
== "") && !SystemTools::FileIsDirectory(dir
.c_str()))
2114 kwsys_stl::string oldDir
= in_name
;
2115 SystemTools::ConvertToUnixSlashes(oldDir
);
2122 bool SystemTools::FindProgramPath(const char* argv0
,
2123 kwsys_stl::string
& pathOut
,
2124 kwsys_stl::string
& errorMsg
,
2125 const char* exeName
,
2126 const char* buildDir
,
2127 const char* installPrefix
)
2129 kwsys_stl::vector
<kwsys_stl::string
> failures
;
2130 kwsys_stl::string self
= argv0
;
2131 SystemTools::ConvertToUnixSlashes(self
);
2132 failures
.push_back(argv0
);
2133 self
= SystemTools::FindProgram(self
.c_str());
2134 if(!SystemTools::FileExists(self
.c_str()))
2138 kwsys_stl::string intdir
= ".";
2140 intdir
= CMAKE_INTDIR
;
2147 self
+= SystemTools::GetExecutableExtension();
2152 if(!SystemTools::FileExists(self
.c_str()))
2154 failures
.push_back(self
);
2155 self
= installPrefix
;
2160 if(!SystemTools::FileExists(self
.c_str()))
2162 failures
.push_back(self
);
2163 kwsys_ios::ostringstream msg
;
2164 msg
<< "Can not find the command line program " << exeName
<< "\n";
2165 msg
<< " argv[0] = \"" << argv0
<< "\"\n";
2166 msg
<< " Attempted paths:\n";
2167 kwsys_stl::vector
<kwsys_stl::string
>::iterator i
;
2168 for(i
=failures
.begin(); i
!= failures
.end(); ++i
)
2170 msg
<< " \"" << i
->c_str() << "\"\n";
2172 errorMsg
= msg
.str();
2180 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_relative
)
2182 return SystemTools::CollapseFullPath(in_relative
, 0);
2185 void SystemTools::AddTranslationPath(const char * a
, const char * b
)
2187 kwsys_stl::string path_a
= a
;
2188 kwsys_stl::string path_b
= b
;
2189 SystemTools::ConvertToUnixSlashes(path_a
);
2190 SystemTools::ConvertToUnixSlashes(path_b
);
2191 // First check this is a directory path, since we don't want the table to
2193 if( SystemTools::FileIsDirectory( path_a
.c_str() ) )
2195 // Make sure the path is a full path and does not contain no '..'
2196 if( SystemTools::FileIsFullPath(path_b
.c_str()) && path_b
.find("..")
2197 == kwsys_stl::string::npos
)
2199 // Before inserting make sure path ends with '/'
2200 if(path_a
.size() && path_a
[path_a
.size() -1] != '/')
2204 if(path_b
.size() && path_b
[path_b
.size() -1] != '/')
2208 if( !(path_a
== path_b
) )
2210 SystemTools::TranslationMap
->insert(
2211 SystemToolsTranslationMap::value_type(path_a
, path_b
));
2217 void SystemTools::AddKeepPath(const char* dir
)
2219 kwsys_stl::string cdir
= SystemTools::CollapseFullPath(dir
);
2220 SystemTools::AddTranslationPath(cdir
.c_str(), dir
);
2223 void SystemTools::CheckTranslationPath(kwsys_stl::string
& path
)
2225 // Do not translate paths that are too short to have meaningful
2232 // Always add a trailing slash before translation. It does not
2233 // matter if this adds an extra slash, but we do not want to
2234 // translate part of a directory (like the foo part of foo-dir).
2237 // In case a file was specified we still have to go through this:
2238 // Now convert any path found in the table back to the one desired:
2239 kwsys_stl::map
<kwsys_stl::string
,kwsys_stl::string
>::const_iterator it
;
2240 for(it
= SystemTools::TranslationMap
->begin();
2241 it
!= SystemTools::TranslationMap
->end();
2244 // We need to check of the path is a substring of the other path
2245 if(path
.find( it
->first
) == 0)
2247 path
= path
.replace( 0, it
->first
.size(), it
->second
);
2251 // Remove the trailing slash we added before.
2252 path
.erase(path
.end()-1, path
.end());
2256 SystemToolsAppendComponents(
2257 kwsys_stl::vector
<kwsys_stl::string
>& out_components
,
2258 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator first
,
2259 kwsys_stl::vector
<kwsys_stl::string
>::const_iterator last
)
2261 for(kwsys_stl::vector
<kwsys_stl::string
>::const_iterator i
= first
;
2266 if(out_components
.begin() != out_components
.end())
2268 out_components
.erase(out_components
.end()-1, out_components
.end());
2271 else if(!(*i
== ".") && !(*i
== ""))
2273 out_components
.push_back(*i
);
2278 kwsys_stl::string
SystemTools::CollapseFullPath(const char* in_path
,
2279 const char* in_base
)
2281 // Collect the output path components.
2282 kwsys_stl::vector
<kwsys_stl::string
> out_components
;
2284 // Split the input path components.
2285 kwsys_stl::vector
<kwsys_stl::string
> path_components
;
2286 SystemTools::SplitPath(in_path
, path_components
);
2288 // If the input path is relative, start with a base path.
2289 if(path_components
[0].length() == 0)
2291 kwsys_stl::vector
<kwsys_stl::string
> base_components
;
2294 // Use the given base path.
2295 SystemTools::SplitPath(in_base
, base_components
);
2299 // Use the current working directory as a base path.
2301 if(const char* cwd
= Getcwd(buf
, 2048))
2303 SystemTools::SplitPath(cwd
, base_components
);
2311 // Append base path components to the output path.
2312 out_components
.push_back(base_components
[0]);
2313 SystemToolsAppendComponents(out_components
,
2314 base_components
.begin()+1,
2315 base_components
.end());
2318 // Append input path components to the output path.
2319 SystemToolsAppendComponents(out_components
,
2320 path_components
.begin(),
2321 path_components
.end());
2323 // Transform the path back to a string.
2324 kwsys_stl::string newPath
= SystemTools::JoinPath(out_components
);
2326 // Update the translation table with this potentially new path.
2327 SystemTools::AddTranslationPath(newPath
.c_str(), in_path
);
2328 SystemTools::CheckTranslationPath(newPath
);
2330 newPath
= SystemTools::GetActualCaseForPath(newPath
.c_str());
2332 // Return the reconstructed path.
2337 // OK, some fun stuff to get the actual case of a given path.
2338 // Basically, you just need to call ShortPath, then GetLongPathName,
2339 // However, GetLongPathName is not implemented on windows NT and 95,
2340 // so we have to simulate it on those versions
2342 int OldWindowsGetLongPath(kwsys_stl::string
const& shortPath
,
2343 kwsys_stl::string
& longPath
)
2345 kwsys_stl::string::size_type iFound
= shortPath
.rfind('/');
2346 if (iFound
> 1 && iFound
!= shortPath
.npos
)
2348 // recurse to peel off components
2350 if (OldWindowsGetLongPath(shortPath
.substr(0, iFound
), longPath
) > 0)
2353 if (shortPath
[1] != '/')
2355 WIN32_FIND_DATA findData
;
2357 // append the long component name to the path
2359 if (INVALID_HANDLE_VALUE
!= ::FindFirstFile
2360 (shortPath
.c_str(), &findData
))
2362 longPath
+= findData
.cFileName
;
2366 // if FindFirstFile fails, return the error code
2376 longPath
= shortPath
;
2378 return longPath
.size();
2382 int PortableGetLongPathName(const char* pathIn
,
2383 kwsys_stl::string
& longPath
)
2385 kwsys_stl::string shortPath
;
2386 if(!SystemTools::GetShortPath(pathIn
, shortPath
))
2390 HMODULE lh
= LoadLibrary("Kernel32.dll");
2393 FARPROC proc
= GetProcAddress(lh
, "GetLongPathNameA");
2396 typedef DWORD (WINAPI
* GetLongFunctionPtr
) (LPCSTR
,LPSTR
,DWORD
);
2397 GetLongFunctionPtr func
= (GetLongFunctionPtr
)proc
;
2398 char buffer
[MAX_PATH
+1];
2399 int len
= (*func
)(shortPath
.c_str(), buffer
, MAX_PATH
+1);
2400 if(len
== 0 || len
> MAX_PATH
+1)
2411 return OldWindowsGetLongPath(shortPath
.c_str(), longPath
);
2416 //----------------------------------------------------------------------------
2417 kwsys_stl::string
SystemTools::GetActualCaseForPath(const char* p
)
2422 kwsys_stl::string shortPath
;
2423 if(!SystemTools::GetShortPath(p
, shortPath
))
2427 kwsys_stl::string longPath
;
2428 int len
= PortableGetLongPathName(shortPath
.c_str(), longPath
);
2429 if(len
== 0 || len
> MAX_PATH
+1)
2437 //----------------------------------------------------------------------------
2438 void SystemTools::SplitPath(const char* p
,
2439 kwsys_stl::vector
<kwsys_stl::string
>& components
)
2442 // Identify the root component.
2444 if((c
[0] == '/' && c
[1] == '/') || (c
[0] == '\\' && c
[1] == '\\'))
2447 components
.push_back("//");
2450 else if(c
[0] == '/')
2453 components
.push_back("/");
2456 else if(c
[0] && c
[1] == ':' && (c
[2] == '/' || c
[2] == '\\'))
2459 kwsys_stl::string root
= "_:/";
2461 components
.push_back(root
);
2464 else if(c
[0] && c
[1] == ':')
2466 // Path relative to a windows drive working directory.
2467 kwsys_stl::string root
= "_:";
2469 components
.push_back(root
);
2475 components
.push_back("");
2478 // Parse the remaining components.
2479 const char* first
= c
;
2480 const char* last
= first
;
2483 if(*last
== '/' || *last
== '\\')
2485 // End of a component. Save it.
2486 components
.push_back(kwsys_stl::string(first
, last
-first
));
2491 // Save the last component unless there were no components.
2494 components
.push_back(kwsys_stl::string(first
, last
-first
));
2498 //----------------------------------------------------------------------------
2500 SystemTools::JoinPath(const kwsys_stl::vector
<kwsys_stl::string
>& components
)
2502 kwsys_stl::string result
;
2503 if(components
.size() > 0)
2505 result
+= components
[0];
2507 if(components
.size() > 1)
2509 result
+= components
[1];
2511 for(unsigned int i
=2; i
< components
.size(); ++i
)
2514 result
+= components
[i
];
2519 //----------------------------------------------------------------------------
2520 bool SystemTools::ComparePath(const char* c1
, const char* c2
)
2522 #if defined(_WIN32) || defined(__APPLE__)
2523 return SystemTools::Strucmp(c1
, c2
) == 0;
2525 return strcmp(c1
, c2
) == 0;
2529 //----------------------------------------------------------------------------
2530 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
, char separator
)
2532 kwsys_stl::string
data(str
);
2533 kwsys_stl::string::size_type lpos
= 0;
2534 while(lpos
< data
.length())
2536 kwsys_stl::string::size_type rpos
= data
.find_first_of(separator
, lpos
);
2537 if(rpos
== kwsys_stl::string::npos
)
2539 // Line ends at end of string without a newline.
2540 lines
.push_back(data
.substr(lpos
));
2545 // Line ends in a "\n", remove the character.
2546 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
2553 //----------------------------------------------------------------------------
2554 bool SystemTools::Split(const char* str
, kwsys_stl::vector
<kwsys_stl::string
>& lines
)
2556 kwsys_stl::string
data(str
);
2557 kwsys_stl::string::size_type lpos
= 0;
2558 while(lpos
< data
.length())
2560 kwsys_stl::string::size_type rpos
= data
.find_first_of("\n", lpos
);
2561 if(rpos
== kwsys_stl::string::npos
)
2563 // Line ends at end of string without a newline.
2564 lines
.push_back(data
.substr(lpos
));
2567 if((rpos
> lpos
) && (data
[rpos
-1] == '\r'))
2569 // Line ends in a "\r\n" pair, remove both characters.
2570 lines
.push_back(data
.substr(lpos
, (rpos
-1)-lpos
));
2574 // Line ends in a "\n", remove the character.
2575 lines
.push_back(data
.substr(lpos
, rpos
-lpos
));
2583 * Return path of a full filename (no trailing slashes).
2584 * Warning: returned path is converted to Unix slashes format.
2586 kwsys_stl::string
SystemTools::GetFilenamePath(const kwsys_stl::string
& filename
)
2588 kwsys_stl::string fn
= filename
;
2589 SystemTools::ConvertToUnixSlashes(fn
);
2591 kwsys_stl::string::size_type slash_pos
= fn
.rfind("/");
2592 if(slash_pos
!= kwsys_stl::string::npos
)
2594 return fn
.substr(0, slash_pos
);
2604 * Return file name of a full filename (i.e. file name without path).
2606 kwsys_stl::string
SystemTools::GetFilenameName(const kwsys_stl::string
& filename
)
2609 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/\\");
2611 kwsys_stl::string::size_type slash_pos
= filename
.find_last_of("/");
2613 if(slash_pos
!= kwsys_stl::string::npos
)
2615 return filename
.substr(slash_pos
+ 1);
2625 * Return file extension of a full filename (dot included).
2626 * Warning: this is the longest extension (for example: .tar.gz)
2628 kwsys_stl::string
SystemTools::GetFilenameExtension(const kwsys_stl::string
& filename
)
2630 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2631 kwsys_stl::string::size_type dot_pos
= name
.find(".");
2632 if(dot_pos
!= kwsys_stl::string::npos
)
2634 return name
.substr(dot_pos
);
2643 * Return file extension of a full filename (dot included).
2644 * Warning: this is the shortest extension (for example: .tar.gz)
2646 kwsys_stl::string
SystemTools::GetFilenameLastExtension(const kwsys_stl::string
& filename
)
2648 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2649 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
2650 if(dot_pos
!= kwsys_stl::string::npos
)
2652 return name
.substr(dot_pos
);
2661 * Return file name without extension of a full filename (i.e. without path).
2662 * Warning: it considers the longest extension (for example: .tar.gz)
2664 kwsys_stl::string
SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string
& filename
)
2666 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2667 kwsys_stl::string::size_type dot_pos
= name
.find(".");
2668 if(dot_pos
!= kwsys_stl::string::npos
)
2670 return name
.substr(0, dot_pos
);
2680 * Return file name without extension of a full filename (i.e. without path).
2681 * Warning: it considers the last extension (for example: removes .gz
2685 SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string
& filename
)
2687 kwsys_stl::string name
= SystemTools::GetFilenameName(filename
);
2688 kwsys_stl::string::size_type dot_pos
= name
.rfind(".");
2689 if(dot_pos
!= kwsys_stl::string::npos
)
2691 return name
.substr(0, dot_pos
);
2699 bool SystemTools::FileHasSignature(const char *filename
,
2700 const char *signature
,
2703 if (!filename
|| !signature
)
2709 fp
= fopen(filename
, "rb");
2715 fseek(fp
, offset
, SEEK_SET
);
2718 size_t signature_len
= strlen(signature
);
2719 char *buffer
= new char [signature_len
];
2721 if (fread(buffer
, 1, signature_len
, fp
) == signature_len
)
2723 res
= (!strncmp(buffer
, signature
, signature_len
) ? true : false);
2732 bool SystemTools::LocateFileInDir(const char *filename
,
2734 kwsys_stl::string
& filename_found
,
2735 int try_filename_dirs
)
2737 if (!filename
|| !dir
)
2742 // Get the basename of 'filename'
2744 kwsys_stl::string filename_base
= SystemTools::GetFilenameName(filename
);
2746 // Check if 'dir' is really a directory
2747 // If win32 and matches something like C:, accept it as a dir
2749 kwsys_stl::string real_dir
;
2750 if (!SystemTools::FileIsDirectory(dir
))
2753 size_t dir_len
= strlen(dir
);
2754 if (dir_len
< 2 || dir
[dir_len
- 1] != ':')
2757 real_dir
= SystemTools::GetFilenamePath(dir
);
2758 dir
= real_dir
.c_str();
2764 // Try to find the file in 'dir'
2767 if (filename_base
.size() && dir
)
2769 size_t dir_len
= strlen(dir
);
2771 (dir_len
&& dir
[dir_len
- 1] != '/' && dir
[dir_len
- 1] != '\\');
2773 kwsys_stl::string temp
= dir
;
2778 temp
+= filename_base
;
2780 if (SystemTools::FileExists(filename_found
.c_str()))
2783 filename_found
= temp
;
2786 // If not found, we can try harder by appending part of the file to
2787 // to the directory to look inside.
2788 // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then
2789 // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc.
2791 else if (try_filename_dirs
)
2793 kwsys_stl::string
filename_dir(filename
);
2794 kwsys_stl::string filename_dir_base
;
2795 kwsys_stl::string filename_dir_bases
;
2798 filename_dir
= SystemTools::GetFilenamePath(filename_dir
);
2799 filename_dir_base
= SystemTools::GetFilenameName(filename_dir
);
2801 if (!filename_dir_base
.size() ||
2802 filename_dir_base
[filename_dir_base
.size() - 1] == ':')
2804 if (!filename_dir_base
.size())
2810 filename_dir_bases
= filename_dir_base
+ "/" + filename_dir_bases
;
2817 temp
+= filename_dir_bases
;
2819 res
= SystemTools::LocateFileInDir(
2820 filename_base
.c_str(), temp
.c_str(), filename_found
, 0);
2822 } while (!res
&& filename_dir_base
.size());
2829 bool SystemTools::FileIsFullPath(const char* in_name
)
2831 kwsys_stl::string name
= in_name
;
2832 #if defined(_WIN32) || defined(__CYGWIN__)
2833 // On Windows, the name must be at least two characters long.
2834 if(name
.length() < 2)
2847 // On UNIX, the name must be at least one character long.
2848 if(name
.length() < 1)
2853 // On UNIX, the name must begin in a '/'.
2854 // On Windows, if the name begins in a '/', then it is a full
2863 bool SystemTools::GetShortPath(const char* path
, kwsys_stl::string
& shortPath
)
2865 #if defined(WIN32) && !defined(__CYGWIN__)
2866 const int size
= int(strlen(path
)) +1; // size of return
2867 char *buffer
= new char[size
]; // create a buffer
2868 char *tempPath
= new char[size
]; // create a buffer
2871 // if the path passed in has quotes around it, first remove the quotes
2872 if (path
[0] == '"' && path
[strlen(path
)-1] == '"')
2874 strcpy(tempPath
,path
+1);
2875 tempPath
[strlen(tempPath
)-1] = '\0';
2879 strcpy(tempPath
,path
);
2883 ret
= GetShortPathName(tempPath
, buffer
, size
);
2885 if(buffer
[0] == 0 || ret
> size
)
2904 void SystemTools::SplitProgramFromArgs(const char* path
,
2905 kwsys_stl::string
& program
, kwsys_stl::string
& args
)
2907 // see if this is a full path to a program
2908 // if so then set program to path and args to nothing
2909 if(SystemTools::FileExists(path
))
2915 // Try to find the program in the path, note the program
2916 // may have spaces in its name so we have to look for it
2917 kwsys_stl::vector
<kwsys_stl::string
> e
;
2918 kwsys_stl::string findProg
= SystemTools::FindProgram(path
, e
);
2926 // Now try and peel off space separated chunks from the end of the string
2927 // so the largest path possible is found allowing for spaces in the path
2928 kwsys_stl::string dir
= path
;
2929 kwsys_stl::string::size_type spacePos
= dir
.rfind(' ');
2930 while(spacePos
!= kwsys_stl::string::npos
)
2932 kwsys_stl::string tryProg
= dir
.substr(0, spacePos
);
2933 // See if the file exists
2934 if(SystemTools::FileExists(tryProg
.c_str()))
2937 // remove trailing spaces from program
2938 kwsys_stl::string::size_type pos
= program
.size()-1;
2939 while(program
[pos
] == ' ')
2944 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
2947 // Now try and find the the program in the path
2948 findProg
= SystemTools::FindProgram(tryProg
.c_str(), e
);
2952 // remove trailing spaces from program
2953 kwsys_stl::string::size_type pos
= program
.size()-1;
2954 while(program
[pos
] == ' ')
2959 args
= dir
.substr(spacePos
, dir
.size()-spacePos
);
2962 // move past the space for the next search
2964 spacePos
= dir
.rfind(' ', spacePos
);
2971 kwsys_stl::string
SystemTools::GetCurrentDateTime(const char* format
)
2976 strftime(buf
, sizeof(buf
), format
, localtime(&t
));
2980 kwsys_stl::string
SystemTools::MakeCindentifier(const char* s
)
2982 kwsys_stl::string
str(s
);
2983 if (str
.find_first_of("0123456789") == 0)
2988 kwsys_stl::string
permited_chars("_"
2989 "abcdefghijklmnopqrstuvwxyz"
2990 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2992 kwsys_stl::string::size_type pos
= 0;
2993 while ((pos
= str
.find_first_not_of(permited_chars
, pos
)) != kwsys_stl::string::npos
)
3000 // Due to a buggy stream library on the HP and another on Mac OSX, we
3001 // need this very carefully written version of getline. Returns true
3002 // if any data were read before the end-of-file was reached.
3003 bool SystemTools::GetLineFromStream(kwsys_ios::istream
& is
, kwsys_stl::string
& line
,
3004 bool *has_newline
/* = 0 */)
3006 const int bufferSize
= 1024;
3007 char buffer
[bufferSize
];
3009 bool haveData
= false;
3012 *has_newline
= false;
3015 // If no characters are read from the stream, the end of file has
3017 while((is
.getline(buffer
, bufferSize
), is
.gcount() > 0))
3020 line
.append(buffer
);
3022 // If newline character was read, the gcount includes the
3023 // character, but the buffer does not. The end of line has been
3025 if(strlen(buffer
) < static_cast<size_t>(is
.gcount()))
3029 *has_newline
= true;
3034 // The fail bit may be set. Clear it.
3035 is
.clear(is
.rdstate() & ~kwsys_ios::ios::failbit
);
3040 int SystemTools::GetTerminalWidth()
3045 char *columns
; /* Unix98 environment variable */
3046 if(ioctl(1, TIOCGWINSZ
, &ws
) != -1 && ws
.ws_col
>0 && ws
.ws_row
>0)
3050 if(!isatty(STDOUT_FILENO
))
3054 columns
= getenv("COLUMNS");
3055 if(columns
&& *columns
)
3059 t
= strtol(columns
, &endptr
, 0);
3060 if(endptr
&& !*endptr
&& (t
>0) && (t
<1000))
3073 bool SystemTools::GetPermissions(const char* file
, mode_t
& mode
)
3081 if ( stat(file
, &st
) < 0 )
3089 bool SystemTools::SetPermissions(const char* file
, mode_t mode
)
3095 if ( !SystemTools::FileExists(file
) )
3099 if ( chmod(file
, mode
) < 0 )
3107 kwsys_stl::string
SystemTools::GetParentDirectory(const char* fileOrDir
)
3109 if ( !fileOrDir
|| !*fileOrDir
)
3113 kwsys_stl::string res
= fileOrDir
;
3114 SystemTools::ConvertToUnixSlashes(res
);
3115 kwsys_stl::string::size_type cc
= res
.size()-1;
3116 if ( res
[cc
] == '/' )
3120 for ( ; cc
> 0; cc
-- )
3122 if ( res
[cc
] == '/' )
3127 return res
.substr(0, cc
);
3130 bool SystemTools::IsSubDirectory(const char* cSubdir
, const char* cDir
)
3132 kwsys_stl::string subdir
= cSubdir
;
3133 kwsys_stl::string dir
= cDir
;
3134 SystemTools::ConvertToUnixSlashes(dir
);
3135 kwsys_stl::string path
= subdir
;
3138 path
= SystemTools::GetParentDirectory(path
.c_str());
3144 while ( path
.size() > dir
.size() );
3148 kwsys_stl::string
SystemTools::FileExistsInParentDirectories(const char* fname
,
3149 const char* directory
, const char* toplevel
)
3151 kwsys_stl::string file
= fname
;
3152 SystemTools::ConvertToUnixSlashes(file
);
3153 kwsys_stl::string dir
= directory
;
3154 SystemTools::ConvertToUnixSlashes(dir
);
3155 while ( !dir
.empty() )
3157 kwsys_stl::string path
= dir
+ "/" + file
;
3158 if ( SystemTools::FileExists(path
.c_str()) )
3162 if ( dir
.size() < strlen(toplevel
) )
3166 dir
= SystemTools::GetParentDirectory(dir
.c_str());
3171 void SystemTools::Delay(unsigned int msec
)
3176 usleep(msec
* 1000);
3180 void SystemTools::ConvertWindowsCommandLineToUnixArguments(
3181 const char *cmd_line
, int *argc
, char ***argv
)
3183 if (!cmd_line
|| !argc
|| !argv
)
3188 // A space delimites an argument except when it is inside a quote
3192 size_t cmd_line_len
= strlen(cmd_line
);
3195 for (i
= 0; i
< cmd_line_len
; i
++)
3197 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
3201 if (i
< cmd_line_len
)
3203 if (cmd_line
[i
] == '\"')
3206 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
3214 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
3223 (*argv
) = new char* [(*argc
) + 1];
3224 (*argv
)[(*argc
)] = NULL
;
3226 // Set the first arg to be the exec name
3228 (*argv
)[0] = new char [1024];
3230 ::GetModuleFileName(0, (*argv
)[0], 1024);
3232 (*argv
)[0][0] = '\0';
3235 // Allocate the others
3238 for (j
= 1; j
< (*argc
); j
++)
3240 (*argv
)[j
] = new char [cmd_line_len
+ 10];
3248 for (i
= 0; i
< cmd_line_len
; i
++)
3250 while (isspace(cmd_line
[i
]) && i
< cmd_line_len
)
3254 if (i
< cmd_line_len
)
3256 if (cmd_line
[i
] == '\"')
3260 while (cmd_line
[i
] != '\"' && i
< cmd_line_len
)
3264 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
3265 (*argv
)[argc_idx
][i
- pos
] = '\0';
3271 while (!isspace(cmd_line
[i
]) && i
< cmd_line_len
)
3275 memcpy((*argv
)[argc_idx
], &cmd_line
[pos
], i
- pos
);
3276 (*argv
)[argc_idx
][i
- pos
] = '\0';
3283 kwsys_stl::string
SystemTools::GetOperatingSystemNameAndVersion()
3285 kwsys_stl::string res
;
3290 OSVERSIONINFOEX osvi
;
3291 BOOL bOsVersionInfoEx
;
3293 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
3294 // If that fails, try using the OSVERSIONINFO structure.
3296 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
3297 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
3299 bOsVersionInfoEx
= GetVersionEx((OSVERSIONINFO
*)&osvi
);
3300 if (!bOsVersionInfoEx
)
3302 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
3303 if (!GetVersionEx((OSVERSIONINFO
*)&osvi
))
3309 switch (osvi
.dwPlatformId
)
3311 // Test for the Windows NT product family.
3313 case VER_PLATFORM_WIN32_NT
:
3315 // Test for the specific product family.
3317 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
3319 res
+= "Microsoft Windows Server 2003 family";
3322 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
3324 res
+= "Microsoft Windows XP";
3327 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
3329 res
+= "Microsoft Windows 2000";
3332 if (osvi
.dwMajorVersion
<= 4)
3334 res
+= "Microsoft Windows NT";
3337 // Test for specific product on Windows NT 4.0 SP6 and later.
3339 if (bOsVersionInfoEx
)
3341 // Test for the workstation type.
3343 #if (_MSC_VER >= 1300)
3344 if (osvi
.wProductType
== VER_NT_WORKSTATION
)
3346 if (osvi
.dwMajorVersion
== 4)
3348 res
+= " Workstation 4.0";
3350 else if (osvi
.wSuiteMask
& VER_SUITE_PERSONAL
)
3352 res
+= " Home Edition";
3356 res
+= " Professional";
3360 // Test for the server type.
3362 else if (osvi
.wProductType
== VER_NT_SERVER
)
3364 if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
3366 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
3368 res
+= " Datacenter Edition";
3370 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
3372 res
+= " Enterprise Edition";
3374 else if (osvi
.wSuiteMask
== VER_SUITE_BLADE
)
3376 res
+= " Web Edition";
3380 res
+= " Standard Edition";
3384 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
3386 if (osvi
.wSuiteMask
& VER_SUITE_DATACENTER
)
3388 res
+= " Datacenter Server";
3390 else if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
3392 res
+= " Advanced Server";
3400 else // Windows NT 4.0
3402 if (osvi
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
3404 res
+= " Server 4.0, Enterprise Edition";
3408 res
+= " Server 4.0";
3412 #endif // Visual Studio 7 and up
3415 // Test for specific product on Windows NT 4.0 SP5 and earlier
3421 char szProductType
[BUFSIZE
];
3422 DWORD dwBufLen
=BUFSIZE
;
3425 lRet
= RegOpenKeyEx(
3427 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
3428 0, KEY_QUERY_VALUE
, &hKey
);
3429 if (lRet
!= ERROR_SUCCESS
)
3434 lRet
= RegQueryValueEx(hKey
, "ProductType", NULL
, NULL
,
3435 (LPBYTE
) szProductType
, &dwBufLen
);
3437 if ((lRet
!= ERROR_SUCCESS
) || (dwBufLen
> BUFSIZE
))
3444 if (lstrcmpi("WINNT", szProductType
) == 0)
3446 res
+= " Workstation";
3448 if (lstrcmpi("LANMANNT", szProductType
) == 0)
3452 if (lstrcmpi("SERVERNT", szProductType
) == 0)
3454 res
+= " Advanced Server";
3458 sprintf(buffer
, "%d", osvi
.dwMajorVersion
);
3461 sprintf(buffer
, "%d", osvi
.dwMinorVersion
);
3465 // Display service pack (if any) and build number.
3467 if (osvi
.dwMajorVersion
== 4 &&
3468 lstrcmpi(osvi
.szCSDVersion
, "Service Pack 6") == 0)
3473 // Test for SP6 versus SP6a.
3475 lRet
= RegOpenKeyEx(
3477 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
3478 0, KEY_QUERY_VALUE
, &hKey
);
3480 if (lRet
== ERROR_SUCCESS
)
3482 res
+= " Service Pack 6a (Build ";
3483 sprintf(buffer
, "%d", osvi
.dwBuildNumber
& 0xFFFF);
3487 else // Windows NT 4.0 prior to SP6a
3490 res
+= osvi
.szCSDVersion
;
3492 sprintf(buffer
, "%d", osvi
.dwBuildNumber
& 0xFFFF);
3499 else // Windows NT 3.51 and earlier or Windows 2000 and later
3502 res
+= osvi
.szCSDVersion
;
3504 sprintf(buffer
, "%d", osvi
.dwBuildNumber
& 0xFFFF);
3511 // Test for the Windows 95 product family.
3513 case VER_PLATFORM_WIN32_WINDOWS
:
3515 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
3517 res
+= "Microsoft Windows 95";
3518 if (osvi
.szCSDVersion
[1] == 'C' || osvi
.szCSDVersion
[1] == 'B')
3524 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
3526 res
+= "Microsoft Windows 98";
3527 if (osvi
.szCSDVersion
[1] == 'A')
3533 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
3535 res
+= "Microsoft Windows Millennium Edition";
3539 case VER_PLATFORM_WIN32s
:
3541 res
+= "Microsoft Win32s";
3549 // These must NOT be initialized. Default initialization to zero is
3551 unsigned int SystemToolsManagerCount
;
3552 SystemToolsTranslationMap
*SystemTools::TranslationMap
;
3554 // SystemToolsManager manages the SystemTools singleton.
3555 // SystemToolsManager should be included in any translation unit
3556 // that will use SystemTools or that implements the singleton
3557 // pattern. It makes sure that the SystemTools singleton is created
3558 // before and destroyed after all other singletons in CMake.
3560 SystemToolsManager::SystemToolsManager()
3562 if(++SystemToolsManagerCount
== 1)
3564 SystemTools::ClassInitialize();
3568 SystemToolsManager::~SystemToolsManager()
3570 if(--SystemToolsManagerCount
== 0)
3572 SystemTools::ClassFinalize();
3576 void SystemTools::ClassInitialize()
3578 // Allocate the translation map first.
3579 SystemTools::TranslationMap
= new SystemToolsTranslationMap
;
3581 // Add some special translation paths for unix. These are not added
3582 // for windows because drive letters need to be maintained. Also,
3583 // there are not sym-links and mount points on windows anyway.
3584 #if !defined(_WIN32) || defined(__CYGWIN__)
3585 // Work-around an SGI problem by always adding this mapping:
3586 SystemTools::AddTranslationPath("/tmp_mnt/", "/");
3587 // The tmp path is frequently a logical path so always keep it:
3588 SystemTools::AddKeepPath("/tmp/");
3590 // If the current working directory is a logical path then keep the
3592 if(const char* pwd
= getenv("PWD"))
3595 if(const char* cwd
= Getcwd(buf
, 2048))
3597 kwsys_stl::string pwd_path
;
3598 Realpath(pwd
, pwd_path
);
3599 if(cwd
== pwd_path
&& strcmp(cwd
, pwd
) != 0)
3601 // The current working directory is a logical path. Split
3602 // both the logical and physical paths into their components.
3603 kwsys_stl::vector
<kwsys_stl::string
> cwd_components
;
3604 kwsys_stl::vector
<kwsys_stl::string
> pwd_components
;
3605 SystemTools::SplitPath(cwd
, cwd_components
);
3606 SystemTools::SplitPath(pwd
, pwd_components
);
3608 // Remove the common ending of the paths to leave only the
3609 // part that changes under the logical mapping.
3610 kwsys_stl::vector
<kwsys_stl::string
>::iterator ic
= cwd_components
.end();
3611 kwsys_stl::vector
<kwsys_stl::string
>::iterator ip
= pwd_components
.end();
3612 for(;ip
!= pwd_components
.begin() && ic
!= cwd_components
.begin() &&
3613 *(ip
-1) == *(ic
-1); --ip
,--ic
);
3614 cwd_components
.erase(ic
, cwd_components
.end());
3615 pwd_components
.erase(ip
, pwd_components
.end());
3617 // Reconstruct the string versions of the part of the path
3619 kwsys_stl::string cwd_changed
= SystemTools::JoinPath(cwd_components
);
3620 kwsys_stl::string pwd_changed
= SystemTools::JoinPath(pwd_components
);
3622 // Add the translation to keep the logical path name.
3623 if(!cwd_changed
.empty() && !pwd_changed
.empty())
3625 SystemTools::AddTranslationPath(cwd_changed
.c_str(),
3626 pwd_changed
.c_str());
3634 void SystemTools::ClassFinalize()
3636 delete SystemTools::TranslationMap
;
3640 } // namespace KWSYS_NAMESPACE
3642 #if defined(_MSC_VER) && defined(_DEBUG)
3643 # include <crtdbg.h>
3645 # include <stdlib.h>
3646 namespace KWSYS_NAMESPACE
3649 static int SystemToolsDebugReport(int, char* message
, int*)
3651 fprintf(stderr
, message
);
3654 void SystemTools::EnableMSVCDebugHook()
3656 if(getenv("DART_TEST_FROM_DART"))
3658 _CrtSetReportHook(SystemToolsDebugReport
);
3662 } // namespace KWSYS_NAMESPACE
3664 namespace KWSYS_NAMESPACE
3666 void SystemTools::EnableMSVCDebugHook() {}
3667 } // namespace KWSYS_NAMESPACE