cmSystemTools.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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. const char* cmSystemTools::GetExecutableExtension()
  60. {
  61. #if defined(_WIN32)
  62. return ".exe";
  63. #else
  64. return "";
  65. #endif
  66. }
  67. bool cmSystemTools::MakeDirectory(const char* path)
  68. {
  69. std::string dir = path;
  70. // replace all of the \ with /
  71. size_t pos = 0;
  72. while((pos = dir.find('\\', pos)) != std::string::npos)
  73. {
  74. dir[pos] = '/';
  75. pos++;
  76. }
  77. pos = dir.find(':');
  78. if(pos == std::string::npos)
  79. {
  80. pos = 0;
  81. }
  82. while((pos = dir.find('/', pos)) != std::string::npos)
  83. {
  84. std::string topdir = dir.substr(0, pos);
  85. Mkdir(topdir.c_str());
  86. pos++;
  87. }
  88. if(Mkdir(path) != 0)
  89. {
  90. // if it is some other error besides directory exists
  91. // then return false
  92. if(errno != EEXIST)
  93. {
  94. return false;
  95. }
  96. }
  97. return true;
  98. }
  99. // replace replace with with as many times as it shows up in source.
  100. // write the result into source.
  101. void cmSystemTools::ReplaceString(std::string& source,
  102. const char* replace,
  103. const char* with)
  104. {
  105. int lengthReplace = strlen(replace);
  106. std::string rest;
  107. size_t start = source.find(replace);
  108. while(start != std::string::npos)
  109. {
  110. rest = source.substr(start+lengthReplace);
  111. source = source.substr(0, start);
  112. source += with;
  113. source += rest;
  114. start = source.find(replace, start + lengthReplace );
  115. }
  116. }
  117. std::string cmSystemTools::EscapeSpaces(const char* str)
  118. {
  119. std::string result = "";
  120. for(const char* ch = str; *ch != '\0'; ++ch)
  121. {
  122. if(*ch == ' ')
  123. {
  124. result += '\\';
  125. }
  126. result += *ch;
  127. }
  128. return result;
  129. }
  130. // return true if the file exists
  131. bool cmSystemTools::FileExists(const char* filename)
  132. {
  133. struct stat fs;
  134. if (stat(filename, &fs) != 0)
  135. {
  136. return false;
  137. }
  138. else
  139. {
  140. return true;
  141. }
  142. }
  143. // convert windows slashes to unix slashes \ with /
  144. void cmSystemTools::ConvertToUnixSlashes(std::string& path)
  145. {
  146. std::string::size_type pos = path.find('\\');
  147. while(pos != std::string::npos)
  148. {
  149. path[pos] = '/';
  150. pos = path.find('\\');
  151. }
  152. // remove any trailing slash
  153. if(path[path.size()-1] == '/')
  154. {
  155. path = path.substr(0, path.size()-1);
  156. }
  157. }
  158. int cmSystemTools::Grep(const char* dir, const char* file,
  159. const char* expression)
  160. {
  161. std::string path = dir;
  162. path += "/";
  163. path += file;
  164. std::ifstream fin(path.c_str());
  165. char buffer[2056];
  166. int count = 0;
  167. cmRegularExpression reg(expression);
  168. while(fin)
  169. {
  170. fin.getline(buffer, sizeof(buffer));
  171. count += reg.find(buffer);
  172. }
  173. return count;
  174. }
  175. void cmSystemTools::ConvertCygwinPath(std::string& pathname)
  176. {
  177. if(pathname.find("/cygdrive/") != std::string::npos)
  178. {
  179. std::string cygStuff = pathname.substr(0, 11);
  180. std::string replace;
  181. replace += cygStuff.at(10);
  182. replace += ":";
  183. cmSystemTools::ReplaceString(pathname, cygStuff.c_str(), replace.c_str());
  184. }
  185. }
  186. bool cmSystemTools::ParseFunction(std::ifstream& fin,
  187. std::string& name,
  188. std::vector<std::string>& arguments)
  189. {
  190. name = "";
  191. arguments = std::vector<std::string>();
  192. const int BUFFER_SIZE = 4096;
  193. char inbuffer[BUFFER_SIZE];
  194. if(!fin)
  195. {
  196. return false;
  197. }
  198. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  199. {
  200. cmRegularExpression blankLine("^[ \t]*$");
  201. cmRegularExpression comment("^[ \t]*#.*$");
  202. cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t]*$");
  203. cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
  204. cmRegularExpression lastLine("^(.*)\\)[ \t]*$");
  205. // BEGIN VERBATIM JUNK SHOULD BE REMOVED
  206. cmRegularExpression verbatim("BEGIN MAKE VERBATIM");
  207. if(verbatim.find(inbuffer))
  208. {
  209. cmRegularExpression endVerbatim("END MAKE VERBATIM");
  210. name = "VERBATIM";
  211. bool done = false;
  212. while(!done)
  213. {
  214. if(fin.getline(inbuffer, BUFFER_SIZE))
  215. {
  216. if(endVerbatim.find(inbuffer))
  217. {
  218. done = true;
  219. }
  220. else
  221. {
  222. arguments.push_back(inbuffer);
  223. }
  224. }
  225. else
  226. {
  227. done = true;
  228. }
  229. }
  230. return true;
  231. }
  232. // END VERBATIM JUNK SHOULD BE REMOVED
  233. // check for black line or comment
  234. if(blankLine.find(inbuffer) || comment.find(inbuffer))
  235. {
  236. return false;
  237. }
  238. // look for a oneline fun(arg arg2)
  239. else if(oneLiner.find(inbuffer))
  240. {
  241. // the arguments are the second match
  242. std::string args = oneLiner.match(2);
  243. name = oneLiner.match(1);
  244. // break up the arguments
  245. cmSystemTools::GetArguments(args, arguments);
  246. return true;
  247. }
  248. // look for a start of a multiline with no trailing ")" fun(arg arg2
  249. else if(multiLine.find(inbuffer))
  250. {
  251. name = multiLine.match(1);
  252. std::string args = multiLine.match(2);
  253. cmSystemTools::GetArguments(args, arguments);
  254. // Read lines until the closing paren is hit
  255. bool done = false;
  256. while(!done)
  257. {
  258. // read lines until the end paren is found
  259. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  260. {
  261. // Check for comment lines and ignore them.
  262. if(blankLine.find(inbuffer) || comment.find(inbuffer))
  263. { continue; }
  264. // Is this the last line?
  265. if(lastLine.find(inbuffer))
  266. {
  267. done = true;
  268. std::string args = lastLine.match(1);
  269. cmSystemTools::GetArguments(args, arguments);
  270. }
  271. else
  272. {
  273. std::string line = inbuffer;
  274. cmSystemTools::GetArguments(line, arguments);
  275. }
  276. }
  277. else
  278. {
  279. cmSystemTools::Error("Parse error in read function missing end )",
  280. inbuffer);
  281. return false;
  282. }
  283. }
  284. return true;
  285. }
  286. else
  287. {
  288. cmSystemTools::Error("Parse error in read function ", inbuffer);
  289. return false;
  290. }
  291. }
  292. return false;
  293. }
  294. void cmSystemTools::GetArguments(std::string& line,
  295. std::vector<std::string>& arguments)
  296. {
  297. // Match a normal argument (not quoted, no spaces).
  298. cmRegularExpression normalArgument("[\t ]*([^\" \t]+)[\t ]*");
  299. // Match a quoted argument (surrounded by double quotes, spaces allowed).
  300. cmRegularExpression quotedArgument("[\t ]*(\"[^\"]*\")[\t ]*");
  301. bool done = false;
  302. while(!done)
  303. {
  304. std::string arg;
  305. long endpos;
  306. bool foundQuoted = quotedArgument.find(line.c_str());
  307. bool foundNormal = normalArgument.find(line.c_str());
  308. if(foundQuoted && foundNormal)
  309. {
  310. // Both matches were found. Take the earlier one.
  311. if(normalArgument.start(1) < quotedArgument.start(1))
  312. {
  313. arg = normalArgument.match(1);
  314. endpos = normalArgument.end(1);
  315. }
  316. else
  317. {
  318. arg = quotedArgument.match(1);
  319. endpos = quotedArgument.end(1);
  320. // Strip off the double quotes on the ends.
  321. arg = arg.substr(1, arg.length()-2);
  322. }
  323. }
  324. else if (foundQuoted)
  325. {
  326. arg = quotedArgument.match(1);
  327. endpos = quotedArgument.end(1);
  328. // Strip off the double quotes on the ends.
  329. arg = arg.substr(1, arg.length()-2);
  330. }
  331. else if(foundNormal)
  332. {
  333. arg = normalArgument.match(1);
  334. endpos = normalArgument.end(1);
  335. }
  336. else
  337. {
  338. done = true;
  339. }
  340. if(!done)
  341. {
  342. arguments.push_back(arg);
  343. line = line.substr(endpos, line.length() - endpos);
  344. }
  345. }
  346. }
  347. void cmSystemTools::Error(const char* m1, const char* m2,
  348. const char* m3, const char* m4)
  349. {
  350. std::string message = "CMake Error: ";
  351. if(m1)
  352. {
  353. message += m1;
  354. }
  355. if(m2)
  356. {
  357. message += m2;
  358. }
  359. if(m3)
  360. {
  361. message += m3;
  362. }
  363. if(m4)
  364. {
  365. message += m4;
  366. }
  367. cmSystemTools::s_ErrorOccured = true;
  368. #if defined(_WIN32) && !defined(__CYGWIN__)
  369. ::MessageBox(0, message.c_str(), 0, MB_OK);
  370. std::cerr << message.c_str() << std::endl;
  371. #else
  372. std::cerr << message.c_str() << std::endl;
  373. #endif
  374. }
  375. void cmSystemTools::CopyFileIfDifferent(const char* source,
  376. const char* destination)
  377. {
  378. if(cmSystemTools::FilesDiffer(source, destination))
  379. {
  380. cmSystemTools::cmCopyFile(source, destination);
  381. }
  382. }
  383. bool cmSystemTools::FilesDiffer(const char* source,
  384. const char* destination)
  385. {
  386. struct stat statSource;
  387. if (stat(source, &statSource) != 0)
  388. {
  389. return true;
  390. }
  391. struct stat statDestination;
  392. if (stat(destination, &statDestination) != 0)
  393. {
  394. return true;
  395. }
  396. if(statSource.st_size != statDestination.st_size)
  397. {
  398. return true;
  399. }
  400. std::ifstream finSource(source);
  401. std::ifstream finDestination(destination);
  402. if(!finSource || !finDestination)
  403. {
  404. return true;
  405. }
  406. while(finSource && finDestination)
  407. {
  408. char s, d;
  409. finSource >> s;
  410. finDestination >> d;
  411. if(s != d)
  412. {
  413. return true;
  414. }
  415. }
  416. return false;
  417. }
  418. void cmSystemTools::cmCopyFile(const char* source,
  419. const char* destination)
  420. {
  421. std::ifstream fin(source);
  422. char buff[4096];
  423. std::ofstream fout(destination);
  424. if(!fout )
  425. {
  426. cmSystemTools::Error("CopyFile failed to open input file", source);
  427. }
  428. if(!fin)
  429. {
  430. cmSystemTools::Error("CopyFile failed to open output file", destination);
  431. }
  432. while(fin)
  433. {
  434. fin.getline(buff, 4096);
  435. if(fin)
  436. {
  437. fout << buff << "\n";
  438. }
  439. }
  440. }
  441. // return true if the file exists
  442. long int cmSystemTools::ModifiedTime(const char* filename)
  443. {
  444. struct stat fs;
  445. if (stat(filename, &fs) != 0)
  446. {
  447. return 0;
  448. }
  449. else
  450. {
  451. return (long int)fs.st_mtime;
  452. }
  453. }
  454. void cmSystemTools::RemoveFile(const char* source)
  455. {
  456. unlink(source);
  457. }