diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ModuleCache.cc | 22 | ||||
-rw-r--r-- | src/func.cc | 2 | ||||
-rw-r--r-- | src/lexer.l | 84 | ||||
-rw-r--r-- | src/mainwin.cc | 20 | ||||
-rw-r--r-- | src/module.cc | 20 | ||||
-rw-r--r-- | src/module.h | 13 | ||||
-rw-r--r-- | src/parsersettings.cc | 56 | ||||
-rw-r--r-- | src/parsersettings.h | 5 |
8 files changed, 135 insertions, 87 deletions
diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc index 4944495..030cfa0 100644 --- a/src/ModuleCache.cc +++ b/src/ModuleCache.cc @@ -14,32 +14,26 @@ #include <time.h> #include <sys/stat.h> +//#include "parsersettings.h" /*! FIXME: Implement an LRU scheme to avoid having an ever-growing module cache */ 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); -} - FileModule *ModuleCache::evaluate(const std::string &filename) { + std::cout << "modcache eval" << filename << "\n"; FileModule *lib_mod = NULL; - // Create cache ID + // Create cache ID struct stat st; memset(&st, 0, sizeof(struct stat)); stat(filename.c_str(), &st); std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size); - // Lookup in cache + // Lookup in cache if (this->entries.find(filename) != this->entries.end() && this->entries[filename].cache_id == cache_id) { #ifdef DEBUG @@ -48,15 +42,15 @@ FileModule *ModuleCache::evaluate(const std::string &filename) #endif lib_mod = &(*this->entries[filename].module); - BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, lib_mod->includes) { - if (is_modified(item.first, item.second)) { + BOOST_FOREACH(const FileModule::IncludeContainer::value_type &include, lib_mod->includes) { + if (lib_mod->include_modified(include.second)) { lib_mod = NULL; break; } } } - // If cache lookup failed (non-existing or old timestamp), compile module + // If cache lookup failed (non-existing or old timestamp), compile module if (!lib_mod) { #ifdef DEBUG if (this->entries.find(filename) != this->entries.end()) { @@ -91,7 +85,7 @@ FileModule *ModuleCache::evaluate(const std::string &filename) if (lib_mod) { // We defer deletion so we can ensure that the new module won't - // have the same address as the old + // have the same address as the old delete oldmodule; this->entries[filename].module = lib_mod; } else { diff --git a/src/func.cc b/src/func.cc index 18884b8..eaaae74 100644 --- a/src/func.cc +++ b/src/func.cc @@ -64,6 +64,7 @@ AbstractFunction::~AbstractFunction() Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const { + (void)evalctx; // unusued parameter return Value(); } @@ -500,6 +501,7 @@ Value builtin_search(const Context *, const EvalContext *evalctx) Value builtin_version(const Context *, const EvalContext *evalctx) { + (void)evalctx; // unusued parameter Value::VectorType val; val.push_back(Value(double(OPENSCAD_YEAR))); val.push_back(Value(double(OPENSCAD_MONTH))); diff --git a/src/lexer.l b/src/lexer.l index 6dfe9bc..0084d93 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -113,29 +113,15 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); } [^\t\r\n>]+ { filename = yytext; } ">" { BEGIN(INITIAL); - fs::path usepath; - if (boosty::is_absolute(fs::path(filename))) { - usepath = filename; - } - else { - usepath = sourcepath() / filename; - if (!fs::exists(usepath)) { - usepath = locate_file(filename); - } - } - /* Only accept regular files which exists */ - if (usepath.has_parent_path() && fs::exists(usepath) && !fs::is_directory(usepath)) { - handle_dep(usepath.string()); - parserlval.text = strdup(usepath.string().c_str()); - return TOK_USE; - } else { + fs::path fullpath = find_valid_path( sourcepath(), filename, openfilenames ); + if ( fullpath.empty() ) { PRINTB("WARNING: Can't open 'use' file '%s'.", filename); - if ( filename.size() == 0 ) - PRINT("WARNING: 'use' filename is blank"); - else if ( fs::is_directory( usepath ) ) - PRINTB("WARNING: 'use' file points to a directory: %s",filename); - } - } + } else { + handle_dep(fullpath.string()); + parserlval.text = strdup(fullpath.string().c_str()); + return TOK_USE; + } + } } <<EOF>> { @@ -206,55 +192,43 @@ fs::path sourcepath() Rules for include <path/file> 1) include <sourcepath/path/file> 2) include <librarydir/path/file> + + Globals used: filepath, sourcepath, filename */ void includefile() { - if (filename.empty()) return; - - fs::path dirinfo = sourcepath(); - if (!filepath.empty()) { - if (boosty::is_absolute(fs::path(filepath))) { - dirinfo = filepath; - } - else { - dirinfo /= filepath; - } + PRINTB("lex includefile filename %s",filename.c_str()); + PRINTB("lex includefile filepath %s",filepath.c_str()); + PRINTB("lex includefile sourcepath %s",sourcepath().c_str()); + BOOST_FOREACH(std::string of, openfilenames ) { + PRINTB("lex includefile openfilename: %s",of); } - fs::path finfo = dirinfo / filename; - if (!exists(finfo)) { - finfo = locate_file((fs::path(filepath) / filename).string()); - } + rootmodule->registerInclude(filename); - if (!exists(finfo) || finfo.empty()) { - // deal with some unusual situations with is_absolute() and Wine - fs::path fnp( fs::path(filepath) / filename ); - if (fs::exists( fnp ) && !fs::is_directory( fnp )) { - finfo = fnp; - } - } + fs::path fullpath = find_valid_path( sourcepath(), filename, openfilenames ); + if ( fullpath.empty() ) { + PRINTB("WARNING: Can't open 'include' file '%s'.", filename); + if (path_stack.size()>0) path_stack.pop_back(); + return; + }; + PRINTB("lex fullpath %s",fullpath ); - if (finfo.empty()) { - PRINTB("WARNING: Can't find 'include' file '%s'.", filename); - } - - std::string fullname = boosty::absolute(finfo).string(); - // Detect circular includes - BOOST_FOREACH(std::string &s, openfilenames) { - if (s == fullname) return; - } + std::string fullname = boosty::stringy( fullpath ); + PRINTB("lex fullname %s",fullname ); filepath.clear(); - path_stack.push_back(finfo.parent_path()); + path_stack.push_back(fullpath.parent_path()); handle_dep(fullname); - rootmodule->registerInclude(fullname); + yyin = fopen(fullname.c_str(), "r"); if (!yyin) { - PRINTB("WARNING: Can't open 'include' file '%s'.", filename); + PRINTB("WARNING: Can't open 'include' file '%s'.", fullname); path_stack.pop_back(); return; } + openfiles.push_back(yyin); openfilenames.push_back(fullname); filename.clear(); diff --git a/src/mainwin.cc b/src/mainwin.cc index 1ac96fa..a7b7a30 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -615,7 +615,9 @@ void MainWindow::refreshDocument() */ bool MainWindow::compile(bool reload, bool procevents) { + PRINT("compile"); if (!compileTopLevelDocument(reload)) return false; + PRINT("init render"); // Invalidate renderers before we kill the CSG tree this->qglview->setRenderer(NULL); @@ -1018,22 +1020,18 @@ bool MainWindow::fileChangedOnDisk() return false; } -// FIXME: The following two methods are duplicated in ModuleCache.cc - refactor -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); -} - bool MainWindow::includesChanged() { + PRINT("includes changed?"); if (this->root_module) { BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, this->root_module->includes) { - if (is_modified(item.first, item.second)) return true; + //std::cout<< item.first << "second" << item.second << "\n"; + //std::cout<< (is_modified(item.first, item.second)) <<"\n"; + if (this->root_module->include_modified(item.second)) + return true; } } + PRINT("includes not changed"); return false; } @@ -1046,6 +1044,7 @@ bool MainWindow::includesChanged() */ bool MainWindow::compileTopLevelDocument(bool reload) { + PRINT("compile top level"); bool shouldcompiletoplevel = !reload; if (includesChanged()) shouldcompiletoplevel = true; @@ -1056,6 +1055,7 @@ bool MainWindow::compileTopLevelDocument(bool reload) } if (shouldcompiletoplevel) { + PRINT("shouldcompile top level"); console->clear(); updateTemporalVariables(); diff --git a/src/module.cc b/src/module.cc index e853457..2c7246e 100644 --- a/src/module.cc +++ b/src/module.cc @@ -46,6 +46,8 @@ AbstractModule::~AbstractModule() AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { + (void)ctx; // avoid unusued parameter warning + AbstractNode *node = new AbstractNode(inst); node->children = inst->instantiateChildren(evalctx); @@ -196,10 +198,12 @@ std::string Module::dump(const std::string &indent, const std::string &name) con void FileModule::registerInclude(const std::string &filename) { + PRINTB("filemodule reginclude %s", filename); struct stat st; memset(&st, 0, sizeof(struct stat)); - stat(filename.c_str(), &st); - this->includes[filename] = st.st_mtime; + bool valid = stat(filename.c_str(), &st); + IncludeFile inc = {filename,valid,st.st_mtime}; + this->includes[filename] = inc; } /*! @@ -250,3 +254,15 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat return node; } + +bool FileModule::include_modified(IncludeFile inc) +{ + struct stat st; + memset(&st, 0, sizeof(struct stat)); + // todo - search paths + bool valid = stat(inc.filename.c_str(), &st); + if (inc.valid != valid) return true; + if (st.st_mtime > inc.mtime) return true; + return false; +} + diff --git a/src/module.h b/src/module.h index 9f46d37..fa255e1 100644 --- a/src/module.h +++ b/src/module.h @@ -5,6 +5,9 @@ #include <vector> #include <list> #include <boost/unordered_map.hpp> +#include <time.h> +#include <sys/stat.h> + #include "value.h" #include "typedefs.h" #include "localscope.h" @@ -74,6 +77,12 @@ public: LocalScope scope; }; +struct IncludeFile { + std::string filename; + bool valid; + time_t mtime; +}; + // FIXME: A FileModule doesn't have definition arguments, so we shouldn't really // inherit from a Module class FileModule : public Module @@ -90,9 +99,9 @@ public: typedef boost::unordered_map<std::string, class FileModule*> ModuleContainer; ModuleContainer usedlibs; - typedef boost::unordered_map<std::string, time_t> IncludeContainer; + typedef boost::unordered_map<std::string, struct IncludeFile> IncludeContainer; IncludeContainer includes; - + bool include_modified( struct IncludeFile inc ); private: bool is_handling_dependencies; std::string path; diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 8d82744..799949c 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -20,13 +20,63 @@ void add_librarydir(const std::string &libdir) Searces for the given file in library paths and returns the full path if found. Returns an empty path if file cannot be found or filename is a directory. */ -std::string locate_file(const std::string &filename) +fs::path search_libs(const std::string &filename) { BOOST_FOREACH(const std::string &dir, librarypath) { fs::path usepath = fs::path(dir) / filename; - if (fs::exists(usepath) && !fs::is_directory(usepath)) return usepath.string(); + if (fs::exists(usepath) && !fs::is_directory(usepath)) { + PRINTB("found %s in %s", filename % dir ); + return usepath.string(); + } + } + return fs::path(); +} + +// files must be 'ordinary' - they mus exist and be non-directories +bool check_valid( fs::path p, std::vector<std::string> openfilenames ) +{ + if (p.empty()) { + PRINTB("WARNING: %s invalid - file path is blank",p); + return false; + } + if (!p.has_parent_path()) { + PRINTB("WARNING: %s invalid - no parent path",p); + return false; + } + if (!fs::exists(p)) { + PRINTB("WARNING: %s invalid - file not found",p); + // searched === + return false; + } + if (fs::is_directory(p)) { + PRINTB("WARNING: %s invalid - points to a directory",p); + return false; } - return std::string(); + std::string fullname = boosty::stringy( p ); + BOOST_FOREACH(std::string &s, openfilenames) { + PRINTB("WARNING: circular include with %s", fullname); + if (s == fullname) return false; + } + return true; +} + +// check if file is valid, search path for valid simple file +// return empty path on failure +fs::path find_valid_path( fs::path sourcepath, std::string filename, + std::vector<std::string> openfilenames ) +{ + fs::path fpath = fs::path( filename ); + + if ( boosty::is_absolute( fpath ) ) + if ( check_valid( fpath, openfilenames ) ) + return boosty::absolute( fpath ); + + + fpath = sourcepath / filename; + if ( check_valid( fpath, openfilenames ) ) return fpath; + fpath = search_libs( filename ); + if ( check_valid( fpath, openfilenames ) ) return fpath; + return fs::path(); } void parser_init(const std::string &applicationpath) diff --git a/src/parsersettings.h b/src/parsersettings.h index 007aa9c..12b4a61 100644 --- a/src/parsersettings.h +++ b/src/parsersettings.h @@ -2,11 +2,14 @@ #define PARSERSETTINGS_H_ #include <string> +#include "boosty.h" extern int parser_error_pos; void parser_init(const std::string &applicationpath); void add_librarydir(const std::string &libdir); -std::string locate_file(const std::string &filename); +fs::path search_libs(const std::string &filename); +fs::path find_valid_path( fs::path sourcepath, std::string filename, + std::vector<std::string> openfilenames ); #endif |