summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2012-02-17 22:05:36 (GMT)
committerMarius Kintel <marius@kintel.net>2012-02-17 22:05:36 (GMT)
commit2316127e62ba4c4c0e49cd35d869fcaeca357a29 (patch)
treed4876248cb049d58583d97bb1b716db6815904b2
parent6845399e497726958d51170f906474e2624848c4 (diff)
Handle include dependencies
-rw-r--r--src/MainWindow.h4
-rw-r--r--src/ModuleCache.cc26
-rw-r--r--src/ModuleCache.h2
-rw-r--r--src/lexer.l10
-rw-r--r--src/mainwin.cc47
-rw-r--r--src/module.cc20
-rw-r--r--src/module.h6
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;
contact: Jan Huwald // Impressum