ppDirectory.cxx 25 KB

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