cmGlob.cxx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html 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 "cmGlob.h"
  14. #include <cmsys/Directory.hxx>
  15. #include <cmsys/RegularExpression.hxx>
  16. #include <cmsys/SystemTools.hxx>
  17. #include <stdio.h>
  18. class cmGlobInternal
  19. {
  20. public:
  21. std::vector<std::string> Files;
  22. std::vector<cmsys::RegularExpression> Expressions;
  23. };
  24. cmGlob::cmGlob()
  25. {
  26. m_Internals = new cmGlobInternal;
  27. m_Recurse = false;
  28. }
  29. cmGlob::~cmGlob()
  30. {
  31. delete m_Internals;
  32. }
  33. void cmGlob::Escape(int ch, char* buffer)
  34. {
  35. if (! (
  36. 'a' <= ch && ch <= 'z' ||
  37. 'A' <= ch && ch <= 'Z' ||
  38. '0' <= ch && ch <= '9') )
  39. {
  40. sprintf(buffer, "\\%c", ch);
  41. }
  42. else
  43. {
  44. sprintf(buffer, "%c", ch);
  45. }
  46. }
  47. std::vector<std::string>& cmGlob::GetFiles()
  48. {
  49. return m_Internals->Files;
  50. }
  51. std::string cmGlob::ConvertExpression(const std::string& expr)
  52. {
  53. std::string::size_type i = 0;
  54. std::string::size_type n = expr.size();
  55. std::string res = "^";
  56. std::string stuff = "";
  57. while ( i < n )
  58. {
  59. int c = expr[i];
  60. i = i+1;
  61. if ( c == '*' )
  62. {
  63. res = res + ".*";
  64. }
  65. else if ( c == '?' )
  66. {
  67. res = res + ".";
  68. }
  69. else if ( c == '[' )
  70. {
  71. std::string::size_type j = i;
  72. if ( j < n && expr[j] == '!' )
  73. {
  74. j = j+1;
  75. }
  76. if ( j < n && expr[j] == ']' )
  77. {
  78. j = j+1;
  79. }
  80. while ( j < n && expr[j] != ']' )
  81. {
  82. j = j+1;
  83. }
  84. if ( j >= n )
  85. {
  86. res = res + "\\[";
  87. }
  88. else
  89. {
  90. stuff = "";
  91. std::string::size_type cc;
  92. for ( cc = i; cc < j; cc ++ )
  93. {
  94. if ( expr[cc] == '\\' )
  95. {
  96. stuff += "\\\\";
  97. }
  98. else
  99. {
  100. stuff += expr[cc];
  101. }
  102. }
  103. i = j+1;
  104. if ( stuff[0] == '!' )
  105. {
  106. stuff = '^' + stuff.substr(1);
  107. }
  108. else if ( stuff[0] == '^' )
  109. {
  110. stuff = '\\' + stuff;
  111. }
  112. res = res + "[" + stuff + "]";
  113. }
  114. }
  115. else
  116. {
  117. char buffer[100];
  118. buffer[0] = 0;
  119. this->Escape(c, buffer);
  120. res = res + buffer;
  121. }
  122. }
  123. return res + "$";
  124. }
  125. void cmGlob::RecurseDirectory(const std::string& dir, bool dir_only)
  126. {
  127. cmsys::Directory d;
  128. if ( !d.Load(dir.c_str()) )
  129. {
  130. return;
  131. }
  132. unsigned long cc;
  133. std::string fullname;
  134. for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
  135. {
  136. if ( strcmp(d.GetFile(cc), ".") == 0 ||
  137. strcmp(d.GetFile(cc), "..") == 0 )
  138. {
  139. continue;
  140. }
  141. fullname = dir + "/" + d.GetFile(cc);
  142. if ( !dir_only || !cmsys::SystemTools::FileIsDirectory(fullname.c_str()) )
  143. {
  144. if ( m_Internals->Expressions[m_Internals->Expressions.size()-1].find(d.GetFile(cc)) )
  145. {
  146. m_Internals->Files.push_back(fullname);
  147. }
  148. }
  149. if ( cmsys::SystemTools::FileIsDirectory(fullname.c_str()) )
  150. {
  151. this->RecurseDirectory(fullname, dir_only);
  152. }
  153. }
  154. }
  155. void cmGlob::ProcessDirectory(std::string::size_type start,
  156. const std::string& dir, bool dir_only)
  157. {
  158. bool last = ( start == m_Internals->Expressions.size()-1 );
  159. if ( last && m_Recurse )
  160. {
  161. this->RecurseDirectory(dir, dir_only);
  162. return;
  163. }
  164. cmsys::Directory d;
  165. if ( !d.Load(dir.c_str()) )
  166. {
  167. return;
  168. }
  169. unsigned long cc;
  170. std::string fullname;
  171. for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
  172. {
  173. if ( strcmp(d.GetFile(cc), ".") == 0 ||
  174. strcmp(d.GetFile(cc), "..") == 0 )
  175. {
  176. continue;
  177. }
  178. if ( start == 0 )
  179. {
  180. fullname = dir + d.GetFile(cc);
  181. }
  182. else
  183. {
  184. fullname = dir + "/" + d.GetFile(cc);
  185. }
  186. if ( (!dir_only || !last) && !cmsys::SystemTools::FileIsDirectory(fullname.c_str()) )
  187. {
  188. continue;
  189. }
  190. if ( m_Internals->Expressions[start].find(d.GetFile(cc)) )
  191. {
  192. if ( last )
  193. {
  194. m_Internals->Files.push_back(fullname);
  195. }
  196. else
  197. {
  198. this->ProcessDirectory(start+1, fullname, dir_only);
  199. }
  200. }
  201. }
  202. }
  203. bool cmGlob::FindFiles(const std::string& inexpr)
  204. {
  205. std::string cexpr;
  206. std::string::size_type cc;
  207. std::string expr = inexpr;
  208. m_Internals->Expressions.empty();
  209. m_Internals->Files.empty();
  210. if ( !cmsys::SystemTools::FileIsFullPath(expr.c_str()) )
  211. {
  212. expr = cmsys::SystemTools::GetCurrentWorkingDirectory();
  213. expr += "/" + inexpr;
  214. }
  215. for ( cc = 0; cc < expr.size(); cc ++ )
  216. {
  217. int ch = expr[cc];
  218. if ( ch == '/' )
  219. {
  220. if ( cexpr.size() > 0 )
  221. {
  222. this->AddExpression(cexpr.c_str());
  223. }
  224. cexpr = "";
  225. }
  226. else
  227. {
  228. cexpr.append(1, (char)ch);
  229. }
  230. }
  231. if ( cexpr.size() > 0 )
  232. {
  233. this->AddExpression(cexpr.c_str());
  234. }
  235. this->ProcessDirectory(0, "/", true);
  236. return true;
  237. }
  238. void cmGlob::AddExpression(const char* expr)
  239. {
  240. m_Internals->Expressions.push_back(
  241. cmsys::RegularExpression(
  242. this->ConvertExpression(expr).c_str()));
  243. }