diff --git a/preprocessor/DynareMain.cc b/preprocessor/DynareMain.cc index 0535663c3..de52a1084 100644 --- a/preprocessor/DynareMain.cc +++ b/preprocessor/DynareMain.cc @@ -49,7 +49,7 @@ usage() { cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [nolog] [warn_uninit]" << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]" - << " [-D[=]] [nostrict] [fast] [minimal_workspace] [output=dynamic|first|second|third] [language=C|C++]" + << " [-D[=]] [-I/path] [nostrict] [fast] [minimal_workspace] [output=dynamic|first|second|third] [language=C|C++]" #if defined(_WIN32) || defined(__CYGWIN32__) << " [cygwin] [msvc]" #endif @@ -100,6 +100,7 @@ main(int argc, char **argv) bool check_model_changes = false; bool minimal_workspace = false; map defines; + vector path; FileOutputType output_mode = none; LanguageOutputType language = matlab; @@ -205,6 +206,16 @@ main(int argc, char **argv) defines[key] = "1"; } } + else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-I", 2)) + { + if (strlen(argv[arg]) == 2) + { + cerr << "Incorrect syntax for command line define: the defined variable " + << "must not be separated from -I by whitespace." << endl; + usage(); + } + path.push_back(string(argv[arg]).erase(0,2)); + } else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "output", 6)) { if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=') @@ -271,7 +282,7 @@ main(int argc, char **argv) MacroDriver m; stringstream macro_output; - m.parse(argv[1], macro_output, debug, no_line_macro, defines); + m.parse(argv[1], macro_output, debug, no_line_macro, defines, path); if (save_macro) { if (save_macro_file.empty()) diff --git a/preprocessor/macro/MacroDriver.cc b/preprocessor/macro/MacroDriver.cc index 746fd12e3..1d13c5cee 100644 --- a/preprocessor/macro/MacroDriver.cc +++ b/preprocessor/macro/MacroDriver.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 Dynare Team + * Copyright (C) 2008-2015 Dynare Team * * This file is part of Dynare. * @@ -37,7 +37,8 @@ MacroDriver::~MacroDriver() } void -MacroDriver::parse(const string &f, ostream &out, bool debug, bool no_line_macro, map defines) +MacroDriver::parse(const string &f, ostream &out, bool debug, bool no_line_macro, + map defines, vector path) { file = f; @@ -67,7 +68,7 @@ MacroDriver::parse(const string &f, ostream &out, bool debug, bool no_line_macro } file_with_endl << in.rdbuf() << endl; - lexer = new MacroFlex(&file_with_endl, &out, no_line_macro); + lexer = new MacroFlex(&file_with_endl, &out, no_line_macro, path); lexer->set_debug(debug); Macro::parser parser(*this, out); diff --git a/preprocessor/macro/MacroDriver.hh b/preprocessor/macro/MacroDriver.hh index 0945a3296..92d90ee40 100644 --- a/preprocessor/macro/MacroDriver.hh +++ b/preprocessor/macro/MacroDriver.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 Dynare Team + * Copyright (C) 2008-2015 Dynare Team * * This file is part of Dynare. * @@ -78,7 +78,8 @@ private: //! Should we omit the @#line statements ? const bool no_line_macro; - + //! The paths to search when looking for .mod files + const vector path; //! True iff current context is the body of a loop bool is_for_context; //! If current context is the body of a loop, contains the string of the loop body @@ -136,7 +137,7 @@ private: void new_loop_body_buffer(Macro::parser::location_type *yylloc); public: - MacroFlex(istream *in, ostream *out, bool no_line_macro_arg); + MacroFlex(istream *in, ostream *out, bool no_line_macro_arg, vector path_arg); //! The main lexing function Macro::parser::token_type lex(Macro::parser::semantic_type *yylval, @@ -176,7 +177,8 @@ public: //! Starts parsing a file, returns output in out /*! \param no_line_macro should we omit the @#line statements ? */ - void parse(const string &f, ostream &out, bool debug, bool no_line_macro, map defines); + void parse(const string &f, ostream &out, bool debug, bool no_line_macro, + map defines, const vector path); //! Name of main file being parsed string file; diff --git a/preprocessor/macro/MacroFlex.ll b/preprocessor/macro/MacroFlex.ll index 0b5ff7a21..72b4a4b51 100644 --- a/preprocessor/macro/MacroFlex.ll +++ b/preprocessor/macro/MacroFlex.ll @@ -347,8 +347,8 @@ CONT \\\\ <*>. { driver.error(*yylloc, "Macro lexer error: '" + string(yytext) + "'"); } %% -MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg) - : MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), +MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg, vector path_arg) + : MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), path(path_arg), reading_for_statement(false), reading_if_statement(false) { } @@ -387,11 +387,30 @@ void MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc, MacroDriver &driver) { +#ifdef _WIN32 + string FILESEP = "\\"; +#else + string FILESEP = "/"; +#endif save_context(yylloc); // Open new file input = new ifstream(filename->c_str(), ios::binary); if (input->fail()) - driver.error(*yylloc, "Could not open " + *filename); + { + ostringstream dirs; + dirs << "." << FILESEP << endl; + for (vector::const_iterator it = path.begin(); it != path.end(); it++) + { + input = new ifstream(it->c_str() + FILESEP + filename->c_str(), ios::binary); + if (input->good()) + break; + dirs << *it << endl; + } + if (input->fail()) + driver.error(*yylloc, "Could not open " + *filename + + ". The following directories were searched:\n" + dirs.str()); + } + // Reset location yylloc->begin.filename = yylloc->end.filename = filename; yylloc->begin.line = yylloc->end.line = 1;