ppDirectoryTree.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Filename: ppDirectoryTree.cxx
  2. // Created by: drose (28Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppDirectoryTree.h"
  6. #include "ppDirectory.h"
  7. #include "ppDependableFile.h"
  8. #include "tokenize.h"
  9. #include <algorithm>
  10. ////////////////////////////////////////////////////////////////////
  11. // Function: PPDirectoryTree::Constructor
  12. // Access: Public
  13. // Description:
  14. ////////////////////////////////////////////////////////////////////
  15. PPDirectoryTree::
  16. PPDirectoryTree(PPDirectoryTree *main_tree) {
  17. if (main_tree == NULL) {
  18. _main_tree = this;
  19. } else {
  20. _main_tree = main_tree;
  21. }
  22. _root = new PPDirectory(this);
  23. }
  24. ////////////////////////////////////////////////////////////////////
  25. // Function: PPDirectoryTree::Destructor
  26. // Access: Public
  27. // Description:
  28. ////////////////////////////////////////////////////////////////////
  29. PPDirectoryTree::
  30. ~PPDirectoryTree() {
  31. delete _root;
  32. RelatedTrees::iterator ri;
  33. for (ri = _related_trees.begin(); ri != _related_trees.end(); ++ri) {
  34. delete (*ri);
  35. }
  36. }
  37. ////////////////////////////////////////////////////////////////////
  38. // Function: PPDirectoryTree::get_main_tree
  39. // Access: Public
  40. // Description: Returns the PPDirectoryTree that represents the
  41. // actual source hierarchy. If the return value is
  42. // something other than this, it indicates that this
  43. // tree is an external dependable tree.
  44. ////////////////////////////////////////////////////////////////////
  45. PPDirectoryTree *PPDirectoryTree::
  46. get_main_tree() {
  47. return _main_tree;
  48. }
  49. ////////////////////////////////////////////////////////////////////
  50. // Function: PPDirectoryTree::set_fullpath
  51. // Access: Public
  52. // Description: Indicates the full path to the root of this
  53. // particular tree.
  54. ////////////////////////////////////////////////////////////////////
  55. void PPDirectoryTree::
  56. set_fullpath(const string &fullpath) {
  57. _fullpath = fullpath;
  58. }
  59. ////////////////////////////////////////////////////////////////////
  60. // Function: PPDirectoryTree::scan_source
  61. // Access: Public
  62. // Description: Reads in the complete hierarchy of source files,
  63. // beginning at the current directory.
  64. ////////////////////////////////////////////////////////////////////
  65. bool PPDirectoryTree::
  66. scan_source(PPNamedScopes *named_scopes) {
  67. if (!_root->r_scan("")) {
  68. return false;
  69. }
  70. if (!_root->read_source_file("", named_scopes)) {
  71. return false;
  72. }
  73. return true;
  74. }
  75. ////////////////////////////////////////////////////////////////////
  76. // Function: PPDirectoryTree::scan_depends
  77. // Access: Public
  78. // Description: Reads in the depends file for each source file, and
  79. // then sorts the files into dependency order.
  80. ////////////////////////////////////////////////////////////////////
  81. bool PPDirectoryTree::
  82. scan_depends(PPNamedScopes *named_scopes) {
  83. if (!_root->read_depends_file(named_scopes)) {
  84. return false;
  85. }
  86. if (!_root->resolve_dependencies()) {
  87. return false;
  88. }
  89. return true;
  90. }
  91. ////////////////////////////////////////////////////////////////////
  92. // Function: PPDirectoryTree::scan_extra_depends
  93. // Access: Public
  94. // Description: Accepts the value of DEPENDABLE_HEADER_DIRS, which
  95. // was presumably set by the various Config.pp and/or
  96. // Depends.pp scripts that were read in, and treats each
  97. // named filename there as the name of a directory that
  98. // contains header files in a separate but related tree,
  99. // for which we also need to generate dependency rules
  100. // in this tree.
  101. ////////////////////////////////////////////////////////////////////
  102. bool PPDirectoryTree::
  103. scan_extra_depends(const string &dependable_header_dirs,
  104. const string &cache_filename) {
  105. bool okflag = true;
  106. vector<string> dirnames;
  107. tokenize_whitespace(dependable_header_dirs, dirnames);
  108. // Sort dirnames and remove duplicates.
  109. sort(dirnames.begin(), dirnames.end());
  110. dirnames.erase(unique(dirnames.begin(), dirnames.end()), dirnames.end());
  111. vector<string>::const_iterator ni;
  112. for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
  113. string dirname = (*ni);
  114. if (dirname[0] != '/') {
  115. // Insist that the external dirname be a full pathname.
  116. dirname = _fullpath + "/" + dirname;
  117. }
  118. // Now we need to make up a different tree for each external
  119. // dirname.
  120. PPDirectoryTree *tree = new PPDirectoryTree(this);
  121. tree->set_fullpath(dirname);
  122. _related_trees.push_back(tree);
  123. if (!tree->get_root()->scan_extra_depends(cache_filename)) {
  124. okflag = false;
  125. }
  126. }
  127. return okflag;
  128. }
  129. ////////////////////////////////////////////////////////////////////
  130. // Function: PPDirectoryTree::count_source_files
  131. // Access: Public
  132. // Description: Returns the number of directories within the tree
  133. // that actually have a Sources.pp file that was read.
  134. ////////////////////////////////////////////////////////////////////
  135. int PPDirectoryTree::
  136. count_source_files() const {
  137. return _root->count_source_files();
  138. }
  139. ////////////////////////////////////////////////////////////////////
  140. // Function: PPDirectoryTree::get_root
  141. // Access: Public
  142. // Description: Returns the root directory of the tree.
  143. ////////////////////////////////////////////////////////////////////
  144. PPDirectory *PPDirectoryTree::
  145. get_root() const {
  146. return _root;
  147. }
  148. ////////////////////////////////////////////////////////////////////
  149. // Function: PPDirectoryTree::get_fullpath
  150. // Access: Public
  151. // Description: Returns the full path to the root of the tree.
  152. ////////////////////////////////////////////////////////////////////
  153. const string &PPDirectoryTree::
  154. get_fullpath() const {
  155. return _fullpath;
  156. }
  157. ////////////////////////////////////////////////////////////////////
  158. // Function: PPDirectoryTree::get_complete_tree
  159. // Access: Public
  160. // Description: Returns a single string listing the relative path
  161. // from the source root to each source directory in the
  162. // tree, delimited by spaces.
  163. ////////////////////////////////////////////////////////////////////
  164. string PPDirectoryTree::
  165. get_complete_tree() const {
  166. return _root->get_complete_subtree();
  167. }
  168. ////////////////////////////////////////////////////////////////////
  169. // Function: PPDirectoryTree::find_dirname
  170. // Access: Public
  171. // Description: Searches for the a source directory with the
  172. // matching dirname. This is just the name of the
  173. // directory itself, not the relative path to the
  174. // directory.
  175. ////////////////////////////////////////////////////////////////////
  176. PPDirectory *PPDirectoryTree::
  177. find_dirname(const string &dirname) const {
  178. Dirnames::const_iterator di;
  179. di = _dirnames.find(dirname);
  180. if (di != _dirnames.end()) {
  181. return (*di).second;
  182. }
  183. // No such dirname; too bad.
  184. return (PPDirectory *)NULL;
  185. }
  186. ////////////////////////////////////////////////////////////////////
  187. // Function: PPDirectoryTree::find_dependable_file
  188. // Access: Public
  189. // Description: Returns a PPDependableFile object corresponding to
  190. // the named filename, searching all of the known source
  191. // subdirectories. This can only find files marked by a
  192. // previous call to get_dependable_file() with is_header
  193. // set to true. Unlike
  194. // get_dependable_file_by_pathname() or
  195. // PPDirectory::get_dependable_file(), this does not
  196. // create an entry if it does not exist; instead, it
  197. // returns NULL if no matching file can be found.
  198. ////////////////////////////////////////////////////////////////////
  199. PPDependableFile *PPDirectoryTree::
  200. find_dependable_file(const string &filename) const {
  201. Dependables::const_iterator di;
  202. di = _dependables.find(filename);
  203. if (di != _dependables.end()) {
  204. return (*di).second;
  205. }
  206. return (PPDependableFile *)NULL;
  207. }
  208. ////////////////////////////////////////////////////////////////////
  209. // Function: PPDirectoryTree::get_dependable_file_by_pathname
  210. // Access: Public
  211. // Description: Given a dirname/filename for a particular dependable
  212. // filename, return (or create and return) the
  213. // corresponding PPDirectoryTree. This is different
  214. // from find_dependable_file() in that an explicit
  215. // dirname is given, and the entry will be created if
  216. // it does not already exist. However, if the directory
  217. // name does not exist, nothing is created, and NULL is
  218. // returned.
  219. ////////////////////////////////////////////////////////////////////
  220. PPDependableFile *PPDirectoryTree::
  221. get_dependable_file_by_dirpath(const string &dirpath, bool is_header) {
  222. size_t slash = dirpath.rfind('/');
  223. if (slash == string::npos) {
  224. // No valid directory name.
  225. return (PPDependableFile *)NULL;
  226. }
  227. string dirname = dirpath.substr(0, slash);
  228. string filename = dirpath.substr(slash + 1);
  229. if (!dirname.empty() && dirname[0] == '+') {
  230. // "+dirname/filename" means to look first for the file as an
  231. // external file, meaning it has no dirname.
  232. dirname = dirname.substr(1);
  233. PPDependableFile *result = get_main_tree()->find_dependable_file(filename);
  234. if (result != (PPDependableFile *)NULL) {
  235. return result;
  236. }
  237. }
  238. PPDirectory *dir = find_dirname(dirname);
  239. if (dir == (PPDirectory *)NULL) {
  240. // No valid directory name.
  241. return (PPDependableFile *)NULL;
  242. }
  243. return dir->get_dependable_file(filename, is_header);
  244. }
  245. ////////////////////////////////////////////////////////////////////
  246. // Function: PPDirectoryTree::read_file_dependencies
  247. // Access: Public
  248. // Description: Before processing the source files, makes a pass and
  249. // reads in all of the dependency cache files so we'll
  250. // have a heads-up on which files depend on the others.
  251. ////////////////////////////////////////////////////////////////////
  252. void PPDirectoryTree::
  253. read_file_dependencies(const string &cache_filename) {
  254. _root->read_file_dependencies(cache_filename);
  255. RelatedTrees::iterator ri;
  256. for (ri = _related_trees.begin(); ri != _related_trees.end(); ++ri) {
  257. (*ri)->read_file_dependencies(cache_filename);
  258. }
  259. }
  260. ////////////////////////////////////////////////////////////////////
  261. // Function: PPDirectoryTree::update_file_dependencies
  262. // Access: Public
  263. // Description: After all source processing has completed, makes one
  264. // more pass through the directory hierarchy and writes
  265. // out the inter-file dependency cache.
  266. ////////////////////////////////////////////////////////////////////
  267. void PPDirectoryTree::
  268. update_file_dependencies(const string &cache_filename) {
  269. _root->update_file_dependencies(cache_filename);
  270. RelatedTrees::iterator ri;
  271. for (ri = _related_trees.begin(); ri != _related_trees.end(); ++ri) {
  272. (*ri)->update_file_dependencies(cache_filename);
  273. }
  274. }