ppDirectory.cxx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. // Filename: ppDirectory.cxx
  2. // Created by: drose (28Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppDirectory.h"
  6. #include "ppDirectoryTree.h"
  7. #include "ppScope.h"
  8. #include "ppNamedScopes.h"
  9. #include "ppCommandFile.h"
  10. #include "ppDependableFile.h"
  11. #include "tokenize.h"
  12. #ifdef HAVE_DIRENT_H
  13. #include <dirent.h>
  14. #endif
  15. #ifdef HAVE_UNISTD_H
  16. #include <unistd.h>
  17. #endif
  18. #ifdef HAVE_SYS_TYPES_H
  19. #include <sys/types.h>
  20. #endif
  21. #include <algorithm>
  22. #include <assert.h>
  23. #ifdef WIN32_VC
  24. #include <direct.h>
  25. #include <windows.h>
  26. #endif
  27. PPDirectory *current_output_directory = (PPDirectory *)NULL;
  28. // An STL object to sort directories in order by dependency and then
  29. // by name, used in get_child_dirnames().
  30. class SortDirectoriesByDependencyAndName {
  31. public:
  32. bool operator () (const PPDirectory *a, const PPDirectory *b) const {
  33. if (a->get_depends_index() != b->get_depends_index()) {
  34. return a->get_depends_index() < b->get_depends_index();
  35. }
  36. return a->get_dirname() < b->get_dirname();
  37. }
  38. };
  39. ////////////////////////////////////////////////////////////////////
  40. // Function: PPDirectory::Constructor
  41. // Access: Public
  42. // Description: Creates the root directory.
  43. ////////////////////////////////////////////////////////////////////
  44. PPDirectory::
  45. PPDirectory(PPDirectoryTree *tree) {
  46. _scope = (PPScope *)NULL;
  47. _source = (PPCommandFile *)NULL;
  48. _parent = (PPDirectory *)NULL;
  49. _tree = tree;
  50. _depth = 0;
  51. _depends_index = 0;
  52. _computing_depends_index = false;
  53. _dirname = "top";
  54. _tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this));
  55. }
  56. ////////////////////////////////////////////////////////////////////
  57. // Function: PPDirectory::Constructor
  58. // Access: Public
  59. // Description: Creates a new directory level that automatically adds
  60. // itself to its parent's children list.
  61. ////////////////////////////////////////////////////////////////////
  62. PPDirectory::
  63. PPDirectory(const string &dirname, PPDirectory *parent) :
  64. _dirname(dirname),
  65. _parent(parent)
  66. {
  67. assert(_parent != (PPDirectory *)NULL);
  68. _scope = (PPScope *)NULL;
  69. _source = (PPCommandFile *)NULL;
  70. _parent->_children.push_back(this);
  71. _tree = _parent->_tree;
  72. _depth = _parent->_depth + 1;
  73. _depends_index = 0;
  74. _computing_depends_index = false;
  75. bool inserted =
  76. _tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this)).second;
  77. if (!inserted) {
  78. cerr << "Warning: multiple directories encountered named "
  79. << _dirname << "\n";
  80. }
  81. }
  82. ////////////////////////////////////////////////////////////////////
  83. // Function: PPDirectory::Destructor
  84. // Access: Public
  85. // Description: When a tree root destructs, all of its children are
  86. // also destroyed.
  87. ////////////////////////////////////////////////////////////////////
  88. PPDirectory::
  89. ~PPDirectory() {
  90. Children::iterator ci;
  91. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  92. delete (*ci);
  93. }
  94. }
  95. ////////////////////////////////////////////////////////////////////
  96. // Function: PPDirectory::get_tree
  97. // Access: Public
  98. // Description: Returns the PPDirectoryTree object corresponding to
  99. // the source tree that this directory is a part of.
  100. ////////////////////////////////////////////////////////////////////
  101. PPDirectoryTree *PPDirectory::
  102. get_tree() const {
  103. return _tree;
  104. }
  105. ////////////////////////////////////////////////////////////////////
  106. // Function: PPDirectory::count_source_files
  107. // Access: Public
  108. // Description: Returns the number of directories within the tree
  109. // that actually have a Sources.pp file that was read.
  110. ////////////////////////////////////////////////////////////////////
  111. int PPDirectory::
  112. count_source_files() const {
  113. int count = 0;
  114. if (_source != (PPCommandFile *)NULL) {
  115. count++;
  116. }
  117. Children::const_iterator ci;
  118. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  119. count += (*ci)->count_source_files();
  120. }
  121. return count;
  122. }
  123. ////////////////////////////////////////////////////////////////////
  124. // Function: PPDirectory::get_dirname
  125. // Access: Public
  126. // Description: Returns the name of this particular directory level.
  127. ////////////////////////////////////////////////////////////////////
  128. const string &PPDirectory::
  129. get_dirname() const {
  130. return _dirname;
  131. }
  132. ////////////////////////////////////////////////////////////////////
  133. // Function: PPDirectory::get_depends_index
  134. // Access: Public
  135. // Description: Returns the dependency index associated with this
  136. // directory. It is generally true that if directory A
  137. // depends on B, then A.get_depends_index() >
  138. // B.get_depends_index().
  139. ////////////////////////////////////////////////////////////////////
  140. int PPDirectory::
  141. get_depends_index() const {
  142. return _depends_index;
  143. }
  144. ////////////////////////////////////////////////////////////////////
  145. // Function: PPDirectory::get_path
  146. // Access: Public
  147. // Description: Returns the relative path from the root to this
  148. // particular directory. This does not include the root
  149. // name itself, and does not include a trailing slash.
  150. ////////////////////////////////////////////////////////////////////
  151. string PPDirectory::
  152. get_path() const {
  153. if (_parent == (PPDirectory *)NULL) {
  154. return ".";
  155. }
  156. if (_parent->_parent == (PPDirectory *)NULL) {
  157. return _dirname;
  158. }
  159. return _parent->get_path() + "/" + _dirname;
  160. }
  161. ////////////////////////////////////////////////////////////////////
  162. // Function: PPDirectory::get_rel_to
  163. // Access: Public
  164. // Description: Returns the relative path to the other directory from
  165. // this one. This does not include a trailing slash.
  166. ////////////////////////////////////////////////////////////////////
  167. string PPDirectory::
  168. get_rel_to(const PPDirectory *other) const {
  169. const PPDirectory *a = this;
  170. const PPDirectory *b = other;
  171. if (a == b) {
  172. return ".";
  173. }
  174. string prefix, postfix;
  175. while (a->_depth > b->_depth) {
  176. prefix += "../";
  177. a = a->_parent;
  178. assert(a != (PPDirectory *)NULL);
  179. }
  180. while (b->_depth > a->_depth) {
  181. postfix = b->_dirname + "/" + postfix;
  182. b = b->_parent;
  183. assert(b != (PPDirectory *)NULL);
  184. }
  185. while (a != b) {
  186. prefix += "../";
  187. postfix = b->_dirname + "/" + postfix;
  188. a = a->_parent;
  189. b = b->_parent;
  190. assert(a != (PPDirectory *)NULL);
  191. assert(b != (PPDirectory *)NULL);
  192. }
  193. string result = prefix + postfix;
  194. assert(!result.empty());
  195. return result.substr(0, result.length() - 1);
  196. }
  197. ////////////////////////////////////////////////////////////////////
  198. // Function: PPDirectory::get_source
  199. // Access: Public
  200. // Description: Returns the source file associated with this level
  201. // of the directory hierarchy. This *might* be NULL.
  202. ////////////////////////////////////////////////////////////////////
  203. PPCommandFile *PPDirectory::
  204. get_source() const {
  205. return _source;
  206. }
  207. ////////////////////////////////////////////////////////////////////
  208. // Function: PPDirectory::get_num_children
  209. // Access: Public
  210. // Description: Returns the number of subdirectories below this
  211. // level.
  212. ////////////////////////////////////////////////////////////////////
  213. int PPDirectory::
  214. get_num_children() const {
  215. return _children.size();
  216. }
  217. ////////////////////////////////////////////////////////////////////
  218. // Function: PPDirectory::get_child
  219. // Access: Public
  220. // Description: Returns the nth subdirectory below this level.
  221. ////////////////////////////////////////////////////////////////////
  222. PPDirectory *PPDirectory::
  223. get_child(int n) const {
  224. assert(n >= 0 && n < (int)_children.size());
  225. return _children[n];
  226. }
  227. ////////////////////////////////////////////////////////////////////
  228. // Function: PPDirectory::get_child_dirnames
  229. // Access: Public
  230. // Description: Returns a single string listing the names of all the
  231. // subdirectories of this level, delimited by spaces.
  232. //
  233. // The list is sorted in dependency order such that a
  234. // directory is listed after the other directories it
  235. // might depend on.
  236. ////////////////////////////////////////////////////////////////////
  237. string PPDirectory::
  238. get_child_dirnames() const {
  239. Children copy_children = _children;
  240. sort(copy_children.begin(), copy_children.end(),
  241. SortDirectoriesByDependencyAndName());
  242. vector<string> words;
  243. Children::const_iterator ci;
  244. for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
  245. words.push_back((*ci)->get_dirname());
  246. }
  247. string result = repaste(words, " ");
  248. return result;
  249. }
  250. ////////////////////////////////////////////////////////////////////
  251. // Function: PPDirectory::get_complete_subtree
  252. // Access: Public
  253. // Description: Returns a single string listing the relative path
  254. // from the source root to each source directory at this
  255. // level and below, delimited by spaces.
  256. ////////////////////////////////////////////////////////////////////
  257. string PPDirectory::
  258. get_complete_subtree() const {
  259. Children copy_children = _children;
  260. sort(copy_children.begin(), copy_children.end(),
  261. SortDirectoriesByDependencyAndName());
  262. vector<string> words;
  263. words.push_back(get_path());
  264. Children::const_iterator ci;
  265. for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
  266. words.push_back((*ci)->get_complete_subtree());
  267. }
  268. string result = repaste(words, " ");
  269. return result;
  270. }
  271. ////////////////////////////////////////////////////////////////////
  272. // Function: PPDirectory::get_dependable_file
  273. // Access: Public
  274. // Description: Returns a PPDependableFile object corresponding to
  275. // the named filename, creating one if it does not
  276. // already exist. This can be used to determine the
  277. // inter-file dependencies between source files.
  278. //
  279. // If is_header is true, then the file will be added to
  280. // the index at the top of the directory tree, so that
  281. // other directories may include this file. In this
  282. // case, if the filename is not unique, a warning
  283. // message will be issued.
  284. ////////////////////////////////////////////////////////////////////
  285. PPDependableFile *PPDirectory::
  286. get_dependable_file(const string &filename, bool is_header) {
  287. Dependables::iterator di;
  288. di = _dependables.find(filename);
  289. if (di != _dependables.end()) {
  290. return (*di).second;
  291. }
  292. // No such file found; create a new definition.
  293. PPDependableFile *dependable = new PPDependableFile(this, filename);
  294. _dependables.insert(Dependables::value_type(filename, dependable));
  295. if (is_header) {
  296. bool unique = _tree->_dependables.insert
  297. (PPDirectoryTree::Dependables::value_type(filename, dependable)).second;
  298. if (!unique) {
  299. cerr << "Warning: source file " << dependable->get_pathname()
  300. << " may be confused with "
  301. << _tree->find_dependable_file(filename)->get_pathname()
  302. << ".\n";
  303. }
  304. }
  305. return dependable;
  306. }
  307. ////////////////////////////////////////////////////////////////////
  308. // Function: PPDirectory::report_depends
  309. // Access: Public
  310. // Description: Reports all the directories that the current
  311. // directory depends on.
  312. ////////////////////////////////////////////////////////////////////
  313. void PPDirectory::
  314. report_depends() const {
  315. if (_i_depend_on.empty()) {
  316. cerr << _dirname << " depends on no other directories.\n";
  317. } else {
  318. // Get the complete set of directories we depend on.
  319. Depends dep;
  320. get_complete_i_depend_on(dep);
  321. cerr << _dirname << " depends directly on the following directories:";
  322. show_directories(_i_depend_on);
  323. cerr << "and directly or indirectly on the following directories:";
  324. show_directories(dep);
  325. }
  326. }
  327. ////////////////////////////////////////////////////////////////////
  328. // Function: PPDirectory::report_reverse_depends
  329. // Access: Public
  330. // Description: Reports all the directories that depend on the
  331. // current directory.
  332. ////////////////////////////////////////////////////////////////////
  333. void PPDirectory::
  334. report_reverse_depends() const {
  335. if (_depends_on_me.empty()) {
  336. cerr << _dirname << " is needed by no other directories.\n";
  337. } else {
  338. // Get the complete set of directories we depend on.
  339. Depends dep;
  340. get_complete_depends_on_me(dep);
  341. cerr << _dirname << " is needed directly by the following directories:";
  342. show_directories(_depends_on_me);
  343. cerr << "and directly or indirectly by the following directories:";
  344. show_directories(dep);
  345. }
  346. }
  347. ////////////////////////////////////////////////////////////////////
  348. // Function: PPDirectory::r_scan
  349. // Access: Private
  350. // Description: The recursive implementation of scan_source().
  351. ////////////////////////////////////////////////////////////////////
  352. bool PPDirectory::
  353. r_scan(const string &prefix) {
  354. Filename root_name = ".";
  355. if (!prefix.empty()) {
  356. root_name = prefix.substr(0, prefix.length() - 1);
  357. }
  358. // Collect all the filenames in the directory in this vector first,
  359. // so we can sort them.
  360. vector<string> filenames;
  361. if (!root_name.scan_directory(filenames)) {
  362. cerr << "Unable to scan directory " << root_name << "\n";
  363. return false;
  364. }
  365. vector<string>::const_iterator fi;
  366. for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
  367. string filename = (*fi);
  368. if (!filename.empty() && filename[0] != '.') {
  369. // Is this possibly a subdirectory with its own Sources.pp
  370. // within it?
  371. string next_prefix = prefix + filename + "/";
  372. Filename source_filename = next_prefix + SOURCE_FILENAME;
  373. if (source_filename.exists()) {
  374. PPDirectory *subtree = new PPDirectory(filename, this);
  375. if (!subtree->r_scan(next_prefix)) {
  376. return false;
  377. }
  378. }
  379. }
  380. }
  381. return true;
  382. }
  383. ////////////////////////////////////////////////////////////////////
  384. // Function: PPDirectory::read_source_file
  385. // Access: Private
  386. // Description: Recursively reads in the source file at each level,
  387. // if defined.
  388. ////////////////////////////////////////////////////////////////////
  389. bool PPDirectory::
  390. read_source_file(const string &prefix, PPNamedScopes *named_scopes) {
  391. string source_filename = prefix + SOURCE_FILENAME;
  392. ifstream in(source_filename.c_str());
  393. if (in) {
  394. if (verbose) {
  395. cerr << "Reading (dir) \"" << source_filename << "\"\n";
  396. }
  397. named_scopes->set_current(_dirname);
  398. _scope = named_scopes->make_scope("");
  399. _scope->define_variable("SOURCEFILE", SOURCE_FILENAME);
  400. _scope->define_variable("DIRNAME", _dirname);
  401. _scope->define_variable("DIRPREFIX", prefix);
  402. _scope->define_variable("PATH", get_path());
  403. _scope->define_variable("SUBDIRS", get_child_dirnames());
  404. _scope->define_variable("SUBTREE", get_complete_subtree());
  405. _scope->set_directory(this);
  406. _source = new PPCommandFile(_scope);
  407. if (!_source->read_stream(in, source_filename)) {
  408. return false;
  409. }
  410. }
  411. Children::iterator ci;
  412. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  413. if (!(*ci)->read_source_file(prefix + (*ci)->get_dirname() + "/",
  414. named_scopes)) {
  415. return false;
  416. }
  417. }
  418. return true;
  419. }
  420. ////////////////////////////////////////////////////////////////////
  421. // Function: PPDirectory::read_depends_file
  422. // Access: Private
  423. // Description: Recursively reads in the dependency definition file
  424. // for each source file.
  425. ////////////////////////////////////////////////////////////////////
  426. bool PPDirectory::
  427. read_depends_file(PPNamedScopes *named_scopes) {
  428. if (_scope != (PPScope *)NULL) {
  429. // Read the depends file, so we can determine the relationship
  430. // between this source file and all of the other source files.
  431. string depends_filename = _scope->expand_variable("DEPENDS_FILE");
  432. if (depends_filename.empty()) {
  433. cerr << "No definition given for $[DEPENDS_FILE], cannot process.\n";
  434. return false;
  435. }
  436. named_scopes->set_current(_dirname);
  437. current_output_directory = this;
  438. PPCommandFile depends(_scope);
  439. if (!depends.read_file(depends_filename)) {
  440. cerr << "Error reading dependency definition file "
  441. << depends_filename << ".\n";
  442. return false;
  443. }
  444. // This should have defined the variable DEPEND_DIRS, which lists
  445. // the various dirnames this source file depends on.
  446. vector<string> dirnames;
  447. tokenize_whitespace(_scope->expand_variable("DEPEND_DIRS"), dirnames);
  448. vector<string>::const_iterator ni;
  449. for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
  450. const string &dirname = (*ni);
  451. PPDirectory *dir = _tree->find_dirname(dirname);
  452. if (dir == (PPDirectory *)NULL) {
  453. cerr << "Could not find dependent dirname " << dirname << "\n";
  454. } else {
  455. if (dir != this) {
  456. _i_depend_on.insert(dir);
  457. dir->_depends_on_me.insert(this);
  458. }
  459. }
  460. }
  461. // This may also have defined the variable DEPENDABLE_HEADERS,
  462. // which lists the header files in this directory that C/C++
  463. // source files in this and other directories might be including
  464. // (and will therefore depend on).
  465. vector<string> headers;
  466. tokenize_whitespace(_scope->expand_variable("DEPENDABLE_HEADERS"), headers);
  467. for (ni = headers.begin(); ni != headers.end(); ++ni) {
  468. get_dependable_file(*ni, true);
  469. }
  470. }
  471. Children::iterator ci;
  472. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  473. if (!(*ci)->read_depends_file(named_scopes)) {
  474. return false;
  475. }
  476. }
  477. return true;
  478. }
  479. ////////////////////////////////////////////////////////////////////
  480. // Function: PPDirectory::resolve_dependencies
  481. // Access: Private
  482. // Description: Visits each directory and assigns a correct
  483. // _depends_index to each one, such that if directory A
  484. // depends on directory B then A._depends_index >
  485. // B._depends_index.
  486. //
  487. // This also detects cycles in the directory dependency
  488. // graph.
  489. ////////////////////////////////////////////////////////////////////
  490. bool PPDirectory::
  491. resolve_dependencies() {
  492. if (!compute_depends_index()) {
  493. return false;
  494. }
  495. Children::iterator ci;
  496. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  497. if (!(*ci)->resolve_dependencies()) {
  498. return false;
  499. }
  500. }
  501. // Now that we've resolved all of our children's dependencies,
  502. // redefine our SUBDIRS and SUBTREE variables to put things in the
  503. // right order.
  504. if (_scope != (PPScope *)NULL) {
  505. _scope->define_variable("SUBDIRS", get_child_dirnames());
  506. _scope->define_variable("SUBTREE", get_complete_subtree());
  507. }
  508. return true;
  509. }
  510. ////////////////////////////////////////////////////////////////////
  511. // Function: PPDirectory::compute_depends_index
  512. // Access: Private
  513. // Description: Computes the dependency score for a particular
  514. // directory. See resolve_dependencies().
  515. ////////////////////////////////////////////////////////////////////
  516. bool PPDirectory::
  517. compute_depends_index() {
  518. if (_depends_index != 0) {
  519. return true;
  520. }
  521. if (_i_depend_on.empty()) {
  522. _depends_index = 1;
  523. return true;
  524. }
  525. _computing_depends_index = true;
  526. int max_index = 0;
  527. Depends::iterator di;
  528. for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
  529. if ((*di)->_computing_depends_index) {
  530. // Oops, we have a cycle!
  531. cerr << "Cycle detected in inter-directory dependencies!\n"
  532. << _dirname << " depends on " << (*di)->_dirname << "\n";
  533. return false;
  534. }
  535. if (!(*di)->compute_depends_index()) {
  536. // Keep reporting the cycle as we unroll the recursion.
  537. cerr << _dirname << " depends on " << (*di)->_dirname << "\n";
  538. return false;
  539. }
  540. max_index = max(max_index, (*di)->_depends_index);
  541. }
  542. _computing_depends_index = false;
  543. _depends_index = max_index + 1;
  544. return true;
  545. }
  546. ////////////////////////////////////////////////////////////////////
  547. // Function: PPDirectory::read_file_dependencies
  548. // Access: Private
  549. // Description: Before processing the source files, makes a pass and
  550. // reads in all of the dependency cache files so we'll
  551. // have a heads-up on which files depend on the others.
  552. ////////////////////////////////////////////////////////////////////
  553. void PPDirectory::
  554. read_file_dependencies(const string &cache_filename) {
  555. // Open up the dependency cache file in the directory.
  556. string cache_pathname = get_path() + "/" + cache_filename;
  557. ifstream in(cache_pathname.c_str());
  558. if (!in) {
  559. // Can't read it. Maybe it's not there. No problem.
  560. return;
  561. }
  562. if (verbose) {
  563. cerr << "Reading (dep) \"" << cache_pathname.c_str() << "\"\n";
  564. }
  565. string line;
  566. getline(in, line);
  567. while (!in.fail() && !in.eof()) {
  568. vector<string> words;
  569. tokenize_whitespace(line, words);
  570. if (words.size() >= 2) {
  571. PPDependableFile *file = get_dependable_file(words[0], false);
  572. file->update_from_cache(words);
  573. }
  574. getline(in, line);
  575. }
  576. Children::iterator ci;
  577. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  578. (*ci)->read_file_dependencies(cache_filename);
  579. }
  580. }
  581. ////////////////////////////////////////////////////////////////////
  582. // Function: PPDirectory::update_file_dependencies
  583. // Access: Private
  584. // Description: After all source processing has completed, makes one
  585. // more pass through the directory hierarchy and writes
  586. // out the inter-file dependency cache.
  587. ////////////////////////////////////////////////////////////////////
  588. void PPDirectory::
  589. update_file_dependencies(const string &cache_filename) {
  590. if (dry_run) {
  591. // If this is just a dry run, just report circularities.
  592. Dependables::const_iterator di;
  593. for (di = _dependables.begin(); di != _dependables.end(); ++di) {
  594. PPDependableFile *file = (*di).second;
  595. if (file->was_examined()) {
  596. if (file->is_circularity()) {
  597. cerr << "Warning: circular #include directives:\n"
  598. << " " << file->get_circularity() << "\n";
  599. }
  600. }
  601. }
  602. } else {
  603. // Open up the dependency cache file in the directory.
  604. Filename cache_pathname(get_path(), cache_filename);
  605. cache_pathname.set_text();
  606. cache_pathname.unlink();
  607. // If we have no files, don't bother writing the cache.
  608. if (!_dependables.empty()) {
  609. bool wrote_anything = false;
  610. ofstream out;
  611. if (!cache_pathname.open_write(out)) {
  612. cerr << "Cannot update cache dependency file " << cache_pathname << "\n";
  613. return;
  614. }
  615. // Walk through our list of dependable files, writing them out the
  616. // the cache file.
  617. Dependables::const_iterator di;
  618. for (di = _dependables.begin(); di != _dependables.end(); ++di) {
  619. PPDependableFile *file = (*di).second;
  620. if (file->was_examined()) {
  621. if (file->is_circularity()) {
  622. cerr << "Warning: circular #include directives:\n"
  623. << " " << file->get_circularity() << "\n";
  624. }
  625. file->write_cache(out);
  626. wrote_anything = true;
  627. }
  628. }
  629. out.close();
  630. if (!wrote_anything) {
  631. // Well, if we didn't write anything, remove the cache file
  632. // after all.
  633. cache_pathname.unlink();
  634. }
  635. }
  636. }
  637. Children::iterator ci;
  638. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  639. (*ci)->update_file_dependencies(cache_filename);
  640. }
  641. }
  642. ////////////////////////////////////////////////////////////////////
  643. // Function: PPDirectory::get_complete_i_depend_on
  644. // Access: Private
  645. // Description: Gets the transitive closure of i_depend_on. This
  646. // fills the given set (which must have been empty
  647. // before this call) with the complete set of all
  648. // directories this directory depends on, directly or
  649. // indirectly.
  650. ////////////////////////////////////////////////////////////////////
  651. void PPDirectory::
  652. get_complete_i_depend_on(Depends &dep) const {
  653. Depends::const_iterator di;
  654. for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
  655. PPDirectory *dir = (*di);
  656. bool inserted = dep.insert(dir).second;
  657. if (inserted) {
  658. dir->get_complete_i_depend_on(dep);
  659. }
  660. }
  661. }
  662. ////////////////////////////////////////////////////////////////////
  663. // Function: PPDirectory::get_complete_depends_on_me
  664. // Access: Private
  665. // Description: Gets the transitive closure of depends_on_me. This
  666. // fills the given set (which must have been empty
  667. // before this call) with the complete set of all
  668. // directories this that depend on this directory,
  669. // directly or indirectly.
  670. ////////////////////////////////////////////////////////////////////
  671. void PPDirectory::
  672. get_complete_depends_on_me(Depends &dep) const {
  673. Depends::const_iterator di;
  674. for (di = _depends_on_me.begin(); di != _depends_on_me.end(); ++di) {
  675. PPDirectory *dir = (*di);
  676. bool inserted = dep.insert(dir).second;
  677. if (inserted) {
  678. dir->get_complete_depends_on_me(dep);
  679. }
  680. }
  681. }
  682. ////////////////////////////////////////////////////////////////////
  683. // Function: PPDirectory::show_directories
  684. // Access: Private
  685. // Description: Writes a set of dependency directory names to
  686. // standard error. The output begins with a newline.
  687. ////////////////////////////////////////////////////////////////////
  688. void PPDirectory::
  689. show_directories(const PPDirectory::Depends &dep) const {
  690. // Copy the set into a vector, so we can sort it into a nice order
  691. // for the user's pleasure.
  692. vector<PPDirectory *> dirs;
  693. copy(dep.begin(), dep.end(),
  694. back_insert_iterator<vector<PPDirectory *> >(dirs));
  695. sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName());
  696. static const int max_col = 72;
  697. int col = max_col;
  698. vector<PPDirectory *>::const_iterator di;
  699. for (di = dirs.begin(); di != dirs.end(); ++di) {
  700. const string &dirname = (*di)->_dirname;
  701. col += dirname.length() + 1;
  702. if (col >= max_col) {
  703. col = dirname.length() + 2;
  704. cerr << "\n " << dirname;
  705. } else {
  706. cerr << " " << dirname;
  707. }
  708. }
  709. cerr << "\n";
  710. }