diff options
author | Marius Kintel <marius@kintel.net> | 2012-02-17 22:05:36 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2012-02-17 22:05:36 (GMT) |
commit | 2316127e62ba4c4c0e49cd35d869fcaeca357a29 (patch) | |
tree | d4876248cb049d58583d97bb1b716db6815904b2 | |
parent | 6845399e497726958d51170f906474e2624848c4 (diff) |
Handle include dependencies
-rw-r--r-- | src/MainWindow.h | 4 | ||||
-rw-r--r-- | src/ModuleCache.cc | 26 | ||||
-rw-r--r-- | src/ModuleCache.h | 2 | ||||
-rw-r--r-- | src/lexer.l | 10 | ||||
-rw-r--r-- | src/mainwin.cc | 47 | ||||
-rw-r--r-- | src/module.cc | 20 | ||||
-rw-r--r-- | src/module.h | 6 |
7 files changed, 79 insertions, 36 deletions
diff --git a/src/MainWindow.h b/src/MainWindow.h index 4110b45..ed12f34 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -77,8 +77,8 @@ private: AbstractNode *find_root_tag(AbstractNode *n); void updateTemporalVariables(); bool fileChangedOnDisk(); - void compileTopLevelDocument(bool reload); - void compile(bool reload, bool procevents); + bool compileTopLevelDocument(bool reload); + bool compile(bool reload, bool procevents); void compileCSG(bool procevents); bool maybeSave(); bool checkModified(); diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc index 7a0fe51..e974a03 100644 --- a/src/ModuleCache.cc +++ b/src/ModuleCache.cc @@ -6,10 +6,12 @@ #include "boosty.h" #include <boost/format.hpp> #include <boost/filesystem.hpp> +#include <boost/foreach.hpp> #include <stdio.h> #include <fstream> #include <sstream> +#include <time.h> #include <sys/stat.h> /*! @@ -18,10 +20,18 @@ ModuleCache *ModuleCache::inst = NULL; +static bool is_modified(const std::string &filename, const time_t &mtime) +{ + struct stat st; + memset(&st, 0, sizeof(struct stat)); + stat(filename.c_str(), &st); + return (st.st_mtime > mtime); +} + Module *ModuleCache::evaluate(const std::string &filename) { Module *lib_mod = NULL; - + // Create cache ID struct stat st; memset(&st, 0, sizeof(struct stat)); @@ -35,8 +45,14 @@ Module *ModuleCache::evaluate(const std::string &filename) #ifdef DEBUG PRINTB("Using cached library: %s (%s)", filename % cache_id); #endif - PRINTB("%s", this->entries[filename].msg); lib_mod = &(*this->entries[filename].module); + + BOOST_FOREACH(const Module::IncludeContainer::value_type &item, lib_mod->includes) { + if (is_modified(item.first, item.second)) { + lib_mod = NULL; + break; + } + } } // If cache lookup failed (non-existing or old timestamp), compile module @@ -59,9 +75,10 @@ Module *ModuleCache::evaluate(const std::string &filename) print_messages_push(); - cache_entry e = { NULL, cache_id, std::string("WARNING: Library `") + filename + "' tries to recursively use itself!" }; - if (this->entries.find(filename) != this->entries.end()) + cache_entry e = { NULL, cache_id }; + if (this->entries.find(filename) != this->entries.end()) { delete this->entries[filename].module; + } this->entries[filename] = e; std::string pathname = boosty::stringy(fs::path(filename).parent_path()); @@ -69,7 +86,6 @@ Module *ModuleCache::evaluate(const std::string &filename) if (lib_mod) { this->entries[filename].module = lib_mod; - this->entries[filename].msg = print_messages_stack.back(); } else { this->entries.erase(filename); } diff --git a/src/ModuleCache.h b/src/ModuleCache.h index 25ae192..1e6373d 100644 --- a/src/ModuleCache.h +++ b/src/ModuleCache.h @@ -17,7 +17,7 @@ private: struct cache_entry { class Module *module; - std::string cache_id, msg; + std::string cache_id; }; boost::unordered_map<std::string, cache_entry> entries; }; diff --git a/src/lexer.l b/src/lexer.l index 5e24e7f..884275e 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -30,6 +30,7 @@ #include "printutils.h" #include "parsersettings.h" #include "parser_yacc.h" +#include "module.h" #include <assert.h> #include <boost/foreach.hpp> #include <boost/lexical_cast.hpp> @@ -52,7 +53,8 @@ int lexerget_lineno(void); static void yyunput(int, char*) __attribute__((unused)); #endif extern const char *parser_input_buffer; - extern std::string parser_source_path; +extern std::string parser_source_path; +extern Module *currmodule; #define YY_INPUT(buf,result,max_size) { \ if (yyin && yyin != stdin) { \ @@ -219,8 +221,10 @@ void includefile() filepath.clear(); path_stack.push_back(finfo.parent_path()); - handle_dep(boosty::absolute(finfo).string()); - yyin = fopen(boosty::absolute(finfo).string().c_str(), "r"); + std::string fullname = boosty::absolute(finfo).string(); + handle_dep(fullname); + currmodule->registerInclude(fullname); + yyin = fopen(fullname.c_str(), "r"); if (!yyin) { PRINTB("WARNING: Can't open input file '%s'.", filename); path_stack.pop_back(); diff --git a/src/mainwin.cc b/src/mainwin.cc index 3708013..b9544d5 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -79,6 +79,7 @@ #include <algorithm> #include <boost/foreach.hpp> +#include <boost/version.hpp> #include <sys/stat.h> #ifdef ENABLE_CGAL @@ -598,10 +599,13 @@ AbstractNode *MainWindow::find_root_tag(AbstractNode *n) /*! Parse and evaluate the design => this->root_node + + Returns true if something was compiled, false if nothing was changed + and the root_node was left untouched. */ -void MainWindow::compile(bool reload, bool procevents) +bool MainWindow::compile(bool reload, bool procevents) { - compileTopLevelDocument(reload); + if (!compileTopLevelDocument(reload)) return false; // Invalidate renderers before we kill the CSG tree this->glview->setRenderer(NULL); @@ -661,6 +665,8 @@ void MainWindow::compile(bool reload, bool procevents) } if (procevents) QApplication::processEvents(); } + + return true; } /*! @@ -1000,13 +1006,15 @@ bool MainWindow::fileChangedOnDisk() If reload is true, does a timestamp check on the document and tries to reload it. Otherwise, just reparses the current document and any dependencies, updates the GUI accordingly and populates this->root_module. + + Returns true if anything was compiled. */ -void MainWindow::compileTopLevelDocument(bool reload) +bool MainWindow::compileTopLevelDocument(bool reload) { - bool shouldcompiletoplevel = true; + bool shouldcompiletoplevel = !reload; - if (reload && fileChangedOnDisk()) { - if (!checkModified()) shouldcompiletoplevel = false; + if (reload && fileChangedOnDisk() && checkModified()) { + shouldcompiletoplevel = true; refreshDocument(); } @@ -1046,17 +1054,18 @@ void MainWindow::compileTopLevelDocument(bool reload) } } + bool changed = shouldcompiletoplevel; if (this->root_module) { - this->root_module->handleDependencies(); - PRINTB("Module cache size: %d modules", ModuleCache::instance()->size()); + changed |= this->root_module->handleDependencies(); + if (changed) PRINTB("Module cache size: %d modules", ModuleCache::instance()->size()); } + + return changed; } void MainWindow::checkAutoReload() { - if (GuiLocker::isLocked()) return; - GuiLocker lock; - compile(true, true); + if (!this->fileName.isEmpty()) actionReloadCompile(); } void MainWindow::autoReloadSet(bool on) @@ -1091,17 +1100,12 @@ void MainWindow::actionReloadCompile() { if (GuiLocker::isLocked()) return; GuiLocker lock; - - if (!checkModified()) return; - + setCurrentOutput(); console->clear(); - refreshDocument(); - - setCurrentOutput(); - PRINT("Parsing design (AST generation)..."); - QApplication::processEvents(); - compile(true, true); + // PRINT("Parsing design (AST generation)..."); + // QApplication::processEvents(); + if (!compile(true, true)) return; if (this->root_node) compileCSG(true); // Go to non-CGAL view mode @@ -1123,7 +1127,6 @@ void MainWindow::actionCompile() { if (GuiLocker::isLocked()) return; GuiLocker lock; - setCurrentOutput(); console->clear(); @@ -1819,7 +1822,7 @@ void MainWindow::consoleOutput(const std::string &msg, void *userdata) void MainWindow::setCurrentOutput() { - set_output_handler(&MainWindow::consoleOutput, this); +// set_output_handler(&MainWindow::consoleOutput, this); } void MainWindow::clearCurrentOutput() diff --git a/src/module.cc b/src/module.cc index f049da1..69623dd 100644 --- a/src/module.cc +++ b/src/module.cc @@ -34,6 +34,7 @@ #include <boost/foreach.hpp> #include <sstream> +#include <sys/stat.h> AbstractModule::~AbstractModule() { @@ -203,18 +204,33 @@ std::string Module::dump(const std::string &indent, const std::string &name) con return dump.str(); } -void Module::handleDependencies() +void Module::registerInclude(const std::string &filename) { -// PRINTB_NOCACHE("Module::handleDependencies(): %p (%d libs %p)", this % this->usedlibs.size() % &this->usedlibs); + struct stat st; + memset(&st, 0, sizeof(struct stat)); + stat(filename.c_str(), &st); + this->includes[filename] = st.st_mtime; +} + +/*! + Check if any dependencies have been modified and recompile them. + Returns true if anything was recompiled. +*/ +bool Module::handleDependencies() +{ + bool changed = false; // Iterating manually since we want to modify the container while iterating Module::ModuleContainer::iterator iter = this->usedlibs.begin(); while (iter != this->usedlibs.end()) { Module::ModuleContainer::iterator curr = iter++; + Module *oldmodule = curr->second; curr->second = ModuleCache::instance()->evaluate(curr->first); + if (curr->second != oldmodule) changed = true; PRINTB_NOCACHE(" %s: %p", curr->first % curr->second); if (!curr->second) { PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", curr->first); this->usedlibs.erase(curr); } } + return changed; } diff --git a/src/module.h b/src/module.h index a490129..cd25287 100644 --- a/src/module.h +++ b/src/module.h @@ -3,6 +3,7 @@ #include <string> #include <vector> +#include <list> #include <boost/unordered_map.hpp> #include "value.h" @@ -67,7 +68,10 @@ public: typedef boost::unordered_map<std::string, class Module*> ModuleContainer; ModuleContainer usedlibs; - void handleDependencies(); + void registerInclude(const std::string &filename); + typedef boost::unordered_map<std::string, time_t> IncludeContainer; + IncludeContainer includes; + bool handleDependencies(); std::vector<std::string> assignments_var; std::vector<Expression*> assignments_expr; |