From d7e70a40630985a154f81631ef894cda7194db43 Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Wed, 2 Oct 2019 17:38:42 +0200 Subject: [PATCH] macro processor: fix bug: interpret @#include at node level instead of at the Driver level --- src/DynareMain1.cc | 3 +- src/macro/Directives.cc | 40 +++++++++++++++++++--- src/macro/Directives.hh | 14 +++----- src/macro/Driver.cc | 42 +----------------------- src/macro/ForwardDeclarationsAndEnums.hh | 3 ++ src/macro/Parser.yy | 2 +- 6 files changed, 47 insertions(+), 57 deletions(-) diff --git a/src/DynareMain1.cc b/src/DynareMain1.cc index 28cefbe4..7b44da8c 100644 --- a/src/DynareMain1.cc +++ b/src/DynareMain1.cc @@ -33,7 +33,8 @@ main1(const string &filename, const string &basename, istream &modfile, bool deb { // Do macro processing macro::Environment env = macro::Environment(); - macro::Driver m(env, no_line_macro_arg); + vector<string> paths; + macro::Driver m(env, paths, no_line_macro_arg); m.parse(filename, basename, modfile, macro_output, debug, defines, path); if (save_macro) { diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc index 13777551..b7c09e74 100644 --- a/src/macro/Directives.cc +++ b/src/macro/Directives.cc @@ -18,6 +18,9 @@ */ #include "Directives.hh" +#include "Driver.hh" + +#include <fstream> using namespace macro; @@ -39,15 +42,45 @@ Eval::interpret(ostream &output, bool no_line_macro) } } -string -Include::interpretAndGetName() const +void +Include::interpret(ostream &output, bool no_line_macro) { +#ifdef _WIN32 + string FILESEP = "\\"; +#else + string FILESEP = "/"; +#endif try { StringPtr msp = dynamic_pointer_cast<String>(expr->eval()); if (!msp) throw StackTrace("File name does not evaluate to a string"); - return msp->to_string(); + string filename = msp->to_string(); + ifstream incfile(filename, ios::binary); + if (incfile.fail()) + { + ostringstream dirs; + dirs << "." << FILESEP << endl; + for (const auto & path : paths) + { + string testfile = path + FILESEP + filename; + incfile = ifstream(testfile, 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)); + } + + 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); } catch (StackTrace &ex) { @@ -58,7 +91,6 @@ Include::interpretAndGetName() const { error(StackTrace("@#include", e.what(), location)); } - return ""; } void diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh index a0bc92e5..045caa6a 100644 --- a/src/macro/Directives.hh +++ b/src/macro/Directives.hh @@ -66,17 +66,11 @@ namespace macro { private: const ExpressionPtr expr; + vector<string> &paths; public: - Include(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : - Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } - // Not interpretable because we want the class to be immutable (for use with shared_ptr) - // If it were interpretable, the name would need to be stored in a non-const variable - // rendering the class mutable - inline void interpret(ostream &output, bool no_line_macro) override - { - error(StackTrace("@#include", "should never be interpreted", location)); - } - string interpretAndGetName() const; + 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; }; diff --git a/src/macro/Driver.cc b/src/macro/Driver.cc index cccdeece..49553d1a 100644 --- a/src/macro/Driver.cc +++ b/src/macro/Driver.cc @@ -19,8 +19,6 @@ #include "Driver.hh" -#include <fstream> - using namespace macro; void @@ -28,12 +26,6 @@ Driver::parse(const string &file_arg, const string &basename_arg, istream &modfi ostream &output, bool debug, const vector<pair<string, string>> &defines, vector<string> paths_arg) { -#ifdef _WIN32 - string FILESEP = "\\"; -#else - string FILESEP = "/"; -#endif - file = file_arg; basename = basename_arg; paths = move(paths_arg); @@ -80,39 +72,7 @@ Driver::parse(const string &file_arg, const string &basename_arg, istream &modfi statement->printLineInfo(output, no_line_macro); printLine = false; } - - auto ip = dynamic_pointer_cast<Include>(statement); - if (ip) - { - string filename = ip->interpretAndGetName(); - ifstream incfile(filename, ios::binary); - if (incfile.fail()) - { - ostringstream dirs; - dirs << "." << FILESEP << endl; - for (const auto & path : paths) - { - string testfile = path + FILESEP + filename; - incfile = ifstream(testfile, ios::binary); - if (incfile.good()) - break; - dirs << path << endl; - } - if (incfile.fail()) - error(statement->getLocation(), "Could not open " + filename + - ". The following directories were searched:\n" + dirs.str()); - } - - 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, debug, vector<pair<string, string>>{}, paths); - } - else - statement->interpret(output, no_line_macro); + statement->interpret(output, no_line_macro); } } diff --git a/src/macro/ForwardDeclarationsAndEnums.hh b/src/macro/ForwardDeclarationsAndEnums.hh index 71802223..484ea77e 100644 --- a/src/macro/ForwardDeclarationsAndEnums.hh +++ b/src/macro/ForwardDeclarationsAndEnums.hh @@ -56,6 +56,9 @@ namespace macro class Eval; using EvalPtr = shared_ptr<Eval>; + // For Directives.cc + class Driver; + namespace codes { enum class BaseType diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index cbd1dd19..51b25245 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -126,7 +126,7 @@ directive : directive_one_line EOL ; directive_one_line : INCLUDE expr - { $$ = make_shared<Include>($2, driver.env, @$); } + { $$ = make_shared<Include>($2, driver.env, driver.paths, @$); } | INCLUDEPATH expr { $$ = make_shared<IncludePath>($2, driver.env, driver.paths, @$); } | DEFINE symbol EQUAL expr -- GitLab