cmSystemTools.cxx 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/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.
  12. =========================================================================*/
  13. #include "cmSystemTools.h"
  14. #include "errno.h"
  15. #include "stdio.h"
  16. #include <sys/stat.h>
  17. #include "cmRegularExpression.h"
  18. #include <ctype.h>
  19. #include "cmDirectory.h"
  20. // support for realpath call
  21. #ifndef _WIN32
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. #include <sys/param.h>
  25. #include <sys/wait.h>
  26. #endif
  27. #if defined(_MSC_VER) || defined(__BORLANDC__)
  28. #include <string.h>
  29. #include <windows.h>
  30. #include <direct.h>
  31. #define _unlink unlink
  32. inline int Mkdir(const char* dir)
  33. {
  34. return _mkdir(dir);
  35. }
  36. inline const char* Getcwd(char* buf, unsigned int len)
  37. {
  38. return _getcwd(buf, len);
  39. }
  40. inline int Chdir(const char* dir)
  41. {
  42. #if defined(__BORLANDC__)
  43. return chdir(dir);
  44. #else
  45. return _chdir(dir);
  46. #endif
  47. }
  48. #else
  49. #include <sys/types.h>
  50. #include <fcntl.h>
  51. #include <unistd.h>
  52. inline int Mkdir(const char* dir)
  53. {
  54. return mkdir(dir, 00777);
  55. }
  56. inline const char* Getcwd(char* buf, unsigned int len)
  57. {
  58. return getcwd(buf, len);
  59. }
  60. inline int Chdir(const char* dir)
  61. {
  62. return chdir(dir);
  63. }
  64. #endif
  65. bool cmSystemTools::s_DisableRunCommandOutput = false;
  66. bool cmSystemTools::s_ErrorOccured = false;
  67. bool cmSystemTools::s_DisableMessages = false;
  68. void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, bool&);
  69. // adds the elements of the env variable path to the arg passed in
  70. void cmSystemTools::GetPath(std::vector<std::string>& path)
  71. {
  72. #if defined(_WIN32) && !defined(__CYGWIN__)
  73. const char* pathSep = ";";
  74. #else
  75. const char* pathSep = ":";
  76. #endif
  77. std::string pathEnv = getenv("PATH");
  78. // A hack to make the below algorithm work.
  79. if(pathEnv[pathEnv.length()-1] != ':')
  80. {
  81. pathEnv += pathSep;
  82. }
  83. std::string::size_type start =0;
  84. bool done = false;
  85. while(!done)
  86. {
  87. std::string::size_type endpos = pathEnv.find(pathSep, start);
  88. if(endpos != std::string::npos)
  89. {
  90. path.push_back(pathEnv.substr(start, endpos-start));
  91. start = endpos+1;
  92. }
  93. else
  94. {
  95. done = true;
  96. }
  97. }
  98. for(std::vector<std::string>::iterator i = path.begin();
  99. i != path.end(); ++i)
  100. {
  101. cmSystemTools::ConvertToUnixSlashes(*i);
  102. }
  103. }
  104. const char* cmSystemTools::GetExecutableExtension()
  105. {
  106. #if defined(_WIN32) || defined(__CYGWIN__)
  107. return ".exe";
  108. #else
  109. return "";
  110. #endif
  111. }
  112. bool cmSystemTools::MakeDirectory(const char* path)
  113. {
  114. if(cmSystemTools::FileExists(path))
  115. {
  116. return true;
  117. }
  118. std::string dir = path;
  119. if(dir.size() == 0)
  120. {
  121. return false;
  122. }
  123. cmSystemTools::ConvertToUnixSlashes(dir);
  124. std::string::size_type pos = dir.find(':');
  125. if(pos == std::string::npos)
  126. {
  127. pos = 0;
  128. }
  129. std::string topdir;
  130. while((pos = dir.find('/', pos)) != std::string::npos)
  131. {
  132. topdir = dir.substr(0, pos);
  133. Mkdir(topdir.c_str());
  134. pos++;
  135. }
  136. if(dir[dir.size()-1] == '/')
  137. {
  138. topdir = dir.substr(0, dir.size());
  139. }
  140. else
  141. {
  142. topdir = dir;
  143. }
  144. if(Mkdir(topdir.c_str()) != 0)
  145. {
  146. // There is a bug in the Borland Run time library which makes MKDIR
  147. // return EACCES when it should return EEXISTS
  148. // if it is some other error besides directory exists
  149. // then return false
  150. if( (errno != EEXIST)
  151. #ifdef __BORLANDC__
  152. && (errno != EACCES)
  153. #endif
  154. )
  155. {
  156. cmSystemTools::Error("Faild to create directory:", path);
  157. return false;
  158. }
  159. }
  160. return true;
  161. }
  162. // replace replace with with as many times as it shows up in source.
  163. // write the result into source.
  164. void cmSystemTools::ReplaceString(std::string& source,
  165. const char* replace,
  166. const char* with)
  167. {
  168. std::string::size_type lengthReplace = strlen(replace);
  169. std::string rest;
  170. std::string::size_type start = source.find(replace);
  171. while(start != std::string::npos)
  172. {
  173. rest = source.substr(start+lengthReplace);
  174. source = source.substr(0, start);
  175. source += with;
  176. source += rest;
  177. start = source.find(replace, start + lengthReplace );
  178. }
  179. }
  180. #if defined(_WIN32) && !defined(__CYGWIN__)
  181. // Get the data of key value.
  182. // Example :
  183. // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
  184. // => will return the data of the "default" value of the key
  185. // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
  186. // => will return the data of the "Root" value of the key
  187. bool ReadAValue(std::string &res, const char *key)
  188. {
  189. // find the primary key
  190. std::string primary = key;
  191. std::string second;
  192. std::string valuename;
  193. size_t start = primary.find("\\");
  194. if (start == std::string::npos)
  195. {
  196. return false;
  197. }
  198. size_t valuenamepos = primary.find(";");
  199. if (valuenamepos != std::string::npos)
  200. {
  201. valuename = primary.substr(valuenamepos+1);
  202. }
  203. second = primary.substr(start+1, valuenamepos-start-1);
  204. primary = primary.substr(0, start);
  205. HKEY primaryKey;
  206. if (primary == "HKEY_CURRENT_USER")
  207. {
  208. primaryKey = HKEY_CURRENT_USER;
  209. }
  210. if (primary == "HKEY_CURRENT_CONFIG")
  211. {
  212. primaryKey = HKEY_CURRENT_CONFIG;
  213. }
  214. if (primary == "HKEY_CLASSES_ROOT")
  215. {
  216. primaryKey = HKEY_CLASSES_ROOT;
  217. }
  218. if (primary == "HKEY_LOCAL_MACHINE")
  219. {
  220. primaryKey = HKEY_LOCAL_MACHINE;
  221. }
  222. if (primary == "HKEY_USERS")
  223. {
  224. primaryKey = HKEY_USERS;
  225. }
  226. HKEY hKey;
  227. if(RegOpenKeyEx(primaryKey, second.c_str(),
  228. 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  229. {
  230. return false;
  231. }
  232. else
  233. {
  234. DWORD dwType, dwSize;
  235. dwSize = 1023;
  236. char data[1024];
  237. if(RegQueryValueEx(hKey, (LPTSTR)valuename.c_str(), NULL, &dwType,
  238. (BYTE *)data, &dwSize) == ERROR_SUCCESS)
  239. {
  240. if (dwType == REG_SZ)
  241. {
  242. res = data;
  243. return true;
  244. }
  245. }
  246. }
  247. return false;
  248. }
  249. #endif
  250. // replace replace with with as many times as it shows up in source.
  251. // write the result into source.
  252. void cmSystemTools::ExpandRegistryValues(std::string& source)
  253. {
  254. #if defined(_WIN32) && !defined(__CYGWIN__)
  255. // Regular expression to match anything inside [...] that begins in HKEY.
  256. // Note that there is a special rule for regular expressions to match a
  257. // close square-bracket inside a list delimited by square brackets.
  258. // The "[^]]" part of this expression will match any character except
  259. // a close square-bracket. The ']' character must be the first in the
  260. // list of characters inside the [^...] block of the expression.
  261. cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]");
  262. // check for black line or comment
  263. while (regEntry.find(source))
  264. {
  265. // the arguments are the second match
  266. std::string key = regEntry.match(1);
  267. std::string val;
  268. if (ReadAValue(val,key.c_str()))
  269. {
  270. std::string reg = "[";
  271. reg += key + "]";
  272. cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
  273. }
  274. else
  275. {
  276. std::string reg = "[";
  277. reg += key + "]";
  278. cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
  279. }
  280. }
  281. #endif
  282. }
  283. std::string cmSystemTools::EscapeQuotes(const char* str)
  284. {
  285. std::string result = "";
  286. for(const char* ch = str; *ch != '\0'; ++ch)
  287. {
  288. if(*ch == '"')
  289. {
  290. result += '\\';
  291. }
  292. result += *ch;
  293. }
  294. return result;
  295. }
  296. bool cmSystemTools::SameFile(const char* file1, const char* file2)
  297. {
  298. struct stat fileStat1, fileStat2;
  299. if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
  300. {
  301. // see if the files are the same file
  302. // check the device inode and size
  303. if(fileStat2.st_dev == fileStat1.st_dev &&
  304. fileStat2.st_ino == fileStat1.st_ino &&
  305. fileStat2.st_size == fileStat1.st_size
  306. )
  307. {
  308. return true;
  309. }
  310. }
  311. return false;
  312. }
  313. // return true if the file exists
  314. bool cmSystemTools::FileExists(const char* filename)
  315. {
  316. struct stat fs;
  317. if (stat(filename, &fs) != 0)
  318. {
  319. return false;
  320. }
  321. else
  322. {
  323. return true;
  324. }
  325. }
  326. // Return a capitalized string (i.e the first letter is uppercased, all other
  327. // are lowercased)
  328. std::string cmSystemTools::Capitalized(const std::string& s)
  329. {
  330. std::string n;
  331. n.resize(s.size());
  332. n[0] = toupper(s[0]);
  333. for (size_t i = 1; i < s.size(); i++)
  334. {
  335. n[i] = tolower(s[i]);
  336. }
  337. return n;
  338. }
  339. // Return a lower case string
  340. std::string cmSystemTools::LowerCase(const std::string& s)
  341. {
  342. std::string n;
  343. n.resize(s.size());
  344. for (size_t i = 0; i < s.size(); i++)
  345. {
  346. n[i] = tolower(s[i]);
  347. }
  348. return n;
  349. }
  350. // Return a lower case string
  351. std::string cmSystemTools::UpperCase(const std::string& s)
  352. {
  353. std::string n;
  354. n.resize(s.size());
  355. for (size_t i = 0; i < s.size(); i++)
  356. {
  357. n[i] = toupper(s[i]);
  358. }
  359. return n;
  360. }
  361. // convert windows slashes to unix slashes
  362. void cmSystemTools::ConvertToUnixSlashes(std::string& path)
  363. {
  364. std::string::size_type pos = 0;
  365. while((pos = path.find('\\', pos)) != std::string::npos)
  366. {
  367. path[pos] = '/';
  368. pos++;
  369. }
  370. // remove any trailing slash
  371. if(path.size() && path[path.size()-1] == '/')
  372. {
  373. path = path.substr(0, path.size()-1);
  374. }
  375. // if there is a tilda ~ then replace it with HOME
  376. if(path.find("~") == 0)
  377. {
  378. if (getenv("HOME"))
  379. {
  380. path = std::string(getenv("HOME")) + path.substr(1);
  381. }
  382. }
  383. // if there is a /tmp_mnt in a path get rid of it!
  384. // stupid sgi's
  385. if(path.find("/tmp_mnt") == 0)
  386. {
  387. path = path.substr(8);
  388. }
  389. }
  390. // change // to /, and escape any spaces in the path
  391. std::string cmSystemTools::ConvertToUnixOutputPath(const char* path)
  392. {
  393. std::string ret = path;
  394. // remove // except at the beginning might be a cygwin drive
  395. std::string::size_type pos = 1;
  396. while((pos = ret.find("//", pos)) != std::string::npos)
  397. {
  398. ret.erase(pos, 1);
  399. }
  400. // now escape spaces if there is a space in the path
  401. if(ret.find(" ") != std::string::npos)
  402. {
  403. std::string result = "";
  404. char lastch = 1;
  405. for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
  406. {
  407. // if it is already escaped then don't try to escape it again
  408. if(*ch == ' ' && lastch != '\\')
  409. {
  410. result += '\\';
  411. }
  412. result += *ch;
  413. lastch = *ch;
  414. }
  415. ret = result;
  416. }
  417. return ret;
  418. }
  419. std::string cmSystemTools::EscapeSpaces(const char* str)
  420. {
  421. #if defined(_WIN32) && !defined(__CYGWIN__)
  422. std::string result;
  423. // if there are spaces
  424. std::string temp = str;
  425. if (temp.find(" ") != std::string::npos &&
  426. temp.find("\"")==std::string::npos)
  427. {
  428. result = "\"";
  429. result += str;
  430. result += "\"";
  431. return result;
  432. }
  433. return str;
  434. #else
  435. std::string result = "";
  436. for(const char* ch = str; *ch != '\0'; ++ch)
  437. {
  438. if(*ch == ' ')
  439. {
  440. result += '\\';
  441. }
  442. result += *ch;
  443. }
  444. return result;
  445. #endif
  446. }
  447. std::string cmSystemTools::ConvertToOutputPath(const char* path)
  448. {
  449. #if defined(_WIN32) && !defined(__CYGWIN__)
  450. return cmSystemTools::ConvertToWindowsOutputPath(path);
  451. #else
  452. return cmSystemTools::ConvertToUnixOutputPath(path);
  453. #endif
  454. }
  455. // remove double slashes not at the start
  456. std::string cmSystemTools::ConvertToWindowsOutputPath(const char* path)
  457. {
  458. std::string ret = path;
  459. std::string::size_type pos = 0;
  460. // first convert all of the slashes
  461. while((pos = ret.find('/', pos)) != std::string::npos)
  462. {
  463. ret[pos] = '\\';
  464. pos++;
  465. }
  466. // check for really small paths
  467. if(ret.size() < 2)
  468. {
  469. return ret;
  470. }
  471. // now clean up a bit and remove double slashes
  472. // Only if it is not the first position in the path which is a network
  473. // path on windows
  474. pos = 1; // start at position 1
  475. while((pos = ret.find("\\\\", pos)) != std::string::npos)
  476. {
  477. ret.erase(pos, 1);
  478. }
  479. // now double quote the path if it has spaces in it
  480. // and is not already double quoted
  481. if(ret.find(" ") != std::string::npos
  482. && ret[0] != '\"')
  483. {
  484. std::string result;
  485. result = "\"" + ret + "\"";
  486. ret = result;
  487. }
  488. return ret;
  489. }
  490. bool cmSystemTools::ParseFunction(std::ifstream& fin,
  491. std::string& name,
  492. std::vector<std::string>& arguments,
  493. const char* filename,
  494. bool& parseError)
  495. {
  496. parseError = false;
  497. name = "";
  498. arguments = std::vector<std::string>();
  499. const int BUFFER_SIZE = 4096;
  500. char inbuffer[BUFFER_SIZE];
  501. if(!fin)
  502. {
  503. return false;
  504. }
  505. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  506. {
  507. cmRegularExpression blankLine("^[ \t\r]*$");
  508. cmRegularExpression comment("^[ \t]*#.*$");
  509. cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
  510. cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
  511. cmRegularExpression lastLine("^(.*)\\)[ \t\r]*$");
  512. // check for black line or comment
  513. if(blankLine.find(inbuffer) || comment.find(inbuffer))
  514. {
  515. return false;
  516. }
  517. // look for a oneline fun(arg arg2)
  518. else if(oneLiner.find(inbuffer))
  519. {
  520. // the arguments are the second match
  521. std::string args = oneLiner.match(2);
  522. name = oneLiner.match(1);
  523. // break up the arguments
  524. cmSystemTools::GetArguments(args, arguments);
  525. return true;
  526. }
  527. // look for a start of a multiline with no trailing ")" fun(arg arg2
  528. else if(multiLine.find(inbuffer))
  529. {
  530. name = multiLine.match(1);
  531. std::string args = multiLine.match(2);
  532. cmSystemTools::GetArguments(args, arguments);
  533. // Read lines until the closing paren is hit
  534. bool done = false;
  535. while(!done)
  536. {
  537. // read lines until the end paren is found
  538. if(fin.getline(inbuffer, BUFFER_SIZE ) )
  539. {
  540. // Check for comment lines and ignore them.
  541. if(blankLine.find(inbuffer) || comment.find(inbuffer))
  542. { continue; }
  543. // Is this the last line?
  544. if(lastLine.find(inbuffer))
  545. {
  546. done = true;
  547. std::string args = lastLine.match(1);
  548. cmSystemTools::GetArguments(args, arguments);
  549. }
  550. else
  551. {
  552. std::string line = inbuffer;
  553. cmSystemTools::GetArguments(line, arguments);
  554. }
  555. }
  556. else
  557. {
  558. parseError = true;
  559. cmSystemTools::Error("Parse error in read function missing end )\nIn File: ",
  560. filename, "\nCurrent line:", inbuffer);
  561. return false;
  562. }
  563. }
  564. return true;
  565. }
  566. else
  567. {
  568. parseError = true;
  569. cmSystemTools::Error("Parse error in read function\nIn file:",
  570. filename, "\nCurrent line:", inbuffer);
  571. return false;
  572. }
  573. }
  574. return false;
  575. }
  576. void cmSystemTools::GetArguments(std::string& line,
  577. std::vector<std::string>& arguments)
  578. {
  579. // Match a normal argument (not quoted, no spaces).
  580. cmRegularExpression normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*");
  581. // Match a quoted argument (surrounded by double quotes, spaces allowed).
  582. cmRegularExpression quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*");
  583. bool done = false;
  584. while(!done)
  585. {
  586. std::string arg;
  587. std::string::size_type endpos;
  588. bool foundQuoted = quotedArgument.find(line.c_str());
  589. bool foundNormal = normalArgument.find(line.c_str());
  590. if(foundQuoted && foundNormal)
  591. {
  592. // Both matches were found. Take the earlier one.
  593. // Favor double-quoted version if there is a tie.
  594. if(normalArgument.start(1) < quotedArgument.start(1))
  595. {
  596. arg = normalArgument.match(1);
  597. endpos = normalArgument.end(1);
  598. }
  599. else
  600. {
  601. arg = quotedArgument.match(1);
  602. endpos = quotedArgument.end(1);
  603. // Strip off the double quotes on the ends.
  604. arg = arg.substr(1, arg.length()-2);
  605. }
  606. }
  607. else if (foundQuoted)
  608. {
  609. arg = quotedArgument.match(1);
  610. endpos = quotedArgument.end(1);
  611. // Strip off the double quotes on the ends.
  612. arg = arg.substr(1, arg.length()-2);
  613. }
  614. else if(foundNormal)
  615. {
  616. arg = normalArgument.match(1);
  617. endpos = normalArgument.end(1);
  618. }
  619. else
  620. {
  621. done = true;
  622. }
  623. if(!done)
  624. {
  625. arguments.push_back(cmSystemTools::RemoveEscapes(arg.c_str()));
  626. line = line.substr(endpos, line.length() - endpos);
  627. }
  628. }
  629. }
  630. std::string cmSystemTools::RemoveEscapes(const char* s)
  631. {
  632. std::string result = "";
  633. for(const char* ch = s; *ch; ++ch)
  634. {
  635. if(*ch == '\\')
  636. {
  637. ++ch;
  638. switch (*ch)
  639. {
  640. case '\\': result.insert(result.end(), '\\'); break;
  641. case '"': result.insert(result.end(), '"'); break;
  642. case ' ': result.insert(result.end(), ' '); break;
  643. case 't': result.insert(result.end(), '\t'); break;
  644. case 'n': result.insert(result.end(), '\n'); break;
  645. case 'r': result.insert(result.end(), '\r'); break;
  646. case '0': result.insert(result.end(), '\0'); break;
  647. case '\0':
  648. {
  649. cmSystemTools::Error("Trailing backslash in argument:\n", s);
  650. return result;
  651. }
  652. default:
  653. {
  654. std::string chStr(1, *ch);
  655. cmSystemTools::Error("Invalid escape sequence \\", chStr.c_str(),
  656. "\nin argument ", s);
  657. }
  658. }
  659. }
  660. else
  661. {
  662. result.insert(result.end(), *ch);
  663. }
  664. }
  665. return result;
  666. }
  667. void cmSystemTools::Error(const char* m1, const char* m2,
  668. const char* m3, const char* m4)
  669. {
  670. std::string message = "CMake Error: ";
  671. if(m1)
  672. {
  673. message += m1;
  674. }
  675. if(m2)
  676. {
  677. message += m2;
  678. }
  679. if(m3)
  680. {
  681. message += m3;
  682. }
  683. if(m4)
  684. {
  685. message += m4;
  686. }
  687. cmSystemTools::s_ErrorOccured = true;
  688. cmSystemTools::Message(message.c_str(),"Error");
  689. }
  690. void cmSystemTools::SetErrorCallback(ErrorCallback f)
  691. {
  692. s_ErrorCallback = f;
  693. }
  694. void cmSystemTools::Message(const char* m1, const char *title)
  695. {
  696. if(s_DisableMessages)
  697. {
  698. return;
  699. }
  700. if(s_ErrorCallback)
  701. {
  702. (*s_ErrorCallback)(m1, title, s_DisableMessages);
  703. return;
  704. }
  705. else
  706. {
  707. std::cerr << m1 << std::endl;
  708. }
  709. }
  710. bool cmSystemTools::CopyFileIfDifferent(const char* source,
  711. const char* destination)
  712. {
  713. if(cmSystemTools::FilesDiffer(source, destination))
  714. {
  715. cmSystemTools::cmCopyFile(source, destination);
  716. return true;
  717. }
  718. return false;
  719. }
  720. bool cmSystemTools::FilesDiffer(const char* source,
  721. const char* destination)
  722. {
  723. struct stat statSource;
  724. if (stat(source, &statSource) != 0)
  725. {
  726. return true;
  727. }
  728. struct stat statDestination;
  729. if (stat(destination, &statDestination) != 0)
  730. {
  731. return true;
  732. }
  733. if(statSource.st_size != statDestination.st_size)
  734. {
  735. return true;
  736. }
  737. std::ifstream finSource(source);
  738. std::ifstream finDestination(destination);
  739. if(!finSource || !finDestination)
  740. {
  741. return true;
  742. }
  743. const int buffer_length = 4096;
  744. char bufferSource[buffer_length];
  745. char bufferDest[buffer_length];
  746. while(finSource && finDestination)
  747. {
  748. if(finSource.getline(bufferSource, buffer_length, '\n')
  749. || finSource.gcount())
  750. {
  751. if(finDestination.getline(bufferDest, buffer_length, '\n')
  752. || finDestination.gcount())
  753. {
  754. // both if statements passed
  755. if(finSource.eof())
  756. {
  757. if(!finDestination.eof())
  758. {
  759. return true;
  760. }
  761. if(finSource.gcount() != finDestination.gcount())
  762. {
  763. return true;
  764. }
  765. if(strncmp(bufferSource, bufferDest, finSource.gcount()) != 0)
  766. {
  767. return true;
  768. }
  769. }
  770. else if(finSource.fail())
  771. {
  772. if(!finDestination.fail())
  773. {
  774. return true;
  775. }
  776. if(strcmp(bufferSource, bufferDest) != 0)
  777. {
  778. return true;
  779. }
  780. finSource.clear(finSource.rdstate() & ~std::ios::failbit);
  781. finDestination.clear(finDestination.rdstate() & ~std::ios::failbit);
  782. }
  783. else
  784. {
  785. if(strcmp(bufferSource, bufferDest) != 0)
  786. {
  787. return true;
  788. }
  789. }
  790. }
  791. else
  792. {
  793. return true;
  794. }
  795. }
  796. }
  797. return false;
  798. }
  799. /**
  800. * Copy a file named by "source" to the file named by "destination".
  801. */
  802. void cmSystemTools::cmCopyFile(const char* source,
  803. const char* destination)
  804. {
  805. const int bufferSize = 4096;
  806. char buffer[bufferSize];
  807. std::ifstream fin(source,
  808. #ifdef _WIN32
  809. std::ios::binary |
  810. #endif
  811. std::ios::in);
  812. if(!fin)
  813. {
  814. cmSystemTools::Error("CopyFile failed to open input file \"",
  815. source, "\"");
  816. return;
  817. }
  818. std::ofstream fout(destination,
  819. #ifdef _WIN32
  820. std::ios::binary |
  821. #endif
  822. std::ios::out | std::ios::trunc);
  823. if(!fout)
  824. {
  825. cmSystemTools::Error("CopyFile failed to open output file \"",
  826. destination, "\"");
  827. return;
  828. }
  829. // This copy loop is very sensitive on certain platforms with
  830. // slightly broken stream libraries (like HPUX). Normally, it is
  831. // incorrect to not check the error condition on the fin.read()
  832. // before using the data, but the fin.gcount() will be zero if an
  833. // error occurred. Therefore, the loop should be safe everywhere.
  834. while(fin)
  835. {
  836. fin.read(buffer, bufferSize);
  837. if(fin.gcount())
  838. {
  839. fout.write(buffer, fin.gcount());
  840. }
  841. }
  842. }
  843. // return true if the file exists
  844. long int cmSystemTools::ModifiedTime(const char* filename)
  845. {
  846. struct stat fs;
  847. if (stat(filename, &fs) != 0)
  848. {
  849. return 0;
  850. }
  851. else
  852. {
  853. return (long int)fs.st_mtime;
  854. }
  855. }
  856. bool cmSystemTools::RemoveFile(const char* source)
  857. {
  858. return unlink(source) != 0 ? false : true;
  859. }
  860. bool cmSystemTools::IsOn(const char* val)
  861. {
  862. if (!val)
  863. {
  864. return false;
  865. }
  866. std::basic_string<char> v = val;
  867. for(std::basic_string<char>::iterator c = v.begin();
  868. c != v.end(); c++)
  869. {
  870. *c = toupper(*c);
  871. }
  872. return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
  873. }
  874. bool cmSystemTools::IsOff(const char* val)
  875. {
  876. if (!val || strlen(val) == 0)
  877. {
  878. return true;
  879. }
  880. std::basic_string<char> v = val;
  881. for(std::basic_string<char>::iterator c = v.begin();
  882. c != v.end(); c++)
  883. {
  884. *c = toupper(*c);
  885. }
  886. return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
  887. v == "N" || v == "NOTFOUND" || v == "IGNORE");
  888. }
  889. bool cmSystemTools::RunCommand(const char* command,
  890. std::string& output,
  891. const char* dir,
  892. bool verbose)
  893. {
  894. int foo;
  895. return cmSystemTools::RunCommand(command, output, foo, dir, verbose);
  896. }
  897. #if defined(WIN32) && !defined(__CYGWIN__)
  898. // use this for shell commands like echo and dir
  899. bool RunCommandViaSystem(const char* command,
  900. const char* dir,
  901. std::string& output,
  902. int& retVal,
  903. bool verbose)
  904. {
  905. const int BUFFER_SIZE = 4096;
  906. char buffer[BUFFER_SIZE];
  907. std::string commandInDir;
  908. if(dir)
  909. {
  910. commandInDir = "cd ";
  911. commandInDir += dir;
  912. commandInDir += " && ";
  913. commandInDir += command;
  914. }
  915. else
  916. {
  917. commandInDir = command;
  918. }
  919. command = commandInDir.c_str();
  920. std::string commandToFile = command;
  921. commandToFile += " > ";
  922. std::string tempFile;
  923. tempFile += _tempnam(0, "cmake");
  924. commandToFile += tempFile;
  925. retVal = system(commandToFile.c_str());
  926. std::ifstream fin(tempFile.c_str());
  927. if(!fin)
  928. {
  929. if(verbose)
  930. {
  931. std::string errormsg = "RunCommand produced no output: command: \"";
  932. errormsg += command;
  933. errormsg += "\"";
  934. errormsg += "\nOutput file: ";
  935. errormsg += tempFile;
  936. cmSystemTools::Error(errormsg.c_str());
  937. }
  938. fin.close();
  939. cmSystemTools::RemoveFile(tempFile.c_str());
  940. return false;
  941. }
  942. while(fin)
  943. {
  944. fin.getline(buffer, BUFFER_SIZE);
  945. output += buffer;
  946. }
  947. fin.close();
  948. cmSystemTools::RemoveFile(tempFile.c_str());
  949. return true;
  950. }
  951. #endif // endif WIN32 not CYGWIN
  952. // run a command unix uses popen (easy)
  953. // windows uses system and ShortPath
  954. bool cmSystemTools::RunCommand(const char* command,
  955. std::string& output,
  956. int &retVal,
  957. const char* dir,
  958. bool verbose)
  959. {
  960. if(s_DisableRunCommandOutput)
  961. {
  962. verbose = false;
  963. }
  964. #if defined(WIN32) && !defined(__CYGWIN__)
  965. // if the command does not start with a quote, then
  966. // try to find the program, and if the program can not be
  967. // found use system to run the command as it must be a built in
  968. // shell command like echo or dir
  969. int count = 0;
  970. if(command[0] == '\"')
  971. {
  972. // count the number of quotes
  973. for(const char* s = command; *s != 0; ++s)
  974. {
  975. if(*s == '\"')
  976. {
  977. count++;
  978. if(count > 2)
  979. {
  980. break;
  981. }
  982. }
  983. }
  984. // if there are more than two double quotes use
  985. // GetShortPathName, the cmd.exe program in windows which
  986. // is used by system fails to execute if there are more than
  987. // one set of quotes in the arguments
  988. if(count > 2)
  989. {
  990. cmRegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
  991. if(quoted.find(command))
  992. {
  993. std::string shortCmd;
  994. std::string cmd = quoted.match(1);
  995. std::string args = quoted.match(2);
  996. char *buffer = new char[cmd.size()+1];
  997. if(GetShortPathName(cmd.c_str(), buffer,
  998. int(cmd.size())) != 0)
  999. {
  1000. shortCmd = buffer;
  1001. shortCmd += " ";
  1002. shortCmd += args;
  1003. }
  1004. else
  1005. {
  1006. cmSystemTools::Error("Could not get GetShortPathName for ",
  1007. cmd.c_str());
  1008. return false;
  1009. }
  1010. return RunCommandViaSystem(shortCmd.c_str(), dir,
  1011. output, retVal, verbose);
  1012. }
  1013. else
  1014. {
  1015. cmSystemTools::Error("Could not parse command line with quotes ",
  1016. command);
  1017. }
  1018. }
  1019. }
  1020. // if there is only one set of quotes or no quotes then just run the command
  1021. return RunCommandViaSystem(command, dir, output, retVal, verbose);
  1022. #else
  1023. // if only popen worked on windows.....
  1024. std::string commandInDir;
  1025. if(dir)
  1026. {
  1027. commandInDir = "cd ";
  1028. commandInDir += dir;
  1029. commandInDir += " && ";
  1030. commandInDir += command;
  1031. }
  1032. else
  1033. {
  1034. commandInDir = command;
  1035. }
  1036. command = commandInDir.c_str();
  1037. const int BUFFER_SIZE = 4096;
  1038. char buffer[BUFFER_SIZE];
  1039. if(verbose)
  1040. {
  1041. std::cout << "running " << command << std::endl;
  1042. }
  1043. fflush(stdout);
  1044. fflush(stderr);
  1045. FILE* cpipe = popen(command, "r");
  1046. if(!cpipe)
  1047. {
  1048. return false;
  1049. }
  1050. fgets(buffer, BUFFER_SIZE, cpipe);
  1051. while(!feof(cpipe))
  1052. {
  1053. if(verbose)
  1054. {
  1055. std::cout << buffer << std::flush;
  1056. }
  1057. output += buffer;
  1058. fgets(buffer, BUFFER_SIZE, cpipe);
  1059. }
  1060. retVal = pclose(cpipe);
  1061. retVal = WEXITSTATUS(retVal);
  1062. return true;
  1063. #endif
  1064. }
  1065. /**
  1066. * Find the file the given name. Searches the given path and then
  1067. * the system search path. Returns the full path to the file if it is
  1068. * found. Otherwise, the empty string is returned.
  1069. */
  1070. std::string cmSystemTools::FindFile(const char* name,
  1071. const std::vector<std::string>& userPaths)
  1072. {
  1073. // Add the system search path to our path.
  1074. std::vector<std::string> path = userPaths;
  1075. cmSystemTools::GetPath(path);
  1076. std::string tryPath;
  1077. for(std::vector<std::string>::const_iterator p = path.begin();
  1078. p != path.end(); ++p)
  1079. {
  1080. tryPath = *p;
  1081. tryPath += "/";
  1082. tryPath += name;
  1083. if(cmSystemTools::FileExists(tryPath.c_str()) &&
  1084. !cmSystemTools::FileIsDirectory(tryPath.c_str()))
  1085. {
  1086. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1087. }
  1088. }
  1089. // Couldn't find the file.
  1090. return "";
  1091. }
  1092. /**
  1093. * Find the executable with the given name. Searches the given path and then
  1094. * the system search path. Returns the full path to the executable if it is
  1095. * found. Otherwise, the empty string is returned.
  1096. */
  1097. std::string cmSystemTools::FindProgram(const char* name,
  1098. const std::vector<std::string>& userPaths)
  1099. {
  1100. // See if the executable exists as written.
  1101. if(cmSystemTools::FileExists(name) &&
  1102. !cmSystemTools::FileIsDirectory(name))
  1103. {
  1104. return cmSystemTools::CollapseFullPath(name);
  1105. }
  1106. std::string tryPath = name;
  1107. tryPath += cmSystemTools::GetExecutableExtension();
  1108. if(cmSystemTools::FileExists(tryPath.c_str()) &&
  1109. !cmSystemTools::FileIsDirectory(tryPath.c_str()))
  1110. {
  1111. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1112. }
  1113. // Add the system search path to our path.
  1114. std::vector<std::string> path = userPaths;
  1115. cmSystemTools::GetPath(path);
  1116. for(std::vector<std::string>::const_iterator p = path.begin();
  1117. p != path.end(); ++p)
  1118. {
  1119. tryPath = *p;
  1120. tryPath += "/";
  1121. tryPath += name;
  1122. if(cmSystemTools::FileExists(tryPath.c_str()) &&
  1123. !cmSystemTools::FileIsDirectory(tryPath.c_str()))
  1124. {
  1125. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1126. }
  1127. #ifdef _WIN32
  1128. tryPath += ".com";
  1129. if(cmSystemTools::FileExists(tryPath.c_str()) &&
  1130. !cmSystemTools::FileIsDirectory(tryPath.c_str()))
  1131. {
  1132. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1133. }
  1134. tryPath = *p;
  1135. tryPath += "/";
  1136. tryPath += name;
  1137. #endif
  1138. tryPath += cmSystemTools::GetExecutableExtension();
  1139. if(cmSystemTools::FileExists(tryPath.c_str()) &&
  1140. !cmSystemTools::FileIsDirectory(tryPath.c_str()))
  1141. {
  1142. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1143. }
  1144. }
  1145. // Couldn't find the program.
  1146. return "";
  1147. }
  1148. /**
  1149. * Find the library with the given name. Searches the given path and then
  1150. * the system search path. Returns the full path to the library if it is
  1151. * found. Otherwise, the empty string is returned.
  1152. */
  1153. std::string cmSystemTools::FindLibrary(const char* name,
  1154. const std::vector<std::string>& userPaths)
  1155. {
  1156. // See if the executable exists as written.
  1157. if(cmSystemTools::FileExists(name))
  1158. {
  1159. return cmSystemTools::CollapseFullPath(name);
  1160. }
  1161. // Add the system search path to our path.
  1162. std::vector<std::string> path = userPaths;
  1163. cmSystemTools::GetPath(path);
  1164. std::string tryPath;
  1165. for(std::vector<std::string>::const_iterator p = path.begin();
  1166. p != path.end(); ++p)
  1167. {
  1168. #if defined(_WIN32) && !defined(__CYGWIN__)
  1169. tryPath = *p;
  1170. tryPath += "/";
  1171. tryPath += name;
  1172. tryPath += ".lib";
  1173. if(cmSystemTools::FileExists(tryPath.c_str()))
  1174. {
  1175. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1176. }
  1177. #else
  1178. tryPath = *p;
  1179. tryPath += "/lib";
  1180. tryPath += name;
  1181. tryPath += ".so";
  1182. if(cmSystemTools::FileExists(tryPath.c_str()))
  1183. {
  1184. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1185. }
  1186. tryPath = *p;
  1187. tryPath += "/lib";
  1188. tryPath += name;
  1189. tryPath += ".a";
  1190. if(cmSystemTools::FileExists(tryPath.c_str()))
  1191. {
  1192. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1193. }
  1194. tryPath = *p;
  1195. tryPath += "/lib";
  1196. tryPath += name;
  1197. tryPath += ".sl";
  1198. if(cmSystemTools::FileExists(tryPath.c_str()))
  1199. {
  1200. return cmSystemTools::CollapseFullPath(tryPath.c_str());
  1201. }
  1202. #endif
  1203. }
  1204. // Couldn't find the library.
  1205. return "";
  1206. }
  1207. bool cmSystemTools::FileIsDirectory(const char* name)
  1208. {
  1209. struct stat fs;
  1210. if(stat(name, &fs) == 0)
  1211. {
  1212. #if _WIN32
  1213. return ((fs.st_mode & _S_IFDIR) != 0);
  1214. #else
  1215. return S_ISDIR(fs.st_mode);
  1216. #endif
  1217. }
  1218. else
  1219. {
  1220. return false;
  1221. }
  1222. }
  1223. int cmSystemTools::ChangeDirectory(const char *dir)
  1224. {
  1225. return Chdir(dir);
  1226. }
  1227. std::string cmSystemTools::GetCurrentWorkingDirectory()
  1228. {
  1229. char buf[2048];
  1230. std::string path = Getcwd(buf, 2048);
  1231. return path;
  1232. }
  1233. /**
  1234. * Given the path to a program executable, get the directory part of the path with the
  1235. * file stripped off. If there is no directory part, the empty string is returned.
  1236. */
  1237. std::string cmSystemTools::GetProgramPath(const char* in_name)
  1238. {
  1239. std::string dir, file;
  1240. cmSystemTools::SplitProgramPath(in_name, dir, file);
  1241. return dir;
  1242. }
  1243. /**
  1244. * Given the path to a program executable, get the directory part of the path
  1245. * with the file stripped off. If there is no directory part, the empty
  1246. * string is returned.
  1247. */
  1248. void cmSystemTools::SplitProgramPath(const char* in_name,
  1249. std::string& dir,
  1250. std::string& file)
  1251. {
  1252. dir = in_name;
  1253. file = "";
  1254. cmSystemTools::ConvertToUnixSlashes(dir);
  1255. if(!cmSystemTools::FileIsDirectory(dir.c_str()))
  1256. {
  1257. std::string::size_type slashPos = dir.rfind("/");
  1258. if(slashPos != std::string::npos)
  1259. {
  1260. file = dir.substr(slashPos+1);
  1261. dir = dir.substr(0, slashPos);
  1262. }
  1263. else
  1264. {
  1265. file = dir;
  1266. dir = "";
  1267. }
  1268. }
  1269. if((dir != "") && !cmSystemTools::FileIsDirectory(dir.c_str()))
  1270. {
  1271. std::string oldDir = in_name;
  1272. cmSystemTools::ConvertToUnixSlashes(oldDir);
  1273. cmSystemTools::Error("Error splitting file name off end of path:\n",
  1274. oldDir.c_str(), "\nDirectory not found: ",
  1275. dir.c_str());
  1276. dir = in_name;
  1277. return;
  1278. }
  1279. }
  1280. /**
  1281. * Given a path to a file or directory, convert it to a full path.
  1282. * This collapses away relative paths. The full path is returned.
  1283. */
  1284. std::string cmSystemTools::CollapseFullPath(const char* in_name)
  1285. {
  1286. std::string dir, file;
  1287. cmSystemTools::SplitProgramPath(in_name, dir, file);
  1288. #ifdef _WIN32
  1289. // Ultra-hack warning:
  1290. // This changes to the target directory, saves the working directory,
  1291. // and then changes back to the original working directory.
  1292. std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  1293. if(dir != "") { Chdir(dir.c_str()); }
  1294. std::string newDir = cmSystemTools::GetCurrentWorkingDirectory();
  1295. Chdir(cwd.c_str());
  1296. cmSystemTools::ConvertToUnixSlashes(newDir);
  1297. std::string newPath = newDir+"/"+file;
  1298. return newPath;
  1299. #else
  1300. # ifdef MAXPATHLEN
  1301. char resolved_name[MAXPATHLEN];
  1302. # else
  1303. # ifdef PATH_MAX
  1304. char resolved_name[PATH_MAX];
  1305. # else
  1306. char resolved_name[5024];
  1307. # endif
  1308. # endif
  1309. if(dir != "")
  1310. {
  1311. realpath(dir.c_str(), resolved_name);
  1312. dir = resolved_name;
  1313. }
  1314. else
  1315. {
  1316. dir = cmSystemTools::GetCurrentWorkingDirectory();
  1317. }
  1318. if(file == "")
  1319. {
  1320. return dir;
  1321. }
  1322. return dir + "/" + file;
  1323. #endif
  1324. }
  1325. /**
  1326. * Return path of a full filename (no trailing slashes).
  1327. * Warning: returned path is converted to Unix slashes format.
  1328. */
  1329. std::string cmSystemTools::GetFilenamePath(const std::string& filename)
  1330. {
  1331. std::string fn = filename;
  1332. cmSystemTools::ConvertToUnixSlashes(fn);
  1333. std::string::size_type slash_pos = fn.rfind("/");
  1334. if(slash_pos != std::string::npos)
  1335. {
  1336. return fn.substr(0, slash_pos);
  1337. }
  1338. else
  1339. {
  1340. return "";
  1341. }
  1342. }
  1343. /**
  1344. * Return file name of a full filename (i.e. file name without path).
  1345. */
  1346. std::string cmSystemTools::GetFilenameName(const std::string& filename)
  1347. {
  1348. std::string fn = filename;
  1349. cmSystemTools::ConvertToUnixSlashes(fn);
  1350. std::string::size_type slash_pos = fn.rfind("/");
  1351. if(slash_pos != std::string::npos)
  1352. {
  1353. return fn.substr(slash_pos + 1);
  1354. }
  1355. else
  1356. {
  1357. return filename;
  1358. }
  1359. }
  1360. /**
  1361. * Return file extension of a full filename (dot included).
  1362. * Warning: this is the longest extension (for example: .tar.gz)
  1363. */
  1364. std::string cmSystemTools::GetFilenameExtension(const std::string& filename)
  1365. {
  1366. std::string name = cmSystemTools::GetFilenameName(filename);
  1367. std::string::size_type dot_pos = name.find(".");
  1368. if(dot_pos != std::string::npos)
  1369. {
  1370. return name.substr(dot_pos);
  1371. }
  1372. else
  1373. {
  1374. return "";
  1375. }
  1376. }
  1377. /**
  1378. * Return file extension of a full filename (dot included).
  1379. */
  1380. std::string cmSystemTools::GetFilenameShortestExtension(const std::string& filename)
  1381. {
  1382. std::string name = cmSystemTools::GetFilenameName(filename);
  1383. std::string::size_type dot_pos = name.rfind(".");
  1384. if(dot_pos != std::string::npos)
  1385. {
  1386. return name.substr(dot_pos);
  1387. }
  1388. else
  1389. {
  1390. return "";
  1391. }
  1392. }
  1393. /**
  1394. * Return file name without extension of a full filename (i.e. without path).
  1395. * Warning: it considers the longest extension (for example: .tar.gz)
  1396. */
  1397. std::string cmSystemTools::GetFilenameNameWithoutExtension(const std::string& filename)
  1398. {
  1399. std::string name = cmSystemTools::GetFilenameName(filename);
  1400. std::string::size_type dot_pos = name.find(".");
  1401. if(dot_pos != std::string::npos)
  1402. {
  1403. return name.substr(0, dot_pos);
  1404. }
  1405. else
  1406. {
  1407. return name;
  1408. }
  1409. }
  1410. void cmSystemTools::Glob(const char *directory, const char *regexp,
  1411. std::vector<std::string>& files)
  1412. {
  1413. cmDirectory d;
  1414. cmRegularExpression reg(regexp);
  1415. if (d.Load(directory))
  1416. {
  1417. size_t numf;
  1418. unsigned int i;
  1419. numf = d.GetNumberOfFiles();
  1420. for (i = 0; i < numf; i++)
  1421. {
  1422. std::string fname = d.GetFile(i);
  1423. if (reg.find(fname))
  1424. {
  1425. files.push_back(fname);
  1426. }
  1427. }
  1428. }
  1429. }
  1430. void cmSystemTools::GlobDirs(const char *fullPath,
  1431. std::vector<std::string>& files)
  1432. {
  1433. std::string path = fullPath;
  1434. std::string::size_type pos = path.find("/*");
  1435. if(pos == std::string::npos)
  1436. {
  1437. files.push_back(fullPath);
  1438. return;
  1439. }
  1440. std::string startPath = path.substr(0, pos);
  1441. std::string finishPath = path.substr(pos+2);
  1442. cmDirectory d;
  1443. if (d.Load(startPath.c_str()))
  1444. {
  1445. for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
  1446. {
  1447. if((std::string(d.GetFile(i)) != ".")
  1448. && (std::string(d.GetFile(i)) != ".."))
  1449. {
  1450. std::string fname = startPath;
  1451. fname +="/";
  1452. fname += d.GetFile(i);
  1453. if(cmSystemTools::FileIsDirectory(fname.c_str()))
  1454. {
  1455. fname += finishPath;
  1456. cmSystemTools::GlobDirs(fname.c_str(), files);
  1457. }
  1458. }
  1459. }
  1460. }
  1461. }
  1462. void cmSystemTools::ExpandListArguments(std::vector<std::string> const& arguments,
  1463. std::vector<std::string>& newargs)
  1464. {
  1465. std::vector<std::string>::const_iterator i;
  1466. for(i = arguments.begin();i != arguments.end(); ++i)
  1467. {
  1468. if(i->find(';') != std::string::npos)
  1469. {
  1470. std::string::size_type start = 0;
  1471. std::string::size_type endpos = 0;
  1472. while(endpos != std::string::npos)
  1473. {
  1474. endpos = i->find(';', start);
  1475. std::string::size_type len;
  1476. if(endpos != std::string::npos)
  1477. {
  1478. len = endpos - start;
  1479. }
  1480. else
  1481. {
  1482. len = i->size()-start;
  1483. }
  1484. newargs.push_back(i->substr(start, len));
  1485. start = endpos+1;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. newargs.push_back(*i);
  1491. }
  1492. }
  1493. }