diff --git a/src/DynareMain.cc b/src/DynareMain.cc index 37990b86b130ef92aa96bb674ddeb256070c2fae..06a1e547ded9cd767f4e1524d4b167169261408a 100644 --- a/src/DynareMain.cc +++ b/src/DynareMain.cc @@ -52,7 +52,8 @@ void main2(stringstream &in, const string &basename, bool debug, bool clear_all, const filesystem::path &dynareroot, bool onlymodel); void main1(const string &filename, const string &basename, istream &modfile, bool debug, bool save_macro, string &save_macro_file, - bool no_line_macro, bool no_empty_line_macro, const vector<pair<string, string>> &defines, const vector<string> &path, stringstream ¯o_output); + bool no_line_macro, bool no_empty_line_macro, const vector<pair<string, string>> &defines, + vector<filesystem::path> &paths, stringstream ¯o_output); void usage() @@ -155,7 +156,7 @@ main(int argc, char **argv) bool compute_xrefs = false; bool transform_unary_ops = false; vector<pair<string, string>> defines; - vector<string> path; + vector<filesystem::path> paths; FileOutputType output_mode{FileOutputType::none}; JsonOutputPointType json{JsonOutputPointType::nojson}; JsonFileOutputType json_output_mode{JsonFileOutputType::file}; @@ -284,7 +285,7 @@ main(int argc, char **argv) << "must not be separated from -I by whitespace." << endl; usage(); } - path.push_back(s.substr(2)); + paths.push_back(s.substr(2)); } else if (s.substr(0, 6) == "output") { @@ -409,12 +410,12 @@ main(int argc, char **argv) // it to paths before macroprocessing vector<string> config_include_paths = config_file.getIncludePaths(); for (const auto &it : config_include_paths) - path.push_back(it); + paths.emplace_back(it); // Do macro processing stringstream macro_output; main1(filename, basename, modfile, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro, - defines, path, macro_output); + defines, paths, macro_output); if (only_macro) return EXIT_SUCCESS; diff --git a/src/DynareMain1.cc b/src/DynareMain1.cc index 7b44da8c9697bc306ec37d0b94d7abbe4428c53e..621d178e128c05d9ff666a28138e923243d6548c 100644 --- a/src/DynareMain1.cc +++ b/src/DynareMain1.cc @@ -19,6 +19,7 @@ #include <sstream> #include <fstream> +#include <filesystem> #include "macro/Driver.hh" @@ -28,14 +29,13 @@ bool compareNewline (int i, int j) { void main1(const string &filename, const string &basename, istream &modfile, bool debug, bool save_macro, string &save_macro_file, - bool no_line_macro_arg, bool no_empty_line_macro, const vector<pair<string, string>> &defines, const vector<string> &path, - stringstream ¯o_output) + bool no_line_macro_arg, bool no_empty_line_macro, const vector<pair<string, string>> &defines, + vector<filesystem::path> &paths, stringstream ¯o_output) { // Do macro processing macro::Environment env = macro::Environment(); - vector<string> paths; - macro::Driver m(env, paths, no_line_macro_arg); - m.parse(filename, basename, modfile, macro_output, debug, defines, path); + macro::Driver m(env, no_line_macro_arg); + m.parse(filename, basename, modfile, macro_output, debug, defines, paths); if (save_macro) { if (save_macro_file.empty()) diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc index b7c09e74d8655801049a17d7a3656f4f8745b497..899399b6e1fd6afaabc65d578c65f018d68bf295 100644 --- a/src/macro/Directives.cc +++ b/src/macro/Directives.cc @@ -25,7 +25,7 @@ using namespace macro; void -Eval::interpret(ostream &output, bool no_line_macro) +Eval::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { try { @@ -43,44 +43,37 @@ Eval::interpret(ostream &output, bool no_line_macro) } void -Include::interpret(ostream &output, bool no_line_macro) +Include::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { -#ifdef _WIN32 - string FILESEP = "\\"; -#else - string FILESEP = "/"; -#endif + using namespace filesystem; try { StringPtr msp = dynamic_pointer_cast<String>(expr->eval()); if (!msp) throw StackTrace("File name does not evaluate to a string"); - string filename = msp->to_string(); + path filename = msp->to_string(); ifstream incfile(filename, ios::binary); if (incfile.fail()) { - ostringstream dirs; - dirs << "." << FILESEP << endl; - for (const auto & path : paths) + for (auto file : paths) { - string testfile = path + FILESEP + filename; - incfile = ifstream(testfile, ios::binary); + file /= filename; + incfile = ifstream(file, ios::binary); if (incfile.good()) break; - dirs << path << endl; } if (incfile.fail()) - error(StackTrace("@#includepath", "Could not open " + filename + - ". The following directories were searched:\n" + dirs.str(), location)); + { + ostringstream errmsg; + errmsg << " * " << current_path().string() << endl; + for (auto & dir : paths) + errmsg << " * " << absolute(dir).string() << endl; + error(StackTrace("@#includepath", "Could not open " + filename.string() + + ". The following directories were searched:\n" + errmsg.str(), location)); + } } - - string basename = filename; - size_t pos = basename.find_last_of('.'); - if (pos != string::npos) - basename.erase(pos); - - Driver m(env, paths, no_line_macro); - m.parse(filename, basename, incfile, output, false, vector<pair<string, string>>{}, paths); + Driver m(env, no_line_macro); + m.parse(filename, filename.stem(), incfile, output, false, vector<pair<string, string>>{}, paths); } catch (StackTrace &ex) { @@ -94,13 +87,19 @@ Include::interpret(ostream &output, bool no_line_macro) } void -IncludePath::interpret(ostream &output, bool no_line_macro) +IncludePath::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { + using namespace filesystem; try { StringPtr msp = dynamic_pointer_cast<String>(expr->eval()); if (!msp) throw StackTrace("File name does not evaluate to a string"); + path ip = static_cast<string>(*msp); + if (!is_directory(ip)) + throw StackTrace(ip.string() + " does not evaluate to a valid directory"); + if (!exists(ip)) + warning(StackTrace("@#includepath", ip.string() + " does not exist", location)); paths.emplace_back(*msp); } catch (StackTrace &ex) @@ -115,7 +114,7 @@ IncludePath::interpret(ostream &output, bool no_line_macro) } void -Define::interpret(ostream &output, bool no_line_macro) +Define::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { try { @@ -138,7 +137,7 @@ Define::interpret(ostream &output, bool no_line_macro) } void -Echo::interpret(ostream &output, bool no_line_macro) +Echo::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { try { @@ -157,7 +156,7 @@ Echo::interpret(ostream &output, bool no_line_macro) } void -Error::interpret(ostream &output, bool no_line_macro) +Error::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { try { @@ -175,7 +174,7 @@ Error::interpret(ostream &output, bool no_line_macro) } void -EchoMacroVars::interpret(ostream &output, bool no_line_macro) +EchoMacroVars::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { if (save) env.print(output, vars, location.begin.line, true); @@ -185,7 +184,7 @@ EchoMacroVars::interpret(ostream &output, bool no_line_macro) } void -For::interpret(ostream &output, bool no_line_macro) +For::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { ArrayPtr ap; try @@ -234,14 +233,14 @@ For::interpret(ostream &output, bool no_line_macro) statement->printLineInfo(output, no_line_macro); printLine = false; } - statement->interpret(output, no_line_macro); + statement->interpret(output, no_line_macro, paths); } } printEndLineInfo(output, no_line_macro); } void -If::interpret(ostream &output, bool no_line_macro) +If::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { for (auto & it : expr_and_body) try @@ -254,7 +253,7 @@ If::interpret(ostream &output, bool no_line_macro) "The condition must evaluate to a boolean or a double", location)); if ((bp && *bp) || (dp && *dp)) { - interpretBody(it.second, output, no_line_macro); + interpretBody(it.second, output, no_line_macro, paths); break; } } @@ -271,7 +270,7 @@ If::interpret(ostream &output, bool no_line_macro) } void -If::interpretBody(const vector<DirectivePtr> &body, ostream &output, bool no_line_macro) +If::interpretBody(const vector<DirectivePtr> &body, ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { bool printLine = !no_line_macro; for (auto & statement : body) @@ -281,12 +280,12 @@ If::interpretBody(const vector<DirectivePtr> &body, ostream &output, bool no_lin statement->printLineInfo(output, no_line_macro); printLine = false; } - statement->interpret(output, no_line_macro); + statement->interpret(output, no_line_macro, paths); } } void -Ifdef::interpret(ostream &output, bool no_line_macro) +Ifdef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { for (auto & it : expr_and_body) { @@ -294,7 +293,7 @@ Ifdef::interpret(ostream &output, bool no_line_macro) if (dynamic_pointer_cast<BaseType>(it.first) || (vp && env.isVariableDefined(vp->getName()))) { - interpretBody(it.second, output, no_line_macro); + interpretBody(it.second, output, no_line_macro, paths); break; } } @@ -302,7 +301,7 @@ Ifdef::interpret(ostream &output, bool no_line_macro) } void -Ifndef::interpret(ostream &output, bool no_line_macro) +Ifndef::interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) { for (auto & it : expr_and_body) { @@ -310,7 +309,7 @@ Ifndef::interpret(ostream &output, bool no_line_macro) if (!(dynamic_pointer_cast<BaseType>(it.first) || (vp && env.isVariableDefined(vp->getName())))) { - interpretBody(it.second, output, no_line_macro); + interpretBody(it.second, output, no_line_macro, paths); break; } } diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh index 045caa6a6733e365c2b527901a906460f97cb94c..d3cb71479dd40830e79d6a98108bd66a14739f6e 100644 --- a/src/macro/Directives.hh +++ b/src/macro/Directives.hh @@ -22,6 +22,8 @@ #include "Expressions.hh" +#include <filesystem> + namespace macro { class Directive : public Node @@ -30,7 +32,7 @@ namespace macro public: Directive(Environment &env_arg, Tokenizer::location location_arg) : Node(env_arg, move(location_arg)) { } // Directives can be interpreted - virtual void interpret(ostream &output, bool no_line_macro) = 0; + virtual void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) = 0; }; @@ -44,7 +46,7 @@ namespace macro public: TextNode(string text_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), text{move(text_arg)} { } - inline void interpret(ostream &output, bool no_line_macro) override { output << text; } + inline void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override { output << text; } }; @@ -58,7 +60,7 @@ namespace macro public: Eval(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -66,11 +68,10 @@ namespace macro { private: const ExpressionPtr expr; - vector<string> &paths; public: - Include(ExpressionPtr expr_arg, Environment &env_arg, vector<string> &paths_arg, Tokenizer::location location_arg) : - Directive(env_arg, move(location_arg)), expr{move(expr_arg)}, paths{paths_arg} { } - void interpret(ostream &output, bool no_line_macro) override; + Include(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : + Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -78,11 +79,10 @@ namespace macro { private: const ExpressionPtr expr; - vector<string> &paths; public: - IncludePath(ExpressionPtr expr_arg, Environment &env_arg, vector<string> &paths_arg, Tokenizer::location location_arg) : - Directive(env_arg, move(location_arg)), expr{move(expr_arg)}, paths{paths_arg} { } - void interpret(ostream &output, bool no_line_macro) override; + IncludePath(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : + Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -101,7 +101,7 @@ namespace macro ExpressionPtr value_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -113,7 +113,7 @@ namespace macro Echo(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -125,7 +125,7 @@ namespace macro Error(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -141,7 +141,7 @@ namespace macro EchoMacroVars(bool save_arg, vector<string> vars_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), save{save_arg}, vars{move(vars_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -158,7 +158,7 @@ namespace macro Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), index_vec{move(index_vec_arg)}, index_vals{move(index_vals_arg)}, statements{move(statements_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -178,9 +178,9 @@ namespace macro If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, Environment &env_arg, Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)} { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; protected: - void interpretBody(const vector<DirectivePtr> &body, ostream &output, bool no_line_macro); + void interpretBody(const vector<DirectivePtr> &body, ostream &output, bool no_line_macro, vector<filesystem::path> &paths); }; @@ -190,7 +190,7 @@ namespace macro Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, Environment &env_arg, Tokenizer::location location_arg) : If(move(expr_and_body_arg), env_arg, move(location_arg)) { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; @@ -200,7 +200,7 @@ namespace macro Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, Environment &env_arg, Tokenizer::location location_arg) : If(move(expr_and_body_arg), env_arg, move(location_arg)) { } - void interpret(ostream &output, bool no_line_macro) override; + void interpret(ostream &output, bool no_line_macro, vector<filesystem::path> &paths) override; }; } #endif diff --git a/src/macro/Driver.cc b/src/macro/Driver.cc index 49553d1a916ca4b7ee3413c56e2dda458f536334..2661091afd429fd069438f6a9f0bd547c5b489e8 100644 --- a/src/macro/Driver.cc +++ b/src/macro/Driver.cc @@ -24,11 +24,10 @@ using namespace macro; void Driver::parse(const string &file_arg, const string &basename_arg, istream &modfile, ostream &output, bool debug, const vector<pair<string, string>> &defines, - vector<string> paths_arg) + vector<filesystem::path> &paths) { file = file_arg; basename = basename_arg; - paths = move(paths_arg); if (!defines.empty()) { @@ -47,7 +46,7 @@ Driver::parse(const string &file_arg, const string &basename_arg, istream &modfi else command_line_defines_with_endl << "@#define " << define.first << " = \"" << define.second << "\"" << endl; } - Driver m(env, paths, true); + Driver m(env, true); istream is(command_line_defines_with_endl.rdbuf()); m.parse("command_line_defines", "command_line_defines", is, output, debug, vector<pair<string, string>>{}, paths); } @@ -72,7 +71,7 @@ Driver::parse(const string &file_arg, const string &basename_arg, istream &modfi statement->printLineInfo(output, no_line_macro); printLine = false; } - statement->interpret(output, no_line_macro); + statement->interpret(output, no_line_macro, paths); } } diff --git a/src/macro/Driver.hh b/src/macro/Driver.hh index 26d5ea7280e565cfb56c0ea3eed071b18293690f..c6997cdedfa57fbc85eab29d8c43565855955d01 100644 --- a/src/macro/Driver.hh +++ b/src/macro/Driver.hh @@ -29,6 +29,7 @@ #include "Expressions.hh" #include <stack> +#include <filesystem> // Declare TokenizerFlexLexer class #ifndef __FLEX_LEXER_H @@ -63,15 +64,13 @@ namespace macro { public: Environment &env; - //! The paths to search when looking for .mod files - vector<string> &paths; private: bool no_line_macro; vector<DirectivePtr> statements; stack<vector<DirectivePtr>> directive_stack; public: - Driver(Environment &env_arg, vector<string> &paths_arg, bool no_line_macro_arg) : - env{env_arg}, paths{paths_arg}, no_line_macro(no_line_macro_arg) { } + Driver(Environment &env_arg, bool no_line_macro_arg) : + env{env_arg}, no_line_macro(no_line_macro_arg) { } Driver(const Driver &) = delete; Driver(Driver &&) = delete; Driver & operator=(const Driver &) = delete; @@ -90,7 +89,7 @@ namespace macro //! Starts parsing a file, returns output in out void parse(const string &file_arg, const string &basename_arg, istream &modfile, ostream &output, bool debug, const vector<pair<string, string>> &defines, - vector<string> paths_arg); + vector<filesystem::path> &paths_arg); //! Name of main file being parsed string file; diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh index a82607001e51aa3f60886260123c18cb9081bd31..fdc3843a78a8b76610eb1dddf26096ac3416110e 100644 --- a/src/macro/Expressions.hh +++ b/src/macro/Expressions.hh @@ -94,6 +94,10 @@ namespace macro cerr << endl << "Macro-processing error: backtrace..." << endl << e.trace(); exit(EXIT_FAILURE); } + inline void warning(const StackTrace &e) const noexcept + { + cerr << endl << "Macro-processing warning: backtrace..." << endl << e.trace(); + } inline void printLineInfo(ostream &output, bool no_line_macro) const noexcept { if (!no_line_macro) diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index 51b2524576d30eef6c0c37d5985ee05c2ab5b308..b84009af4dd727985b8ee7d869efdadddfb68b63 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -126,9 +126,9 @@ directive : directive_one_line EOL ; directive_one_line : INCLUDE expr - { $$ = make_shared<Include>($2, driver.env, driver.paths, @$); } + { $$ = make_shared<Include>($2, driver.env, @$); } | INCLUDEPATH expr - { $$ = make_shared<IncludePath>($2, driver.env, driver.paths, @$); } + { $$ = make_shared<IncludePath>($2, driver.env, @$); } | DEFINE symbol EQUAL expr { $$ = make_shared<Define>($2, $4, driver.env, @$); } | DEFINE function EQUAL expr