diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index b538e6d..31da8ff 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -113,6 +113,18 @@ namespace chaiscript virtual ~Eval_Error() throw() {} }; + /** + * Errors generated when loading a file + */ + struct File_Not_Found_Error : public std::runtime_error { + File_Not_Found_Error(const std::string &filename) + : std::runtime_error("File Not Found: " + filename) + { } + + virtual ~File_Not_Found_Error() throw() {} + }; + + /** * Special type for returned values */ diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index a8be88a..7364925 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -225,6 +225,9 @@ namespace chaiscript std::map loaded_modules; std::set active_loaded_modules; + std::vector modulepaths; + std::vector usepaths; + Eval_Engine engine; @@ -301,26 +304,55 @@ namespace chaiscript void use(const std::string &filename) { -#ifndef CHAISCRIPT_NO_THREADS - boost::lock_guard l(use_mutex); - boost::shared_lock l2(mutex); -#endif - - if (loaded_files.count(filename) == 0) + for (size_t i = 0; i < usepaths.size(); ++i) { -#ifndef CHAISCRIPT_NO_THREADS - l2.unlock(); -#endif - eval_file(filename); - } else { - engine.sync_cache(); - } + try { + + const std::string appendedpath = usepaths[i] + filename; + +#ifndef CHAISCRIPT_NO_THREADS + boost::lock_guard l(use_mutex); + boost::shared_lock l2(mutex); +#endif + + if (loaded_files.count(appendedpath) == 0) + { +#ifndef CHAISCRIPT_NO_THREADS + l2.unlock(); +#endif + eval_file(appendedpath); + } else { + engine.sync_cache(); + } + } catch (const File_Not_Found_Error &) { + if (i == usepaths.size() - 1) + { + throw File_Not_Found_Error(filename); + } + + // failed to load, try the next path + } + + } + } public: - ChaiScript_System() { + ChaiScript_System(const std::vector &t_modulepaths = std::vector(), + const std::vector &t_usepaths = std::vector()) + : modulepaths(t_modulepaths), usepaths(t_usepaths) { + if (modulepaths.empty()) + { + modulepaths.push_back(""); + } + + if (usepaths.empty()) + { + usepaths.push_back(""); + } + loaded_files.insert("__EVAL__"); // Make sure the default name is already registered build_eval_system(); } @@ -408,18 +440,21 @@ namespace chaiscript postfixes.push_back(".so"); postfixes.push_back(""); - for (size_t i = 0; i < prefixes.size(); ++i) + for (size_t i = 0; i < modulepaths.size(); ++i) { - for (size_t j = 0; j < postfixes.size(); ++j) + for (size_t j = 0; j < prefixes.size(); ++j) + { + for (size_t k = 0; k < postfixes.size(); ++k) { - try { - std::string name = prefixes[i] + t_module_name + postfixes[j]; - load_module(t_module_name, name); - return; - } catch (const load_module_error &) { - // Try next set - } + try { + std::string name = modulepaths[i] + prefixes[j] + t_module_name + postfixes[k]; + load_module(t_module_name, name); + return; + } catch (const load_module_error &) { + // Try next set + } } + } } throw load_module_error("Unable to find module: " + t_module_name); @@ -495,7 +530,7 @@ namespace chaiscript std::ifstream infile (filename.c_str(), std::ios::in | std::ios::ate); if (!infile.is_open()) { - throw std::runtime_error("Can not open: " + filename); + throw File_Not_Found_Error(filename); } std::streampos size = infile.tellg(); diff --git a/src/main.cpp b/src/main.cpp index 4f4892b..878f9f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,29 @@ std::string get_next_command() { int main(int argc, char *argv[]) { std::string input; - chaiscript::ChaiScript chai; + + std::vector usepaths; + std::vector modulepaths; + + const char *usepath = getenv("CHAI_USE_PATH"); + const char *modulepath = getenv("CHAI_MODULE_PATH"); + + usepaths.push_back(""); + + if (usepath) + { + usepaths.push_back(usepath); + } + + modulepaths.push_back(""); + + if (modulepath) + { + modulepaths.push_back(modulepath); + } + + + chaiscript::ChaiScript chai(modulepaths,usepaths); chai.add(chaiscript::fun(&exit), "exit"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");