cmSystemTools.cxx 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2000 National Library of Medicine
  8. All rights reserved.
  9. See COPYRIGHT.txt for copyright details.
  10. =========================================================================*/
  11. #include "cmSystemTools.h"
  12. #include "errno.h"
  13. #include "stdio.h"
  14. #include <sys/stat.h>
  15. #include "cmRegularExpression.h"
  16. #if defined(_MSC_VER) || defined(__BORLANDC__)
  17. #include <windows.h>
  18. #include <direct.h>
  19. #define _unlink unlink
  20. inline int Mkdir(const char* dir)
  21. {
  22. return _mkdir(dir);
  23. }
  24. #else
  25. #include <sys/types.h>
  26. #include <fcntl.h>
  27. #include <unistd.h>
  28. inline int Mkdir(const char* dir)
  29. {
  30. return mkdir(dir, 00777);
  31. }
  32. #endif
  33. bool cmSystemTools::s_ErrorOccured = false;
  34. // adds the elements of the env variable path to the arg passed in
  35. void cmSystemTools::GetPath(std::vector<std::string>& path)
  36. {
  37. #if defined(_WIN32) && !defined(__CYGWIN__)
  38. char* pathSep = ";";
  39. #else
  40. char* pathSep = ":";
  41. #endif
  42. std::string pathEnv = getenv("PATH");
  43. std::string::size_type start =0;
  44. bool done = false;
  45. while(!done)
  46. {
  47. std::string::size_type endpos = pathEnv.find(pathSep, start);
  48. if(endpos != std::string::npos)
  49. {
  50. path.push_back(pathEnv.substr(start, endpos-start));
  51. start = endpos+1;
  52. }
  53. else
  54. {
  55. done = true;
  56. }
  57. }
  58. }
  59. bool cmSystemTools::MakeDirectory(const char* path)
  60. {
  61. std::string dir = path;
  62. // replace all of the \ with /
  63. size_t pos = 0;
  64. while((pos = dir.find('\\', pos)) != std::string::npos)
  65. {
  66. dir[pos] = '/';
  67. pos++;
  68. }
  69. pos = dir.find(':');
  70. if(pos == std::string::npos)
  71. {
  72. pos = 0;
  73. }
  74. while((pos = dir.find('/', pos)) != std::string::npos)
  75. {
  76. std::string topdir = dir.substr(0, pos);
  77. Mkdir(topdir.c_str());
  78. pos++;
  79. }
  80. if(Mkdir(path) != 0)
  81. {
  82. // if it is some other error besides directory exists
  83. // then return false
  84. if(errno != EEXIST)
  85. {
  86. return false;
  87. }
  88. }
  89. return true;
  90. }
  91. // replace replace with with as many times as it shows up in source.
  92. // write the result into source.
  93. void cmSystemTools::ReplaceString(std::string& source,
  94. const char* replace,
  95. const char* with)
  96. {
  97. int lengthReplace = strlen(replace);
  98. std::string rest;
  99. size_t start = source.find(replace);
  100. while(start != std::string::npos)
  101. {
  102. rest = source.substr(start+lengthReplace);
  103. source = source.substr(0, start);
  104. source += with;
  105. source += rest;
  106. start = source.find(replace, start + lengthReplace );
  107. }
  108. }
  109. // return true if the file exists
  110. bool cmSystemTools::FileExists(const char* filename)
  111. {
  112. struct stat fs;
  113. if (stat(filename, &fs) != 0)
  114. {
  115. return false;
  116. }
  117. else
  118. {
  119. return true;
  120. }
  121. }
  122. // convert windows slashes to unix slashes \ with /
  123. void cmSystemTools::ConvertToUnixSlashes(std::string& path)
  124. {
  125. std::string::size_type pos = path.find('\\');
  126. while(pos != std::string::npos)
  127. {
  128. path[pos] = '/';
  129. pos = path.find('\\');
  130. }
  131. // remove any trailing slash
  132. if(path[path.size()-1] == '/')
  133. {
  134. path = path.substr(0, path.size()-1);
  135. }
  136. }
  137. int cmSystemTools::Grep(const char* dir, const char* file,
  138. const char* expression)
  139. {
  140. std::string path = dir;
  141. path += "/";
  142. path += file;
  143. std::ifstream fin(path.c_str());
  144. char buffer[2056];
  145. int count = 0;
  146. cmRegularExpression reg(expression);
  147. while(fin)
  148. {
  149. fin.getline(buffer, sizeof(buffer));
  150. count += reg.find(buffer);
  151. }
  152. return count;
  153. }
  154. void cmSystemTools::ConvertCygwinPath(std::string& pathname)
  155. {
  156. if(pathname.find("/cygdrive/") != std::string::npos)
  157. {
  158. std::string cygStuff = pathname.substr(0, 11);
  159. std::string replace;
  160. replace += cygStuff.at(10);
  161. replace += ":";
  162. cmSystemTools::ReplaceString(pathname, cygStuff.c_str(), replace.c_str());
  163. }
  164. }
  165. bool cmSystemTools::ParseFunction(std::ifstream& fin,
  166. std::string& name,
  167. std::vector<std::string>& arguments)
  168. {
  169. name = "";
  170. arguments = std::vector<std::string>();
  171. const int BUFFER_SIZE = 4096;
  172. char inbuffer[BUFFER_SIZE];
  173. if(!fin)
  174. {
  175. return false;
  176. }
  177. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  178. {
  179. cmRegularExpression blankLine("^$");
  180. cmRegularExpression comment("^#.*");
  181. cmRegularExpression oneLiner("[ \t]*([A-Za-z_0-9]*).*\\((.*)\\)");
  182. cmRegularExpression multiLine("[ \t]*([A-Za-z_0-9]*).*\\((.*)");
  183. cmRegularExpression lastLine("(.*)\\)");
  184. // BEGIN VERBATIM JUNK SHOULD BE REMOVED
  185. cmRegularExpression verbatim("BEGIN MAKE VERBATIM");
  186. if(verbatim.find(inbuffer))
  187. {
  188. cmRegularExpression endVerbatim("END MAKE VERBATIM");
  189. name = "VERBATIM";
  190. bool done = false;
  191. while(!done)
  192. {
  193. if(fin.getline(inbuffer, BUFFER_SIZE))
  194. {
  195. if(endVerbatim.find(inbuffer))
  196. {
  197. done = true;
  198. }
  199. else
  200. {
  201. arguments.push_back(inbuffer);
  202. }
  203. }
  204. else
  205. {
  206. done = true;
  207. }
  208. }
  209. return true;
  210. }
  211. // END VERBATIM JUNK SHOULD BE REMOVED
  212. // check for black line or comment
  213. if(blankLine.find(inbuffer) || comment.find(inbuffer))
  214. {
  215. return false;
  216. }
  217. // look for a oneline fun(arg arg2)
  218. else if(oneLiner.find(inbuffer))
  219. {
  220. // the arguments are the second match
  221. std::string args = oneLiner.match(2);
  222. name = oneLiner.match(1);
  223. // break up the arguments
  224. cmSystemTools::GetArguments(args, arguments);
  225. return true;
  226. }
  227. // look for a start of a multiline with no trailing ")" fun(arg arg2
  228. else if(multiLine.find(inbuffer))
  229. {
  230. name = multiLine.match(1);
  231. std::string args = multiLine.match(2);
  232. cmSystemTools::GetArguments(args, arguments);
  233. // Read lines until the closing paren is hit
  234. bool done = false;
  235. while(!done)
  236. {
  237. // read lines until the end paren is found
  238. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  239. {
  240. if(lastLine.find(inbuffer))
  241. {
  242. done = true;
  243. std::string args = lastLine.match(1);
  244. cmSystemTools::GetArguments(args, arguments);
  245. }
  246. else
  247. {
  248. std::string line = inbuffer;
  249. cmSystemTools::GetArguments(line, arguments);
  250. }
  251. }
  252. else
  253. {
  254. cmSystemTools::Error("Parse error in read function missing end )",
  255. inbuffer);
  256. return false;
  257. }
  258. }
  259. return true;
  260. }
  261. else
  262. {
  263. cmSystemTools::Error("Parse error in read function ", inbuffer);
  264. return false;
  265. }
  266. }
  267. return false;
  268. }
  269. void cmSystemTools::GetArguments(std::string& line,
  270. std::vector<std::string>& arguments)
  271. {
  272. cmRegularExpression argument("[\t ]*([-/\\.\\\\{}\\$A-Za-z_0-9]+)[\t ]*");
  273. cmRegularExpression argumentWithSpaces("[\t ]*\"([-\\. /\\\\{}\\$A-Za-z_0-9]+)\"[\t ]*");
  274. std::string arg(" ");
  275. while(arg.length() )
  276. {
  277. arg = "";
  278. long endpos;
  279. if (argumentWithSpaces.find(line.c_str()))
  280. {
  281. arg = argumentWithSpaces.match(1);
  282. endpos = argumentWithSpaces.end(1);
  283. }
  284. else if(argument.find(line.c_str()))
  285. {
  286. arg = argument.match(1);
  287. endpos = argument.end(1);
  288. }
  289. if(arg.length())
  290. {
  291. arguments.push_back(arg);
  292. line = line.substr(endpos, line.length() - endpos);
  293. }
  294. }
  295. }
  296. void cmSystemTools::Error(const char* m1, const char* m2)
  297. {
  298. std::string message = "CMake Error: ";
  299. if(m1)
  300. {
  301. message += m1;
  302. }
  303. if(m2)
  304. {
  305. message += m2;
  306. }
  307. cmSystemTools::s_ErrorOccured = true;
  308. #if defined(_WIN32) && !defined(__CYGWIN__)
  309. ::MessageBox(0, message.c_str(), 0, MB_OK);
  310. std::cerr << message.c_str() << std::endl;
  311. #else
  312. std::cerr << message.c_str() << std::endl;
  313. #endif
  314. }
  315. void cmSystemTools::CopyFileIfDifferent(const char* source,
  316. const char* destination)
  317. {
  318. if(cmSystemTools::FilesDiffer(source, destination))
  319. {
  320. cmSystemTools::cmCopyFile(source, destination);
  321. }
  322. }
  323. bool cmSystemTools::FilesDiffer(const char* source,
  324. const char* destination)
  325. {
  326. struct stat statSource;
  327. if (stat(source, &statSource) != 0)
  328. {
  329. return true;
  330. }
  331. struct stat statDestination;
  332. if (stat(destination, &statDestination) != 0)
  333. {
  334. return true;
  335. }
  336. if(statSource.st_size != statDestination.st_size)
  337. {
  338. return true;
  339. }
  340. std::ifstream finSource(source);
  341. std::ifstream finDestination(destination);
  342. if(!finSource || !finDestination)
  343. {
  344. return true;
  345. }
  346. while(finSource && finDestination)
  347. {
  348. char s, d;
  349. finSource >> s;
  350. finDestination >> d;
  351. if(s != d)
  352. {
  353. return true;
  354. }
  355. }
  356. return false;
  357. }
  358. void cmSystemTools::cmCopyFile(const char* source,
  359. const char* destination)
  360. {
  361. std::ifstream fin(source);
  362. char buff[4096];
  363. std::ofstream fout(destination);
  364. if(!fout )
  365. {
  366. cmSystemTools::Error("CopyFile failed to open input file", source);
  367. }
  368. if(!fin)
  369. {
  370. cmSystemTools::Error("CopyFile failed to open output file", destination);
  371. }
  372. while(fin)
  373. {
  374. fin.getline(buff, 4096);
  375. if(fin)
  376. {
  377. fout << buff << "\n";
  378. }
  379. }
  380. }
  381. // return true if the file exists
  382. long int cmSystemTools::ModifiedTime(const char* filename)
  383. {
  384. struct stat fs;
  385. if (stat(filename, &fs) != 0)
  386. {
  387. return 0;
  388. }
  389. else
  390. {
  391. return (long int)fs.st_mtime;
  392. }
  393. }
  394. void cmSystemTools::RemoveFile(const char* source)
  395. {
  396. unlink(source);
  397. }