summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/MainWindow.h2
-rw-r--r--src/ModuleCache.cc87
-rw-r--r--src/ModuleCache.h22
-rw-r--r--src/context.cc1
-rw-r--r--src/lexer.l3
-rw-r--r--src/mainwin.cc7
-rw-r--r--src/module.cc17
-rw-r--r--src/module.h9
-rw-r--r--src/openscad.cc3
-rw-r--r--src/openscad.h2
-rw-r--r--src/parser.y122
11 files changed, 165 insertions, 110 deletions
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 226689a..a0353a9 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -30,7 +30,7 @@ public:
QString autoReloadInfo;
Context root_ctx;
- AbstractModule *root_module; // Result of parsing
+ Module *root_module; // Result of parsing
ModuleInstantiation root_inst; // Top level instance
AbstractNode *absolute_root_node; // Result of tree evaluation
AbstractNode *root_node; // Root if the root modifier (!) is used
diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc
new file mode 100644
index 0000000..eaa7d33
--- /dev/null
+++ b/src/ModuleCache.cc
@@ -0,0 +1,87 @@
+#include "ModuleCache.h"
+#include "module.h"
+#include "printutils.h"
+#include "boosty.h"
+#include "openscad.h"
+
+#include <stdio.h>
+#include <sstream>
+#include <sys/stat.h>
+
+ModuleCache *ModuleCache::inst = NULL;
+
+Module *ModuleCache::evaluate(const std::string &filename)
+{
+ Module *cached = NULL;
+
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(filename.c_str(), &st);
+
+ std::stringstream idstream;
+ idstream << std::hex << st.st_mtime << "." << st.st_size;
+ std::string cache_id = idstream.str();
+
+ if (this->entries.find(filename) != this->entries.end() &&
+ this->entries[filename].cache_id == cache_id) {
+#ifdef DEBUG
+ PRINTB("Using cached library: %s (%s)", filename % cache_id);
+#endif
+ PRINTB("%s", this->entries[filename].msg);
+ cached = &(*this->entries[filename].module);
+ }
+
+ if (cached) {
+ cached->handleDependencies();
+ return cached;
+ }
+ else {
+ if (this->entries.find(filename) != this->entries.end()) {
+ PRINTB("Recompiling cached library: %s (%s)", filename % cache_id);
+ }
+ else {
+ PRINTB("Compiling library '%s'.", filename);
+ }
+ }
+
+ FILE *fp = fopen(filename.c_str(), "rt");
+ if (!fp) {
+ fprintf(stderr, "WARNING: Can't open library file '%s'\n", filename.c_str());
+ return NULL;
+ }
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+
+ 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())
+ delete this->entries[filename].module;
+ this->entries[filename] = e;
+
+ std::string pathname = boosty::stringy(fs::path(filename).parent_path());
+ Module *lib_mod = dynamic_cast<Module*>(parse(text.str().c_str(), pathname.c_str(), 0));
+
+ if (lib_mod) {
+ this->entries[filename].module = lib_mod;
+ this->entries[filename].msg = print_messages_stack.back();
+ } else {
+ this->entries.erase(filename);
+ }
+
+ print_messages_pop();
+
+ return lib_mod;
+}
+
+void ModuleCache::clear()
+{
+ this->entries.clear();
+}
+
diff --git a/src/ModuleCache.h b/src/ModuleCache.h
new file mode 100644
index 0000000..57ff2e7
--- /dev/null
+++ b/src/ModuleCache.h
@@ -0,0 +1,22 @@
+#include <string>
+#include <boost/unordered_map.hpp>
+
+class ModuleCache
+{
+public:
+ static ModuleCache *instance() { if (!inst) inst = new ModuleCache; return inst; }
+ class Module *evaluate(const std::string &filename);
+ void clear();
+
+private:
+ ModuleCache() {}
+ ~ModuleCache() {}
+
+ static ModuleCache *inst;
+
+ struct cache_entry {
+ class Module *module;
+ std::string cache_id, msg;
+ };
+ boost::unordered_map<std::string, cache_entry> entries;
+};
diff --git a/src/context.cc b/src/context.cc
index b9e685c..f96a45b 100644
--- a/src/context.cc
+++ b/src/context.cc
@@ -162,6 +162,7 @@ AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst) const
}
if (this->usedlibs_p) {
BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
+ assert(m.second);
if (m.second->modules.find(inst.name()) != m.second->modules.end()) {
Context ctx(this->parent, m.second);
return m.second->modules[inst.name()]->evaluate(&ctx, &inst);
diff --git a/src/lexer.l b/src/lexer.l
index 5644ded..11f2aff 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -52,7 +52,7 @@ int lexerget_lineno(void);
static void yyunput(int, char*) __attribute__((unused));
#endif
extern const char *parser_input_buffer;
-extern const char *parser_source_path;
+ extern std::string parser_source_path;
#define YY_INPUT(buf,result,max_size) { \
if (yyin && yyin != stdin) { \
@@ -108,6 +108,7 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); }
<cond_use>{
[^\t\r\n>]+ { filename = yytext; }
">" {
+ PRINTB("USE: %s", filename);
BEGIN(INITIAL);
fs::path usepath;
if (boosty::is_absolute(fs::path(filename))) {
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 9b24eea..8eebf09 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -25,6 +25,7 @@
*/
#include "PolySetCache.h"
+#include "ModuleCache.h"
#include "MainWindow.h"
#include "openscad.h" // examplesdir
#include "parsersettings.h"
@@ -695,6 +696,8 @@ void MainWindow::compile(bool procevents)
goto fail;
}
+ this->root_module->handleDependencies();
+
// Evaluate CSG tree
PRINT("Compiling design (CSG Tree generation)...");
if (procevents)
@@ -1449,7 +1452,7 @@ void MainWindow::actionFlushCaches()
#endif
dxf_dim_cache.clear();
dxf_cross_cache.clear();
- Module::clear_library_cache();
+ ModuleCache::instance()->clear();
}
void MainWindow::viewModeActionsUncheck()
@@ -1797,7 +1800,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 6641ff7..7ad2e33 100644
--- a/src/module.cc
+++ b/src/module.cc
@@ -25,11 +25,13 @@
*/
#include "module.h"
+#include "ModuleCache.h"
#include "node.h"
#include "context.h"
#include "expression.h"
#include "function.h"
#include "printutils.h"
+
#include <boost/foreach.hpp>
#include <sstream>
@@ -201,7 +203,18 @@ std::string Module::dump(const std::string &indent, const std::string &name) con
return dump.str();
}
-void Module::clear_library_cache()
+void Module::handleDependencies()
{
- Module::libs_cache.clear();
+ PRINTB_NOCACHE("Module::handleDependencies(): %p (%d libs %p)", this % this->usedlibs.size() % &this->usedlibs);
+ // 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++;
+ curr->second = ModuleCache::instance()->evaluate(curr->first);
+ 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);
+ }
+ }
}
diff --git a/src/module.h b/src/module.h
index 6c6529b..a490129 100644
--- a/src/module.h
+++ b/src/module.h
@@ -65,11 +65,9 @@ public:
void addChild(ModuleInstantiation *ch) { this->children.push_back(ch); }
- static Module *compile_library(const std::string &filename);
- static void clear_library_cache();
-
typedef boost::unordered_map<std::string, class Module*> ModuleContainer;
ModuleContainer usedlibs;
+ void handleDependencies();
std::vector<std::string> assignments_var;
std::vector<Expression*> assignments_expr;
@@ -87,11 +85,6 @@ public:
protected:
private:
- struct libs_cache_ent {
- Module *mod;
- std::string cache_id, msg;
- };
- static boost::unordered_map<std::string, libs_cache_ent> libs_cache;
};
#endif
diff --git a/src/openscad.cc b/src/openscad.cc
index 11dad7c..39e3f4c 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -255,7 +255,7 @@ int main(int argc, char **argv)
Context root_ctx;
register_builtin(root_ctx);
- AbstractModule *root_module;
+ Module *root_module;
ModuleInstantiation root_inst;
AbstractNode *root_node;
@@ -278,6 +278,7 @@ int main(int argc, char **argv)
std::string fpath = boosty::stringy(abspath.parent_path());
root_module = parse(text.str().c_str(), fpath.c_str(), false);
if (!root_module) exit(1);
+ root_module->handleDependencies();
}
fs::path fpath = boosty::absolute( fs::path(filename) );
diff --git a/src/openscad.h b/src/openscad.h
index dab14cd..8b49ba2 100644
--- a/src/openscad.h
+++ b/src/openscad.h
@@ -27,7 +27,7 @@
#ifndef OPENSCAD_H
#define OPENSCAD_H
-extern class AbstractModule *parse(const char *text, const char *path, int debug);
+extern class Module *parse(const char *text, const char *path, int debug);
extern int get_fragments_from_r(double r, double fn, double fs, double fa);
#include <string>
diff --git a/src/parser.y b/src/parser.y
index 15a754b..85fee48 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -43,7 +43,7 @@
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
-using namespace boost::filesystem;
+namespace fs = boost::filesystem;
#include "boosty.h"
int parser_error_pos = -1;
@@ -56,7 +56,7 @@ int lexerlex_destroy(void);
int lexerlex(void);
std::vector<Module*> module_stack;
-Module *module;
+Module *currmodule;
class ArgContainer {
public:
@@ -133,7 +133,7 @@ public:
input:
/* empty */ |
- TOK_USE { module->usedlibs[$1] = NULL; } input |
+ TOK_USE { currmodule->usedlibs[$1] = NULL; } input |
statement input ;
inner_input:
@@ -145,37 +145,38 @@ statement:
'{' inner_input '}' |
module_instantiation {
if ($1) {
- module->addChild($1);
+ currmodule->addChild($1);
} else {
delete $1;
}
} |
TOK_ID '=' expr ';' {
bool add_new_assignment = true;
- for (size_t i = 0; i < module->assignments_var.size(); i++) {
- if (module->assignments_var[i] != $1)
+ for (size_t i = 0; i < currmodule->assignments_var.size(); i++) {
+ if (currmodule->assignments_var[i] != $1)
continue;
- delete module->assignments_expr[i];
- module->assignments_expr[i] = $3;
+ delete currmodule->assignments_expr[i];
+ currmodule->assignments_expr[i] = $3;
add_new_assignment = false;
}
if (add_new_assignment) {
- module->assignments_var.push_back($1);
- module->assignments_expr.push_back($3);
+ currmodule->assignments_var.push_back($1);
+ currmodule->assignments_expr.push_back($3);
free($1);
}
} |
TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' {
- Module *p = module;
- module_stack.push_back(module);
- module = new Module();
- p->modules[$2] = module;
- module->argnames = $4->argnames;
- module->argexpr = $4->argexpr;
+ Module *p = currmodule;
+ module_stack.push_back(currmodule);
+ currmodule = new Module();
+ PRINTB_NOCACHE("New module: %s %p", $2 % currmodule);
+ p->modules[$2] = currmodule;
+ currmodule->argnames = $4->argnames;
+ currmodule->argexpr = $4->argexpr;
free($2);
delete $4;
} statement {
- module = module_stack.back();
+ currmodule = module_stack.back();
module_stack.pop_back();
} |
TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr {
@@ -183,7 +184,7 @@ statement:
func->argnames = $4->argnames;
func->argexpr = $4->argexpr;
func->expr = $8;
- module->functions[$2] = func;
+ currmodule->functions[$2] = func;
free($2);
delete $4;
} ';' ;
@@ -560,101 +561,34 @@ void yyerror (char const *s)
{
// FIXME: We leak memory on parser errors...
PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s);
- module = NULL;
+ currmodule = NULL;
}
extern void lexerdestroy();
extern FILE *lexerin;
extern const char *parser_input_buffer;
const char *parser_input_buffer;
-const char *parser_source_path;
+std::string parser_source_path;
-AbstractModule *parse(const char *text, const char *path, int debug)
+Module *parse(const char *text, const char *path, int debug)
{
+ PRINT_NOCACHE("New parser");
lexerin = NULL;
parser_error_pos = -1;
parser_input_buffer = text;
- parser_source_path = path;
+ parser_source_path = std::string(path);
module_stack.clear();
- module = new Module();
+ Module *rootmodule = currmodule = new Module();
+ PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule);
parserdebug = debug;
parserparse();
lexerdestroy();
lexerlex_destroy();
- if (!module)
- return NULL;
-
- // Iterating manually since we want to modify the container while iterating
- Module::ModuleContainer::iterator iter = module->usedlibs.begin();
- while (iter != module->usedlibs.end()) {
- Module::ModuleContainer::iterator curr = iter++;
- curr->second = Module::compile_library(curr->first);
- if (!curr->second) {
- PRINTB("WARNING: Failed to compile library '%s'.", curr->first);
- module->usedlibs.erase(curr);
- }
- }
+ if (!rootmodule) return NULL;
parser_error_pos = -1;
- return module;
-}
-
-boost::unordered_map<std::string, Module::libs_cache_ent> Module::libs_cache;
-
-Module *Module::compile_library(const std::string &filename)
-{
- struct stat st;
- memset(&st, 0, sizeof(struct stat));
- stat(filename.c_str(), &st);
-
- std::stringstream idstream;
- idstream << std::hex << st.st_mtime << "." << st.st_size;
- std::string cache_id = idstream.str();
-
- if (libs_cache.find(filename) != libs_cache.end() && libs_cache[filename].cache_id == cache_id) {
- PRINTB("%s", libs_cache[filename].msg);
- return &(*libs_cache[filename].mod);
- }
-
- FILE *fp = fopen(filename.c_str(), "rt");
- if (!fp) {
- fprintf(stderr, "WARNING: Can't open library file '%s'\n", filename.c_str());
- return NULL;
- }
- std::stringstream text;
- char buffer[513];
- int ret;
- while ((ret = fread(buffer, 1, 512, fp)) > 0) {
- buffer[ret] = 0;
- text << buffer;
- }
- fclose(fp);
-
- print_messages_push();
-
- PRINTB("Compiling library '%s'.", filename);
- libs_cache_ent e = { NULL, cache_id, std::string("WARNING: Library `") + filename + "' tries to recursively use itself!" };
- if (libs_cache.find(filename) != libs_cache.end())
- delete libs_cache[filename].mod;
- libs_cache[filename] = e;
-
- Module *backup_mod = module;
- std::string pathname = boosty::stringy( fs::path(filename).parent_path() );
- Module *lib_mod = dynamic_cast<Module*>(parse(text.str().c_str(), pathname.c_str(), 0));
- module = backup_mod;
-
- if (lib_mod) {
- libs_cache[filename].mod = lib_mod;
- libs_cache[filename].msg = print_messages_stack.back();
- } else {
- libs_cache.erase(filename);
- }
-
- print_messages_pop();
-
- return lib_mod;
+ return rootmodule;
}
-
contact: Jan Huwald // Impressum