ppMain.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // Filename: ppMain.cxx
  2. // Created by: drose (28Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppMain.h"
  6. #include "ppScope.h"
  7. #include "ppCommandFile.h"
  8. #include "ppDirectory.h"
  9. #include "tokenize.h"
  10. #include <unistd.h>
  11. #include <assert.h>
  12. #include <errno.h>
  13. #include <stdio.h> // for perror
  14. string PPMain::_root;
  15. ////////////////////////////////////////////////////////////////////
  16. // Function: PPMain::Constructor
  17. // Access: Public
  18. // Description:
  19. ////////////////////////////////////////////////////////////////////
  20. PPMain::
  21. PPMain(PPScope *global_scope) {
  22. _global_scope = global_scope;
  23. PPScope::push_scope(_global_scope);
  24. _def_scope = (PPScope *)NULL;
  25. _defs = (PPCommandFile *)NULL;
  26. }
  27. ////////////////////////////////////////////////////////////////////
  28. // Function: PPMain::Destructor
  29. // Access: Public
  30. // Description:
  31. ////////////////////////////////////////////////////////////////////
  32. PPMain::
  33. ~PPMain() {
  34. if (_def_scope != (PPScope *)NULL) {
  35. delete _def_scope;
  36. }
  37. if (_defs != (PPCommandFile *)NULL) {
  38. delete _defs;
  39. }
  40. }
  41. ////////////////////////////////////////////////////////////////////
  42. // Function: PPMain::read_source
  43. // Access: Public
  44. // Description: Reads the directory hierarchy of Sources.pp files, at
  45. // the indicated directory and below.
  46. ////////////////////////////////////////////////////////////////////
  47. bool PPMain::
  48. read_source(const string &root) {
  49. // First, find the top of the source tree, as indicated by the
  50. // presence of a Package.pp file.
  51. string trydir = root;
  52. string package_file = trydir + "/" + PACKAGE_FILENAME;
  53. while (access(package_file.c_str(), F_OK) != 0) {
  54. // We continue to walk up directories as long as we see a source
  55. // file in each directory. When we stop seeing source files, we
  56. // stop walking upstairs.
  57. string source_file = trydir + "/" + SOURCE_FILENAME;
  58. if (access(source_file.c_str(), F_OK) != 0) {
  59. cerr << "Could not find ppremake package file " << PACKAGE_FILENAME
  60. << ".\n\n"
  61. << "This file should be present in the top of the source directory tree;\n"
  62. << "it defines implementation-specific variables to control the output\n"
  63. << "of ppremake, as well as pointing out the installed location of\n"
  64. << "important ppremake config files.\n\n";
  65. return false;
  66. }
  67. trydir += "/..";
  68. package_file = trydir + "/" + PACKAGE_FILENAME;
  69. }
  70. // Now cd to the source root and get the actual path.
  71. if (chdir(trydir.c_str()) < 0) {
  72. perror("chdir");
  73. return false;
  74. }
  75. _root = get_cwd();
  76. cerr << "Root is " << _root << "\n";
  77. _def_scope = new PPScope(&_named_scopes);
  78. _def_scope->define_variable("PACKAGEFILE", package_file);
  79. _def_scope->define_variable("TOPDIR", _root);
  80. _defs = new PPCommandFile(_def_scope);
  81. if (!_defs->read_file(PACKAGE_FILENAME)) {
  82. return false;
  83. }
  84. // Now check the *_PLATFORM variables that System.pp was supposed to
  85. // set.
  86. if (!trim_blanks(_def_scope->expand_string("$[UNIX_PLATFORM]")).empty()) {
  87. unix_platform = true;
  88. }
  89. if (!trim_blanks(_def_scope->expand_string("$[WINDOWS_PLATFORM]")).empty()) {
  90. windows_platform = true;
  91. }
  92. PPScope::push_scope(_def_scope);
  93. if (!_tree.scan_source(&_named_scopes)) {
  94. return false;
  95. }
  96. _def_scope->define_variable("TREE", _tree.get_complete_tree());
  97. if (_tree.count_source_files() == 0) {
  98. cerr << "Could not find any source definition files named " << SOURCE_FILENAME
  99. << ".\n\n"
  100. << "A file by this name should be present in each directory of the source\n"
  101. << "hierarchy; it defines the source files and targets that should be\n"
  102. << "built in each directory, as well as the relationships between the\n"
  103. << "directories.\n\n";
  104. return false;
  105. }
  106. cerr << "Read " << _tree.count_source_files() << " " << SOURCE_FILENAME
  107. << " files.\n";
  108. if (!read_global_file()) {
  109. return false;
  110. }
  111. if (!_tree.scan_depends(&_named_scopes)) {
  112. return false;
  113. }
  114. return true;
  115. }
  116. ////////////////////////////////////////////////////////////////////
  117. // Function: PPMain::process_all
  118. // Access: Public
  119. // Description: Does all the processing on all known directories.
  120. // See process().
  121. ////////////////////////////////////////////////////////////////////
  122. bool PPMain::
  123. process_all() {
  124. string cache_filename = _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME");
  125. if (cache_filename.empty()) {
  126. cerr << "Warning: no definition given for $[DEPENDENCY_CACHE_FILENAME].\n";
  127. } else {
  128. _tree.read_file_dependencies(cache_filename);
  129. }
  130. if (!r_process_all(_tree.get_root())) {
  131. return false;
  132. }
  133. if (!cache_filename.empty()) {
  134. _tree.update_file_dependencies(cache_filename);
  135. }
  136. return true;
  137. }
  138. ////////////////////////////////////////////////////////////////////
  139. // Function: PPMain::process
  140. // Access: Public
  141. // Description: Does the processing associated with the source file
  142. // in the indicated subdirectory name. This involves
  143. // reading in the template file and generating whatever
  144. // output the template file indicates.
  145. ////////////////////////////////////////////////////////////////////
  146. bool PPMain::
  147. process(const string &dirname) {
  148. string cache_filename = _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME");
  149. if (cache_filename.empty()) {
  150. cerr << "Warning: no definition given for $[DEPENDENCY_CACHE_FILENAME].\n";
  151. } else {
  152. _tree.read_file_dependencies(cache_filename);
  153. }
  154. PPDirectory *dir = _tree.find_dirname(dirname);
  155. if (dir == (PPDirectory *)NULL) {
  156. cerr << "Unknown directory: " << dirname << "\n";
  157. return false;
  158. }
  159. if (dir->get_source() == (PPCommandFile *)NULL) {
  160. cerr << "No source file in " << dirname << "\n";
  161. return false;
  162. }
  163. if (!p_process(dir)) {
  164. return false;
  165. }
  166. if (!cache_filename.empty()) {
  167. _tree.update_file_dependencies(cache_filename);
  168. }
  169. return true;
  170. }
  171. ////////////////////////////////////////////////////////////////////
  172. // Function: PPMain::report_depends
  173. // Access: Public
  174. // Description: Reports all the directories that the named directory
  175. // depends on.
  176. ////////////////////////////////////////////////////////////////////
  177. void PPMain::
  178. report_depends(const string &dirname) const {
  179. PPDirectory *dir = _tree.find_dirname(dirname);
  180. if (dir == (PPDirectory *)NULL) {
  181. cerr << "Unknown directory: " << dirname << "\n";
  182. return;
  183. }
  184. dir->report_depends();
  185. }
  186. ////////////////////////////////////////////////////////////////////
  187. // Function: PPMain::report_needs
  188. // Access: Public
  189. // Description: Reports all the directories that depend on (need) the
  190. // named directory.
  191. ////////////////////////////////////////////////////////////////////
  192. void PPMain::
  193. report_needs(const string &dirname) const {
  194. PPDirectory *dir = _tree.find_dirname(dirname);
  195. if (dir == (PPDirectory *)NULL) {
  196. cerr << "Unknown directory: " << dirname << "\n";
  197. return;
  198. }
  199. dir->report_needs();
  200. }
  201. ////////////////////////////////////////////////////////////////////
  202. // Function: PPMain::get_root
  203. // Access: Public, Static
  204. // Description: Returns the full path to the root directory of the
  205. // source hierarchy; this is the directory in which the
  206. // runs most of the time.
  207. ////////////////////////////////////////////////////////////////////
  208. string PPMain::
  209. get_root() {
  210. return _root;
  211. }
  212. ////////////////////////////////////////////////////////////////////
  213. // Function: PPMain::chdir_root
  214. // Access: Public, Static
  215. // Description: Changes the current directory to the root directory
  216. // of the source hierarchy. This should be executed
  217. // after a temporary change to another directory, to
  218. // restore the current directory to a known state.
  219. ////////////////////////////////////////////////////////////////////
  220. void PPMain::
  221. chdir_root() {
  222. if (chdir(_root.c_str()) < 0) {
  223. perror("chdir");
  224. // This is a real error! We can't get back to our starting
  225. // directory!
  226. cerr << "Error! Source directory is invalid!\n";
  227. exit(1);
  228. }
  229. }
  230. ////////////////////////////////////////////////////////////////////
  231. // Function: PPMain::r_process_all
  232. // Access: Private
  233. // Description: The recursive implementation of process_all().
  234. ////////////////////////////////////////////////////////////////////
  235. bool PPMain::
  236. r_process_all(PPDirectory *dir) {
  237. if (dir->get_source() != (PPCommandFile *)NULL) {
  238. if (!p_process(dir)) {
  239. return false;
  240. }
  241. }
  242. int num_children = dir->get_num_children();
  243. for (int i = 0; i < num_children; i++) {
  244. if (!r_process_all(dir->get_child(i))) {
  245. return false;
  246. }
  247. }
  248. return true;
  249. }
  250. ////////////////////////////////////////////////////////////////////
  251. // Function: PPMain::p_process
  252. // Access: Private
  253. // Description: The private implementation of process().
  254. ////////////////////////////////////////////////////////////////////
  255. bool PPMain::
  256. p_process(PPDirectory *dir) {
  257. current_output_directory = dir;
  258. _named_scopes.set_current(dir->get_dirname());
  259. PPCommandFile *source = dir->get_source();
  260. assert(source != (PPCommandFile *)NULL);
  261. PPScope *scope = source->get_scope();
  262. string template_filename = scope->expand_variable("TEMPLATE_FILE");
  263. if (template_filename.empty()) {
  264. cerr << "No definition given for $[TEMPLATE_FILE], cannot process.\n";
  265. return false;
  266. }
  267. PPCommandFile template_file(scope);
  268. if (!template_file.read_file(template_filename)) {
  269. cerr << "Error reading template file " << template_filename << ".\n";
  270. return false;
  271. }
  272. return true;
  273. }
  274. ////////////////////////////////////////////////////////////////////
  275. // Function: PPMain::read_global_file
  276. // Access: Private
  277. // Description: Reads in the Global.pp file after all sources files
  278. // have been read and sorted into dependency order.
  279. ////////////////////////////////////////////////////////////////////
  280. bool PPMain::
  281. read_global_file() {
  282. assert(_def_scope != (PPScope *)NULL);
  283. string global_filename = _def_scope->expand_variable("GLOBAL_FILE");
  284. if (global_filename.empty()) {
  285. cerr << "No definition given for $[GLOBAL_FILE], cannot process.\n";
  286. return false;
  287. }
  288. PPCommandFile global(_def_scope);
  289. if (!global.read_file(global_filename)) {
  290. cerr << "Error reading global definition file "
  291. << global_filename << ".\n";
  292. return false;
  293. }
  294. return true;
  295. }
  296. ////////////////////////////////////////////////////////////////////
  297. // Function: PPMain::get_cwd
  298. // Access: Private, Static
  299. // Description: Calls the system getcwd(), automatically allocating a
  300. // large enough string.
  301. ////////////////////////////////////////////////////////////////////
  302. string PPMain::
  303. get_cwd() {
  304. static size_t bufsize = 1024;
  305. static char *buffer = NULL;
  306. if (buffer == (char *)NULL) {
  307. buffer = new char[bufsize];
  308. }
  309. while (getcwd(buffer, bufsize) == (char *)NULL) {
  310. if (errno != ERANGE) {
  311. perror("getcwd");
  312. return string();
  313. }
  314. delete[] buffer;
  315. bufsize = bufsize * 2;
  316. buffer = new char[bufsize];
  317. assert(buffer != (char *)NULL);
  318. }
  319. return string(buffer);
  320. }