FIX: stupid pb fixed (close to being medieval'ed by The Ken)
[cmake.git] / Source / cmSystemTools.cxx
blob6adc0f5d4112752d032d4f8ac762526c946447e8
1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmSystemTools.cxx,v $
5 Language: C++
6 Date: $Date: 2002-07-25 20:41:36 $
7 Version: $Revision: 1.162 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmSystemTools.h"
18 #include "errno.h"
19 #include "stdio.h"
20 #include <sys/stat.h>
21 #include "cmRegularExpression.h"
22 #include <ctype.h>
23 #include "cmDirectory.h"
24 #include "cmMakefile.h"
26 // support for realpath call
27 #ifndef _WIN32
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <sys/param.h>
31 #include <sys/wait.h>
32 #endif
34 #if defined(_MSC_VER) || defined(__BORLANDC__)
35 #include <string.h>
36 #include <windows.h>
37 #include <direct.h>
38 #define _unlink unlink
39 inline int Mkdir(const char* dir)
41 return _mkdir(dir);
43 inline const char* Getcwd(char* buf, unsigned int len)
45 return _getcwd(buf, len);
47 inline int Chdir(const char* dir)
49 #if defined(__BORLANDC__)
50 return chdir(dir);
51 #else
52 return _chdir(dir);
53 #endif
55 #else
56 #include <sys/types.h>
57 #include <fcntl.h>
58 #include <unistd.h>
59 inline int Mkdir(const char* dir)
61 return mkdir(dir, 00777);
63 inline const char* Getcwd(char* buf, unsigned int len)
65 return getcwd(buf, len);
67 inline int Chdir(const char* dir)
69 return chdir(dir);
71 #endif
73 bool cmSystemTools::s_DisableRunCommandOutput = false;
74 bool cmSystemTools::s_ErrorOccured = false;
75 bool cmSystemTools::s_DisableMessages = false;
77 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, bool&);
79 // adds the elements of the env variable path to the arg passed in
80 void cmSystemTools::GetPath(std::vector<std::string>& path)
82 #if defined(_WIN32) && !defined(__CYGWIN__)
83 const char* pathSep = ";";
84 #else
85 const char* pathSep = ":";
86 #endif
87 std::string pathEnv = getenv("PATH");
88 // A hack to make the below algorithm work.
89 if(pathEnv[pathEnv.length()-1] != ':')
91 pathEnv += pathSep;
93 std::string::size_type start =0;
94 bool done = false;
95 while(!done)
97 std::string::size_type endpos = pathEnv.find(pathSep, start);
98 if(endpos != std::string::npos)
100 path.push_back(pathEnv.substr(start, endpos-start));
101 start = endpos+1;
103 else
105 done = true;
108 for(std::vector<std::string>::iterator i = path.begin();
109 i != path.end(); ++i)
111 cmSystemTools::ConvertToUnixSlashes(*i);
116 const char* cmSystemTools::GetExecutableExtension()
118 #if defined(_WIN32) || defined(__CYGWIN__)
119 return ".exe";
120 #else
121 return "";
122 #endif
126 bool cmSystemTools::MakeDirectory(const char* path)
128 if(cmSystemTools::FileExists(path))
130 return true;
132 std::string dir = path;
133 if(dir.size() == 0)
135 return false;
137 cmSystemTools::ConvertToUnixSlashes(dir);
139 std::string::size_type pos = dir.find(':');
140 if(pos == std::string::npos)
142 pos = 0;
144 std::string topdir;
145 while((pos = dir.find('/', pos)) != std::string::npos)
147 topdir = dir.substr(0, pos);
148 Mkdir(topdir.c_str());
149 pos++;
151 if(dir[dir.size()-1] == '/')
153 topdir = dir.substr(0, dir.size());
155 else
157 topdir = dir;
159 if(Mkdir(topdir.c_str()) != 0)
161 // There is a bug in the Borland Run time library which makes MKDIR
162 // return EACCES when it should return EEXISTS
163 // if it is some other error besides directory exists
164 // then return false
165 if( (errno != EEXIST)
166 #ifdef __BORLANDC__
167 && (errno != EACCES)
168 #endif
171 cmSystemTools::Error("Faild to create directory:", path);
172 return false;
175 return true;
179 // replace replace with with as many times as it shows up in source.
180 // write the result into source.
181 void cmSystemTools::ReplaceString(std::string& source,
182 const char* replace,
183 const char* with)
185 std::string::size_type lengthReplace = strlen(replace);
186 std::string::size_type lengthWith = strlen(with);
187 std::string rest;
188 std::string::size_type start = source.find(replace);
189 while(start != std::string::npos)
191 rest = source.substr(start+lengthReplace);
192 source = source.substr(0, start);
193 source += with;
194 source += rest;
195 start = source.find(replace, start + lengthWith );
199 // Read a registry value.
200 // Example :
201 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
202 // => will return the data of the "default" value of the key
203 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
204 // => will return the data of the "Root" value of the key
206 #if defined(_WIN32) && !defined(__CYGWIN__)
207 bool cmSystemTools::ReadRegistryValue(const char *key, std::string &value)
210 std::string primary = key;
211 std::string second;
212 std::string valuename;
214 size_t start = primary.find("\\");
215 if (start == std::string::npos)
217 return false;
220 size_t valuenamepos = primary.find(";");
221 if (valuenamepos != std::string::npos)
223 valuename = primary.substr(valuenamepos+1);
226 second = primary.substr(start+1, valuenamepos-start-1);
227 primary = primary.substr(0, start);
229 HKEY primaryKey;
230 if (primary == "HKEY_CURRENT_USER")
232 primaryKey = HKEY_CURRENT_USER;
234 if (primary == "HKEY_CURRENT_CONFIG")
236 primaryKey = HKEY_CURRENT_CONFIG;
238 if (primary == "HKEY_CLASSES_ROOT")
240 primaryKey = HKEY_CLASSES_ROOT;
242 if (primary == "HKEY_LOCAL_MACHINE")
244 primaryKey = HKEY_LOCAL_MACHINE;
246 if (primary == "HKEY_USERS")
248 primaryKey = HKEY_USERS;
251 HKEY hKey;
252 if(RegOpenKeyEx(primaryKey,
253 second.c_str(),
255 KEY_READ,
256 &hKey) != ERROR_SUCCESS)
258 return false;
260 else
262 DWORD dwType, dwSize;
263 dwSize = 1023;
264 char data[1024];
265 if(RegQueryValueEx(hKey,
266 (LPTSTR)valuename.c_str(),
267 NULL,
268 &dwType,
269 (BYTE *)data,
270 &dwSize) == ERROR_SUCCESS)
272 if (dwType == REG_SZ)
274 value = data;
275 return true;
279 return false;
281 #else
282 bool cmSystemTools::ReadRegistryValue(const char *, std::string &)
284 return false;
286 #endif
289 // Write a registry value.
290 // Example :
291 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
292 // => will set the data of the "default" value of the key
293 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
294 // => will set the data of the "Root" value of the key
296 #if defined(_WIN32) && !defined(__CYGWIN__)
297 bool cmSystemTools::WriteRegistryValue(const char *key, const char *value)
299 std::string primary = key;
300 std::string second;
301 std::string valuename;
303 size_t start = primary.find("\\");
304 if (start == std::string::npos)
306 return false;
309 size_t valuenamepos = primary.find(";");
310 if (valuenamepos != std::string::npos)
312 valuename = primary.substr(valuenamepos+1);
315 second = primary.substr(start+1, valuenamepos-start-1);
316 primary = primary.substr(0, start);
318 HKEY primaryKey;
319 if (primary == "HKEY_CURRENT_USER")
321 primaryKey = HKEY_CURRENT_USER;
323 if (primary == "HKEY_CURRENT_CONFIG")
325 primaryKey = HKEY_CURRENT_CONFIG;
327 if (primary == "HKEY_CLASSES_ROOT")
329 primaryKey = HKEY_CLASSES_ROOT;
331 if (primary == "HKEY_LOCAL_MACHINE")
333 primaryKey = HKEY_LOCAL_MACHINE;
335 if (primary == "HKEY_USERS")
337 primaryKey = HKEY_USERS;
340 HKEY hKey;
341 DWORD dwDummy;
342 if(RegCreateKeyEx(primaryKey,
343 second.c_str(),
346 REG_OPTION_NON_VOLATILE,
347 KEY_WRITE,
348 NULL,
349 &hKey,
350 &dwDummy) != ERROR_SUCCESS)
352 return false;
355 if(RegSetValueEx(hKey,
356 (LPTSTR)valuename.c_str(),
358 REG_SZ,
359 (CONST BYTE *)value,
360 (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
362 return true;
364 return false;
366 #else
367 bool cmSystemTools::WriteRegistryValue(const char *, const char *)
369 return false;
371 #endif
373 // Delete a registry value.
374 // Example :
375 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
376 // => will delete the data of the "default" value of the key
377 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
378 // => will delete the data of the "Root" value of the key
380 #if defined(_WIN32) && !defined(__CYGWIN__)
381 bool cmSystemTools::DeleteRegistryValue(const char *key)
383 std::string primary = key;
384 std::string second;
385 std::string valuename;
387 size_t start = primary.find("\\");
388 if (start == std::string::npos)
390 return false;
393 size_t valuenamepos = primary.find(";");
394 if (valuenamepos != std::string::npos)
396 valuename = primary.substr(valuenamepos+1);
399 second = primary.substr(start+1, valuenamepos-start-1);
400 primary = primary.substr(0, start);
402 HKEY primaryKey;
403 if (primary == "HKEY_CURRENT_USER")
405 primaryKey = HKEY_CURRENT_USER;
407 if (primary == "HKEY_CURRENT_CONFIG")
409 primaryKey = HKEY_CURRENT_CONFIG;
411 if (primary == "HKEY_CLASSES_ROOT")
413 primaryKey = HKEY_CLASSES_ROOT;
415 if (primary == "HKEY_LOCAL_MACHINE")
417 primaryKey = HKEY_LOCAL_MACHINE;
419 if (primary == "HKEY_USERS")
421 primaryKey = HKEY_USERS;
424 HKEY hKey;
425 if(RegOpenKeyEx(primaryKey,
426 second.c_str(),
428 KEY_WRITE,
429 &hKey) != ERROR_SUCCESS)
431 return false;
433 else
435 if(RegDeleteValue(hKey,
436 (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
438 return true;
441 return false;
443 #else
444 bool cmSystemTools::DeleteRegistryValue(const char *)
446 return false;
448 #endif
450 // replace replace with with as many times as it shows up in source.
451 // write the result into source.
452 #if defined(_WIN32) && !defined(__CYGWIN__)
453 void cmSystemTools::ExpandRegistryValues(std::string& source)
455 // Regular expression to match anything inside [...] that begins in HKEY.
456 // Note that there is a special rule for regular expressions to match a
457 // close square-bracket inside a list delimited by square brackets.
458 // The "[^]]" part of this expression will match any character except
459 // a close square-bracket. The ']' character must be the first in the
460 // list of characters inside the [^...] block of the expression.
461 cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]");
463 // check for black line or comment
464 while (regEntry.find(source))
466 // the arguments are the second match
467 std::string key = regEntry.match(1);
468 std::string val;
469 if (ReadRegistryValue(key.c_str(), val))
471 std::string reg = "[";
472 reg += key + "]";
473 cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
475 else
477 std::string reg = "[";
478 reg += key + "]";
479 cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
483 #else
484 void cmSystemTools::ExpandRegistryValues(std::string&)
487 #endif
490 std::string cmSystemTools::EscapeQuotes(const char* str)
492 std::string result = "";
493 for(const char* ch = str; *ch != '\0'; ++ch)
495 if(*ch == '"')
497 result += '\\';
499 result += *ch;
501 return result;
504 bool cmSystemTools::SameFile(const char* file1, const char* file2)
506 #ifdef _WIN32
507 HANDLE hFile1, hFile2;
509 hFile1 = CreateFile( file1,
510 GENERIC_READ,
511 FILE_SHARE_READ ,
512 NULL,
513 OPEN_EXISTING,
514 FILE_FLAG_BACKUP_SEMANTICS,
515 NULL
517 hFile2 = CreateFile( file2,
518 GENERIC_READ,
519 FILE_SHARE_READ,
520 NULL,
521 OPEN_EXISTING,
522 FILE_FLAG_BACKUP_SEMANTICS,
523 NULL
525 if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
527 if(hFile1 != INVALID_HANDLE_VALUE)
529 CloseHandle(hFile1);
531 if(hFile2 != INVALID_HANDLE_VALUE)
533 CloseHandle(hFile2);
535 return false;
538 BY_HANDLE_FILE_INFORMATION fiBuf1;
539 BY_HANDLE_FILE_INFORMATION fiBuf2;
540 GetFileInformationByHandle( hFile1, &fiBuf1 );
541 GetFileInformationByHandle( hFile2, &fiBuf2 );
542 CloseHandle(hFile1);
543 CloseHandle(hFile2);
544 return (fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
545 fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
546 #else
547 struct stat fileStat1, fileStat2;
548 if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
550 // see if the files are the same file
551 // check the device inode and size
552 if(fileStat2.st_dev == fileStat1.st_dev &&
553 fileStat2.st_ino == fileStat1.st_ino &&
554 fileStat2.st_size == fileStat1.st_size
557 return true;
560 return false;
561 #endif
565 // return true if the file exists
566 bool cmSystemTools::FileExists(const char* filename)
568 struct stat fs;
569 if (stat(filename, &fs) != 0)
571 return false;
573 else
575 return true;
580 // Return a capitalized string (i.e the first letter is uppercased, all other
581 // are lowercased)
582 std::string cmSystemTools::Capitalized(const std::string& s)
584 std::string n;
585 n.resize(s.size());
586 n[0] = toupper(s[0]);
587 for (size_t i = 1; i < s.size(); i++)
589 n[i] = tolower(s[i]);
591 return n;
595 // Return a lower case string
596 std::string cmSystemTools::LowerCase(const std::string& s)
598 std::string n;
599 n.resize(s.size());
600 for (size_t i = 0; i < s.size(); i++)
602 n[i] = tolower(s[i]);
604 return n;
607 // Return a lower case string
608 std::string cmSystemTools::UpperCase(const std::string& s)
610 std::string n;
611 n.resize(s.size());
612 for (size_t i = 0; i < s.size(); i++)
614 n[i] = toupper(s[i]);
616 return n;
620 // convert windows slashes to unix slashes
621 void cmSystemTools::ConvertToUnixSlashes(std::string& path)
623 std::string::size_type pos = 0;
624 while((pos = path.find('\\', pos)) != std::string::npos)
626 path[pos] = '/';
627 pos++;
629 // remove any trailing slash
630 if(path.size() && path[path.size()-1] == '/')
632 path = path.substr(0, path.size()-1);
635 // if there is a tilda ~ then replace it with HOME
636 if(path.find("~") == 0)
638 if (getenv("HOME"))
640 path = std::string(getenv("HOME")) + path.substr(1);
644 // if there is a /tmp_mnt in a path get rid of it!
645 // stupid sgi's
646 if(path.find("/tmp_mnt") == 0)
648 path = path.substr(8);
653 // change // to /, and escape any spaces in the path
654 std::string cmSystemTools::ConvertToUnixOutputPath(const char* path)
656 std::string ret = path;
658 // remove // except at the beginning might be a cygwin drive
659 std::string::size_type pos = 1;
660 while((pos = ret.find("//", pos)) != std::string::npos)
662 ret.erase(pos, 1);
664 // now escape spaces if there is a space in the path
665 if(ret.find(" ") != std::string::npos)
667 std::string result = "";
668 char lastch = 1;
669 for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
671 // if it is already escaped then don't try to escape it again
672 if(*ch == ' ' && lastch != '\\')
674 result += '\\';
676 result += *ch;
677 lastch = *ch;
679 ret = result;
681 return ret;
686 std::string cmSystemTools::EscapeSpaces(const char* str)
688 #if defined(_WIN32) && !defined(__CYGWIN__)
689 std::string result;
691 // if there are spaces
692 std::string temp = str;
693 if (temp.find(" ") != std::string::npos &&
694 temp.find("\"")==std::string::npos)
696 result = "\"";
697 result += str;
698 result += "\"";
699 return result;
701 return str;
702 #else
703 std::string result = "";
704 for(const char* ch = str; *ch != '\0'; ++ch)
706 if(*ch == ' ')
708 result += '\\';
710 result += *ch;
712 return result;
713 #endif
716 std::string cmSystemTools::ConvertToOutputPath(const char* path)
718 #if defined(_WIN32) && !defined(__CYGWIN__)
719 return cmSystemTools::ConvertToWindowsOutputPath(path);
720 #else
721 return cmSystemTools::ConvertToUnixOutputPath(path);
722 #endif
726 // remove double slashes not at the start
727 std::string cmSystemTools::ConvertToWindowsOutputPath(const char* path)
729 std::string ret = path;
730 std::string::size_type pos = 0;
731 // first convert all of the slashes
732 while((pos = ret.find('/', pos)) != std::string::npos)
734 ret[pos] = '\\';
735 pos++;
737 // check for really small paths
738 if(ret.size() < 2)
740 return ret;
742 // now clean up a bit and remove double slashes
743 // Only if it is not the first position in the path which is a network
744 // path on windows
745 pos = 1; // start at position 1
746 while((pos = ret.find("\\\\", pos)) != std::string::npos)
748 ret.erase(pos, 1);
750 // now double quote the path if it has spaces in it
751 // and is not already double quoted
752 if(ret.find(" ") != std::string::npos
753 && ret[0] != '\"')
755 std::string result;
756 result = "\"" + ret + "\"";
757 ret = result;
759 return ret;
762 inline void RemoveComments(char* ptr)
764 while(*ptr)
766 if(*ptr == '#')
768 *ptr = 0;
769 break;
771 ++ptr;
775 bool cmSystemTools::ParseFunction(std::ifstream& fin,
776 std::string& name,
777 std::vector<std::string>& arguments,
778 const char* filename,
779 bool& parseError)
781 parseError = false;
782 name = "";
783 arguments = std::vector<std::string>();
784 const int BUFFER_SIZE = 4096;
785 char inbuffer[BUFFER_SIZE];
786 if(!fin)
788 return false;
790 if(fin.getline(inbuffer, BUFFER_SIZE ) )
792 RemoveComments(inbuffer);
793 cmRegularExpression blankLine("^[ \t\r]*$");
794 // cmRegularExpression comment("^[ \t]*#.*$");
795 cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
796 cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
797 cmRegularExpression lastLine("^(.*)\\)[ \t\r]*$");
799 // check for blank line or comment
800 if(blankLine.find(inbuffer) )
802 return false;
804 // look for a oneline fun(arg arg2)
805 else if(oneLiner.find(inbuffer))
807 // the arguments are the second match
808 std::string args = oneLiner.match(2);
809 name = oneLiner.match(1);
810 // break up the arguments
811 cmSystemTools::GetArguments(args, arguments);
812 return true;
814 // look for a start of a multiline with no trailing ")" fun(arg arg2
815 else if(multiLine.find(inbuffer))
817 name = multiLine.match(1);
818 std::string args = multiLine.match(2);
819 cmSystemTools::GetArguments(args, arguments);
820 // Read lines until the closing paren is hit
821 bool done = false;
822 while(!done)
824 // read lines until the end paren is found
825 if(fin.getline(inbuffer, BUFFER_SIZE ) )
827 RemoveComments(inbuffer);
828 // Check for comment lines and ignore them.
829 if(blankLine.find(inbuffer))
830 { continue; }
831 // Is this the last line?
832 if(lastLine.find(inbuffer))
834 done = true;
835 std::string args = lastLine.match(1);
836 cmSystemTools::GetArguments(args, arguments);
838 else
840 std::string line = inbuffer;
841 cmSystemTools::GetArguments(line, arguments);
844 else
846 parseError = true;
847 cmSystemTools::Error("Parse error in read function missing end )\nIn File: ",
848 filename, "\nCurrent line:", inbuffer);
849 return false;
852 return true;
854 else
856 parseError = true;
857 cmSystemTools::Error("Parse error in read function\nIn file:",
858 filename, "\nCurrent line:", inbuffer);
859 return false;
862 return false;
866 void cmSystemTools::GetArguments(std::string& line,
867 std::vector<std::string>& arguments)
869 // Match a normal argument (not quoted, no spaces).
870 cmRegularExpression normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*");
871 // Match a quoted argument (surrounded by double quotes, spaces allowed).
872 cmRegularExpression quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*");
874 bool done = false;
875 while(!done)
877 std::string arg;
878 std::string::size_type endpos=0;
879 bool foundQuoted = quotedArgument.find(line.c_str());
880 bool foundNormal = normalArgument.find(line.c_str());
882 if(foundQuoted && foundNormal)
884 // Both matches were found. Take the earlier one.
885 // Favor double-quoted version if there is a tie.
886 if(normalArgument.start(1) < quotedArgument.start(1))
888 arg = normalArgument.match(1);
889 endpos = normalArgument.end(1);
891 else
893 arg = quotedArgument.match(1);
894 endpos = quotedArgument.end(1);
895 // Strip off the double quotes on the ends.
896 arg = arg.substr(1, arg.length()-2);
899 else if (foundQuoted)
901 arg = quotedArgument.match(1);
902 endpos = quotedArgument.end(1);
903 // Strip off the double quotes on the ends.
904 arg = arg.substr(1, arg.length()-2);
906 else if(foundNormal)
908 arg = normalArgument.match(1);
909 endpos = normalArgument.end(1);
911 else
913 done = true;
915 if(!done)
917 arguments.push_back(cmSystemTools::RemoveEscapes(arg.c_str()));
918 line = line.substr(endpos, line.length() - endpos);
924 std::string cmSystemTools::RemoveEscapes(const char* s)
926 std::string result = "";
927 for(const char* ch = s; *ch; ++ch)
929 if(*ch == '\\' && *(ch+1) != ';')
931 ++ch;
932 switch (*ch)
934 case '\\': result.insert(result.end(), '\\'); break;
935 case '"': result.insert(result.end(), '"'); break;
936 case ' ': result.insert(result.end(), ' '); break;
937 case 't': result.insert(result.end(), '\t'); break;
938 case 'n': result.insert(result.end(), '\n'); break;
939 case 'r': result.insert(result.end(), '\r'); break;
940 case '0': result.insert(result.end(), '\0'); break;
941 case '\0':
943 cmSystemTools::Error("Trailing backslash in argument:\n", s);
944 return result;
946 default:
948 std::string chStr(1, *ch);
949 cmSystemTools::Error("Invalid escape sequence \\", chStr.c_str(),
950 "\nin argument ", s);
954 else
956 result.insert(result.end(), *ch);
959 return result;
962 void cmSystemTools::Error(const char* m1, const char* m2,
963 const char* m3, const char* m4)
965 std::string message = "CMake Error: ";
966 if(m1)
968 message += m1;
970 if(m2)
972 message += m2;
974 if(m3)
976 message += m3;
978 if(m4)
980 message += m4;
982 cmSystemTools::s_ErrorOccured = true;
983 cmSystemTools::Message(message.c_str(),"Error");
987 void cmSystemTools::SetErrorCallback(ErrorCallback f)
989 s_ErrorCallback = f;
992 void cmSystemTools::Message(const char* m1, const char *title)
994 if(s_DisableMessages)
996 return;
998 if(s_ErrorCallback)
1000 (*s_ErrorCallback)(m1, title, s_DisableMessages);
1001 return;
1003 else
1005 std::cerr << m1 << std::endl;
1011 bool cmSystemTools::CopyFileIfDifferent(const char* source,
1012 const char* destination)
1014 if(cmSystemTools::FilesDiffer(source, destination))
1016 cmSystemTools::cmCopyFile(source, destination);
1017 return true;
1019 return false;
1023 bool cmSystemTools::FilesDiffer(const char* source,
1024 const char* destination)
1026 struct stat statSource;
1027 if (stat(source, &statSource) != 0)
1029 return true;
1032 struct stat statDestination;
1033 if (stat(destination, &statDestination) != 0)
1035 return true;
1038 if(statSource.st_size != statDestination.st_size)
1040 return true;
1043 if(statSource.st_size == 0)
1045 return false;
1048 #if defined(_WIN32) || defined(__CYGWIN__)
1049 std::ifstream finSource(source,
1050 std::ios::binary | std::ios::in);
1051 std::ifstream finDestination(destination,
1052 std::ios::binary | std::ios::in);
1053 #else
1054 std::ifstream finSource(source);
1055 std::ifstream finDestination(destination);
1056 #endif
1057 if(!finSource || !finDestination)
1059 return true;
1062 char* source_buf = new char[statSource.st_size];
1063 char* dest_buf = new char[statSource.st_size];
1065 finSource.read(source_buf, statSource.st_size);
1066 finDestination.read(dest_buf, statSource.st_size);
1068 if(statSource.st_size != static_cast<long>(finSource.gcount()) ||
1069 statSource.st_size != static_cast<long>(finDestination.gcount()))
1071 cmStringStream msg;
1072 msg << "FilesDiffer failed to read files (allocated: "
1073 << statSource.st_size << ", read source: " << finSource.gcount()
1074 << ", read dest: " << finDestination.gcount();
1075 cmSystemTools::Error(msg.str().c_str());
1076 delete [] source_buf;
1077 delete [] dest_buf;
1078 return false;
1080 int ret = memcmp((const void*)source_buf,
1081 (const void*)dest_buf,
1082 statSource.st_size);
1084 delete [] dest_buf;
1085 delete [] source_buf;
1087 return ret != 0;
1092 * Copy a file named by "source" to the file named by "destination".
1094 void cmSystemTools::cmCopyFile(const char* source,
1095 const char* destination)
1097 const int bufferSize = 4096;
1098 char buffer[bufferSize];
1100 // If destination is a directory, try to create a file with the same
1101 // name as the source in that directory.
1103 std::string new_destination;
1104 if(cmSystemTools::FileExists(destination) &&
1105 cmSystemTools::FileIsDirectory(destination))
1107 new_destination = destination;
1108 cmSystemTools::ConvertToUnixSlashes(new_destination);
1109 new_destination += '/';
1110 std::string source_name = source;
1111 new_destination += cmSystemTools::GetFilenameName(source_name);
1112 destination = new_destination.c_str();
1115 // Create destination directory
1117 std::string destination_dir = destination;
1118 destination_dir = cmSystemTools::GetFilenamePath(destination_dir);
1119 cmSystemTools::MakeDirectory(destination_dir.c_str());
1121 // Open files
1123 #if defined(_WIN32) || defined(__CYGWIN__)
1124 std::ifstream fin(source,
1125 std::ios::binary | std::ios::in);
1126 #else
1127 std::ifstream fin(source);
1128 #endif
1129 if(!fin)
1131 cmSystemTools::Error("CopyFile failed to open input file \"",
1132 source, "\"");
1133 return;
1136 #if defined(_WIN32) || defined(__CYGWIN__)
1137 std::ofstream fout(destination,
1138 std::ios::binary | std::ios::out | std::ios::trunc);
1139 #else
1140 std::ofstream fout(destination,
1141 std::ios::out | std::ios::trunc);
1142 #endif
1143 if(!fout)
1145 cmSystemTools::Error("CopyFile failed to open output file \"",
1146 destination, "\"");
1147 return;
1150 // This copy loop is very sensitive on certain platforms with
1151 // slightly broken stream libraries (like HPUX). Normally, it is
1152 // incorrect to not check the error condition on the fin.read()
1153 // before using the data, but the fin.gcount() will be zero if an
1154 // error occurred. Therefore, the loop should be safe everywhere.
1155 while(fin)
1157 fin.read(buffer, bufferSize);
1158 if(fin.gcount())
1160 fout.write(buffer, fin.gcount());
1164 fin.close();
1165 fout.close();
1167 // More checks
1169 struct stat statSource, statDestination;
1170 if (stat(source, &statSource) != 0 ||
1171 stat(destination, &statDestination) != 0)
1173 cmSystemTools::Error("CopyFile failed to copy files!");
1176 if (statSource.st_size != statDestination.st_size)
1178 cmStringStream msg;
1179 msg << "CopyFile failed to copy files (sizes differ, source: "
1180 << statSource.st_size << " , dest: " << statDestination.st_size;
1181 cmSystemTools::Error(msg.str().c_str());
1185 // return true if the file exists
1186 long int cmSystemTools::ModifiedTime(const char* filename)
1188 struct stat fs;
1189 if (stat(filename, &fs) != 0)
1191 return 0;
1193 else
1195 return (long int)fs.st_mtime;
1201 bool cmSystemTools::RemoveFile(const char* source)
1203 return unlink(source) != 0 ? false : true;
1206 bool cmSystemTools::IsOn(const char* val)
1208 if (!val)
1210 return false;
1212 std::basic_string<char> v = val;
1214 for(std::basic_string<char>::iterator c = v.begin();
1215 c != v.end(); c++)
1217 *c = toupper(*c);
1219 return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
1222 bool cmSystemTools::IsOff(const char* val)
1224 if (!val || strlen(val) == 0)
1226 return true;
1228 std::basic_string<char> v = val;
1230 for(std::basic_string<char>::iterator c = v.begin();
1231 c != v.end(); c++)
1233 *c = toupper(*c);
1235 return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
1236 v == "N" || v == "NOTFOUND" || v == "IGNORE");
1240 bool cmSystemTools::RunCommand(const char* command,
1241 std::string& output,
1242 const char* dir,
1243 bool verbose)
1245 int foo;
1246 return cmSystemTools::RunCommand(command, output, foo, dir, verbose);
1249 #if defined(WIN32) && !defined(__CYGWIN__)
1250 // use this for shell commands like echo and dir
1251 bool RunCommandViaSystem(const char* command,
1252 const char* dir,
1253 std::string& output,
1254 int& retVal,
1255 bool verbose)
1257 const int BUFFER_SIZE = 4096;
1258 char buffer[BUFFER_SIZE];
1259 std::string commandInDir;
1260 if(dir)
1262 commandInDir = "cd ";
1263 commandInDir += cmSystemTools::ConvertToOutputPath(dir);
1264 commandInDir += " && ";
1265 commandInDir += command;
1267 else
1269 commandInDir = command;
1271 command = commandInDir.c_str();
1272 std::string commandToFile = command;
1273 commandToFile += " > ";
1274 std::string tempFile;
1275 tempFile += _tempnam(0, "cmake");
1277 commandToFile += tempFile;
1278 retVal = system(commandToFile.c_str());
1279 std::ifstream fin(tempFile.c_str());
1280 if(!fin)
1282 if(verbose)
1284 std::string errormsg = "RunCommand produced no output: command: \"";
1285 errormsg += command;
1286 errormsg += "\"";
1287 errormsg += "\nOutput file: ";
1288 errormsg += tempFile;
1289 cmSystemTools::Error(errormsg.c_str());
1291 fin.close();
1292 cmSystemTools::RemoveFile(tempFile.c_str());
1293 return false;
1295 bool multiLine = false;
1296 while(fin)
1298 fin.getline(buffer, BUFFER_SIZE);
1299 output += buffer;
1300 if(multiLine)
1302 output += "\n";
1304 multiLine = true;
1306 fin.close();
1307 cmSystemTools::RemoveFile(tempFile.c_str());
1308 return true;
1312 #endif // endif WIN32 not CYGWIN
1315 // run a command unix uses popen (easy)
1316 // windows uses system and ShortPath
1317 bool cmSystemTools::RunCommand(const char* command,
1318 std::string& output,
1319 int &retVal,
1320 const char* dir,
1321 bool verbose)
1323 if(s_DisableRunCommandOutput)
1325 verbose = false;
1328 #if defined(WIN32) && !defined(__CYGWIN__)
1329 // if the command does not start with a quote, then
1330 // try to find the program, and if the program can not be
1331 // found use system to run the command as it must be a built in
1332 // shell command like echo or dir
1333 int count = 0;
1334 if(command[0] == '\"')
1336 // count the number of quotes
1337 for(const char* s = command; *s != 0; ++s)
1339 if(*s == '\"')
1341 count++;
1342 if(count > 2)
1344 break;
1348 // if there are more than two double quotes use
1349 // GetShortPathName, the cmd.exe program in windows which
1350 // is used by system fails to execute if there are more than
1351 // one set of quotes in the arguments
1352 if(count > 2)
1354 cmRegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
1355 if(quoted.find(command))
1357 std::string shortCmd;
1358 std::string cmd = quoted.match(1);
1359 std::string args = quoted.match(2);
1360 if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
1362 cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
1363 return false;
1365 shortCmd += " ";
1366 shortCmd += args;
1367 return RunCommandViaSystem(shortCmd.c_str(), dir,
1368 output, retVal, verbose);
1370 else
1372 cmSystemTools::Error("Could not parse command line with quotes ",
1373 command);
1377 // if there is only one set of quotes or no quotes then just run the command
1378 return RunCommandViaSystem(command, dir, output, retVal, verbose);
1379 #else
1380 // if only popen worked on windows.....
1381 std::string commandInDir;
1382 if(dir)
1384 commandInDir = "cd ";
1385 commandInDir += dir;
1386 commandInDir += " && ";
1387 commandInDir += command;
1389 else
1391 commandInDir = command;
1393 command = commandInDir.c_str();
1394 const int BUFFER_SIZE = 4096;
1395 char buffer[BUFFER_SIZE];
1396 if(verbose)
1398 std::cout << "running " << command << std::endl;
1400 fflush(stdout);
1401 fflush(stderr);
1402 FILE* cpipe = popen(command, "r");
1403 if(!cpipe)
1405 return false;
1407 fgets(buffer, BUFFER_SIZE, cpipe);
1408 while(!feof(cpipe))
1410 if(verbose)
1412 std::cout << buffer << std::flush;
1414 output += buffer;
1415 fgets(buffer, BUFFER_SIZE, cpipe);
1418 retVal = pclose(cpipe);
1419 if (WIFEXITED(retVal))
1421 retVal = WEXITSTATUS(retVal);
1422 return true;
1424 if (WIFSIGNALED(retVal))
1426 retVal = WTERMSIG(retVal);
1427 cmStringStream error;
1428 error << "\nProcess terminated due to ";
1429 switch (retVal)
1431 #ifdef SIGKILL
1432 case SIGKILL:
1433 error << "SIGKILL";
1434 break;
1435 #endif
1436 #ifdef SIGFPE
1437 case SIGFPE:
1438 error << "SIGFPE";
1439 break;
1440 #endif
1441 #ifdef SIGBUS
1442 case SIGBUS:
1443 error << "SIGBUS";
1444 break;
1445 #endif
1446 #ifdef SIGSEGV
1447 case SIGSEGV:
1448 error << "SIGSEGV";
1449 break;
1450 #endif
1451 default:
1452 error << "signal " << retVal;
1453 break;
1455 output += error.str();
1457 return false;
1458 #endif
1462 * Find the file the given name. Searches the given path and then
1463 * the system search path. Returns the full path to the file if it is
1464 * found. Otherwise, the empty string is returned.
1466 std::string cmSystemTools::FindFile(const char* name,
1467 const std::vector<std::string>& userPaths)
1469 // Add the system search path to our path.
1470 std::vector<std::string> path = userPaths;
1471 cmSystemTools::GetPath(path);
1473 std::string tryPath;
1474 for(std::vector<std::string>::const_iterator p = path.begin();
1475 p != path.end(); ++p)
1477 tryPath = *p;
1478 tryPath += "/";
1479 tryPath += name;
1480 if(cmSystemTools::FileExists(tryPath.c_str()) &&
1481 !cmSystemTools::FileIsDirectory(tryPath.c_str()))
1483 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1486 // Couldn't find the file.
1487 return "";
1491 * Find the executable with the given name. Searches the given path and then
1492 * the system search path. Returns the full path to the executable if it is
1493 * found. Otherwise, the empty string is returned.
1495 std::string cmSystemTools::FindProgram(const char* name,
1496 const std::vector<std::string>& userPaths,
1497 bool no_system_path)
1499 // See if the executable exists as written.
1500 if(cmSystemTools::FileExists(name) &&
1501 !cmSystemTools::FileIsDirectory(name))
1503 return cmSystemTools::CollapseFullPath(name);
1505 std::string tryPath = name;
1506 tryPath += cmSystemTools::GetExecutableExtension();
1507 if(cmSystemTools::FileExists(tryPath.c_str()) &&
1508 !cmSystemTools::FileIsDirectory(tryPath.c_str()))
1510 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1513 // Add the system search path to our path.
1514 std::vector<std::string> path = userPaths;
1515 if (!no_system_path)
1517 cmSystemTools::GetPath(path);
1520 for(std::vector<std::string>::const_iterator p = path.begin();
1521 p != path.end(); ++p)
1523 tryPath = *p;
1524 tryPath += "/";
1525 tryPath += name;
1526 if(cmSystemTools::FileExists(tryPath.c_str()) &&
1527 !cmSystemTools::FileIsDirectory(tryPath.c_str()))
1529 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1531 #ifdef _WIN32
1532 tryPath += ".com";
1533 if(cmSystemTools::FileExists(tryPath.c_str()) &&
1534 !cmSystemTools::FileIsDirectory(tryPath.c_str()))
1536 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1538 tryPath = *p;
1539 tryPath += "/";
1540 tryPath += name;
1541 #endif
1542 tryPath += cmSystemTools::GetExecutableExtension();
1543 if(cmSystemTools::FileExists(tryPath.c_str()) &&
1544 !cmSystemTools::FileIsDirectory(tryPath.c_str()))
1546 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1550 // Couldn't find the program.
1551 return "";
1556 * Find the library with the given name. Searches the given path and then
1557 * the system search path. Returns the full path to the library if it is
1558 * found. Otherwise, the empty string is returned.
1560 std::string cmSystemTools::FindLibrary(const char* name,
1561 const std::vector<std::string>& userPaths,
1562 const cmMakefile *makefile)
1564 // See if the executable exists as written.
1565 if(cmSystemTools::FileExists(name))
1567 return cmSystemTools::CollapseFullPath(name);
1570 // Add the system search path to our path.
1571 std::vector<std::string> path = userPaths;
1572 cmSystemTools::GetPath(path);
1574 // Add some lib directories specific to compilers, depending on the
1575 // current generator, so that library that might have been stored here
1576 // can be found too.
1577 // i.e. Microsoft Visual Studio or .Net: path to compiler/../Lib
1578 // Borland: path to compiler/../Lib
1579 if (makefile)
1581 const char* genName = makefile->GetDefinition("CMAKE_GENERATOR");
1582 if (genName)
1584 if (!strcmp(genName, "NMake Makefiles") ||
1585 !strcmp(genName, "Visual Studio 6"))
1587 const char* compiler = makefile->GetDefinition("CMAKE_CXX_COMPILER");
1588 if (compiler)
1590 std::string compiler_path = cmSystemTools::FindProgram(compiler);
1591 if (compiler_path.size())
1593 std::string lib_path =
1594 cmSystemTools::GetFilenamePath(
1595 cmSystemTools::GetFilenamePath(compiler_path)) + "/Lib";
1596 path.push_back(lib_path);
1600 else if (!strcmp(genName, "Visual Studio 7"))
1602 // It is likely that the compiler won't be in the path for .Net, but
1603 // we know where devenv is.
1604 const char* devenv = makefile->GetDefinition("MICROSOFT_DEVENV");
1605 if (devenv)
1607 std::string devenv_path = cmSystemTools::FindProgram(devenv);
1608 if (devenv_path.size())
1610 std::string vc7_path =
1611 cmSystemTools::GetFilenamePath(
1612 cmSystemTools::GetFilenamePath(
1613 cmSystemTools::GetFilenamePath(devenv_path))) + "/Vc7";
1614 path.push_back(vc7_path + "/lib");
1615 path.push_back(vc7_path + "/PlatformSDK/lib");
1619 else if (!strcmp(genName, "Borland Makefiles"))
1621 const char* bcb_bin_path = makefile->GetDefinition("BCB_BIN_PATH");
1622 if (bcb_bin_path)
1624 std::string lib_path =
1625 cmSystemTools::GetFilenamePath(bcb_bin_path) + "/Lib";
1626 path.push_back(lib_path);
1632 std::string tryPath;
1633 for(std::vector<std::string>::const_iterator p = path.begin();
1634 p != path.end(); ++p)
1636 #if defined(_WIN32) && !defined(__CYGWIN__)
1637 tryPath = *p;
1638 tryPath += "/";
1639 tryPath += name;
1640 tryPath += ".lib";
1641 if(cmSystemTools::FileExists(tryPath.c_str()))
1643 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1645 #else
1646 tryPath = *p;
1647 tryPath += "/lib";
1648 tryPath += name;
1649 tryPath += ".so";
1650 if(cmSystemTools::FileExists(tryPath.c_str()))
1652 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1654 tryPath = *p;
1655 tryPath += "/lib";
1656 tryPath += name;
1657 tryPath += ".a";
1658 if(cmSystemTools::FileExists(tryPath.c_str()))
1660 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1662 tryPath = *p;
1663 tryPath += "/lib";
1664 tryPath += name;
1665 tryPath += ".sl";
1666 if(cmSystemTools::FileExists(tryPath.c_str()))
1668 return cmSystemTools::CollapseFullPath(tryPath.c_str());
1670 #endif
1673 // Couldn't find the library.
1674 return "";
1677 bool cmSystemTools::FileIsDirectory(const char* name)
1679 struct stat fs;
1680 if(stat(name, &fs) == 0)
1682 #if _WIN32
1683 return ((fs.st_mode & _S_IFDIR) != 0);
1684 #else
1685 return S_ISDIR(fs.st_mode);
1686 #endif
1688 else
1690 return false;
1694 int cmSystemTools::ChangeDirectory(const char *dir)
1696 return Chdir(dir);
1699 std::string cmSystemTools::GetCurrentWorkingDirectory()
1701 char buf[2048];
1702 std::string path = Getcwd(buf, 2048);
1703 return path;
1707 * Given the path to a program executable, get the directory part of the path with the
1708 * file stripped off. If there is no directory part, the empty string is returned.
1710 std::string cmSystemTools::GetProgramPath(const char* in_name)
1712 std::string dir, file;
1713 cmSystemTools::SplitProgramPath(in_name, dir, file);
1714 return dir;
1718 * Given the path to a program executable, get the directory part of the path
1719 * with the file stripped off. If there is no directory part, the empty
1720 * string is returned.
1722 void cmSystemTools::SplitProgramPath(const char* in_name,
1723 std::string& dir,
1724 std::string& file)
1726 dir = in_name;
1727 file = "";
1728 cmSystemTools::ConvertToUnixSlashes(dir);
1730 if(!cmSystemTools::FileIsDirectory(dir.c_str()))
1732 std::string::size_type slashPos = dir.rfind("/");
1733 if(slashPos != std::string::npos)
1735 file = dir.substr(slashPos+1);
1736 dir = dir.substr(0, slashPos);
1738 else
1740 file = dir;
1741 dir = "";
1745 if((dir != "") && !cmSystemTools::FileIsDirectory(dir.c_str()))
1747 std::string oldDir = in_name;
1748 cmSystemTools::ConvertToUnixSlashes(oldDir);
1749 cmSystemTools::Error("Error splitting file name off end of path:\n",
1750 oldDir.c_str(), "\nDirectory not found: ",
1751 dir.c_str());
1752 dir = in_name;
1753 return;
1758 * Given a path to a file or directory, convert it to a full path.
1759 * This collapses away relative paths. The full path is returned.
1761 std::string cmSystemTools::CollapseFullPath(const char* in_name)
1763 std::string dir, file;
1764 cmSystemTools::SplitProgramPath(in_name, dir, file);
1765 #ifdef _WIN32
1766 // Ultra-hack warning:
1767 // This changes to the target directory, saves the working directory,
1768 // and then changes back to the original working directory.
1769 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1770 if(dir != "") { Chdir(dir.c_str()); }
1771 std::string newDir = cmSystemTools::GetCurrentWorkingDirectory();
1772 Chdir(cwd.c_str());
1774 cmSystemTools::ConvertToUnixSlashes(newDir);
1775 std::string newPath = newDir+"/"+file;
1776 return newPath;
1777 #else
1778 # ifdef MAXPATHLEN
1779 char resolved_name[MAXPATHLEN];
1780 # else
1781 # ifdef PATH_MAX
1782 char resolved_name[PATH_MAX];
1783 # else
1784 char resolved_name[5024];
1785 # endif
1786 # endif
1787 if(dir != "")
1789 realpath(dir.c_str(), resolved_name);
1790 dir = resolved_name;
1792 else
1794 dir = cmSystemTools::GetCurrentWorkingDirectory();
1796 if(file == "")
1798 return dir;
1800 return dir + "/" + file;
1801 #endif
1805 * Return path of a full filename (no trailing slashes).
1806 * Warning: returned path is converted to Unix slashes format.
1808 std::string cmSystemTools::GetFilenamePath(const std::string& filename)
1810 std::string fn = filename;
1811 cmSystemTools::ConvertToUnixSlashes(fn);
1813 std::string::size_type slash_pos = fn.rfind("/");
1814 if(slash_pos != std::string::npos)
1816 return fn.substr(0, slash_pos);
1818 else
1820 return "";
1826 * Return file name of a full filename (i.e. file name without path).
1828 std::string cmSystemTools::GetFilenameName(const std::string& filename)
1830 std::string fn = filename;
1831 cmSystemTools::ConvertToUnixSlashes(fn);
1833 std::string::size_type slash_pos = fn.rfind("/");
1834 if(slash_pos != std::string::npos)
1836 return fn.substr(slash_pos + 1);
1838 else
1840 return filename;
1846 * Return file extension of a full filename (dot included).
1847 * Warning: this is the longest extension (for example: .tar.gz)
1849 std::string cmSystemTools::GetFilenameExtension(const std::string& filename)
1851 std::string name = cmSystemTools::GetFilenameName(filename);
1852 std::string::size_type dot_pos = name.find(".");
1853 if(dot_pos != std::string::npos)
1855 return name.substr(dot_pos);
1857 else
1859 return "";
1865 * Return file name without extension of a full filename (i.e. without path).
1866 * Warning: it considers the longest extension (for example: .tar.gz)
1868 std::string cmSystemTools::GetFilenameWithoutExtension(const std::string& filename)
1870 std::string name = cmSystemTools::GetFilenameName(filename);
1871 std::string::size_type dot_pos = name.find(".");
1872 if(dot_pos != std::string::npos)
1874 return name.substr(0, dot_pos);
1876 else
1878 return name;
1884 * Return file name without extension of a full filename (i.e. without path).
1885 * Warning: it considers the last extension (for example: removes .gz
1886 * from .tar.gz)
1888 std::string
1889 cmSystemTools::GetFilenameWithoutLastExtension(const std::string& filename)
1891 std::string name = cmSystemTools::GetFilenameName(filename);
1892 std::string::size_type dot_pos = name.rfind(".");
1893 if(dot_pos != std::string::npos)
1895 return name.substr(0, dot_pos);
1897 else
1899 return name;
1904 void cmSystemTools::Glob(const char *directory, const char *regexp,
1905 std::vector<std::string>& files)
1907 cmDirectory d;
1908 cmRegularExpression reg(regexp);
1910 if (d.Load(directory))
1912 size_t numf;
1913 unsigned int i;
1914 numf = d.GetNumberOfFiles();
1915 for (i = 0; i < numf; i++)
1917 std::string fname = d.GetFile(i);
1918 if (reg.find(fname))
1920 files.push_back(fname);
1927 void cmSystemTools::GlobDirs(const char *fullPath,
1928 std::vector<std::string>& files)
1930 std::string path = fullPath;
1931 std::string::size_type pos = path.find("/*");
1932 if(pos == std::string::npos)
1934 files.push_back(fullPath);
1935 return;
1937 std::string startPath = path.substr(0, pos);
1938 std::string finishPath = path.substr(pos+2);
1940 cmDirectory d;
1941 if (d.Load(startPath.c_str()))
1943 for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1945 if((std::string(d.GetFile(i)) != ".")
1946 && (std::string(d.GetFile(i)) != ".."))
1948 std::string fname = startPath;
1949 fname +="/";
1950 fname += d.GetFile(i);
1951 if(cmSystemTools::FileIsDirectory(fname.c_str()))
1953 fname += finishPath;
1954 cmSystemTools::GlobDirs(fname.c_str(), files);
1962 void cmSystemTools::ExpandListArguments(std::vector<std::string> const& arguments,
1963 std::vector<std::string>& newargs)
1965 std::vector<std::string>::const_iterator i;
1966 std::string newarg;
1967 for(i = arguments.begin();i != arguments.end(); ++i)
1969 // if there are no ; in the name then just copy the current string
1970 if(i->find(';') == std::string::npos)
1972 newargs.push_back(*i);
1974 else
1976 std::string::size_type start = 0;
1977 std::string::size_type endpos = 0;
1978 const std::string::size_type size = i->size();
1979 // break up ; separated sections of the string into separate strings
1980 while(endpos != size)
1982 endpos = i->find(';', start);
1983 if(endpos == std::string::npos)
1985 endpos = i->size();
1987 else
1989 // skip right over escaped ; ( \; )
1990 while((endpos != std::string::npos)
1991 && (endpos > 0)
1992 && ((*i)[endpos-1] == '\\') )
1994 endpos = i->find(';', endpos+1);
1996 if(endpos == std::string::npos)
1998 endpos = i->size();
2001 std::string::size_type len = endpos - start;
2002 if (len > 0)
2004 // check for a closing ] after the start position
2005 if(i->find('[', start) == std::string::npos)
2007 // if there is no [ in the string then keep it
2008 newarg = i->substr(start, len);
2010 else
2012 int opencount = 0;
2013 int closecount = 0;
2014 for(std::string::size_type j = start; j < endpos; ++j)
2016 if(i->at(j) == '[')
2018 ++opencount;
2020 else if (i->at(j) == ']')
2022 ++closecount;
2025 if(opencount != closecount)
2027 // skip this one
2028 endpos = i->find(';', endpos+1);
2029 if(endpos == std::string::npos)
2031 endpos = i->size();
2033 len = endpos - start;
2035 newarg = i->substr(start, len);
2037 std::string::size_type pos = newarg.find("\\;");
2038 if(pos != std::string::npos)
2040 newarg.erase(pos, 1);
2042 newargs.push_back(newarg);
2044 start = endpos+1;
2050 bool cmSystemTools::GetShortPath(const char* path, std::string& shortPath)
2052 #if defined(WIN32) && !defined(__CYGWIN__)
2053 const int size = int(strlen(path)) +1; // size of return
2054 char *buffer = new char[size]; // create a buffer
2055 char *tempPath = new char[size]; // create a buffer
2056 int ret;
2058 // if the path passed in has quotes around it, first remove the quotes
2059 if (path[0] == '"' && path[strlen(path)-1] == '"')
2061 strcpy(tempPath,path+1);
2062 tempPath[strlen(tempPath)-1] = '\0';
2064 else
2066 strcpy(tempPath,path);
2069 buffer[0] = 0;
2070 ret = GetShortPathName(tempPath, buffer, size);
2072 if(buffer[0] == 0 || ret > size)
2074 if(ret < size)
2076 LPVOID lpMsgBuf;
2077 FormatMessage(
2078 FORMAT_MESSAGE_ALLOCATE_BUFFER |
2079 FORMAT_MESSAGE_FROM_SYSTEM |
2080 FORMAT_MESSAGE_IGNORE_INSERTS,
2081 NULL,
2082 GetLastError(),
2083 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
2084 (LPTSTR) &lpMsgBuf,
2086 NULL
2088 cmSystemTools::Error((LPCTSTR)lpMsgBuf);
2089 LocalFree( lpMsgBuf );
2091 cmSystemTools::Error("Unable to get a short path: ", path);
2092 delete [] tempPath;
2093 return false;
2095 else
2097 shortPath = buffer;
2098 delete [] buffer;
2099 delete [] tempPath;
2100 return true;
2102 #else
2103 shortPath = path;
2104 return true;
2105 #endif