preprocessor: macroprocessor: add -I switch. closes #1039

time-shift
Houtan Bastani 2015-08-27 16:49:00 +02:00
parent 9179d331e0
commit 1ba04976aa
4 changed files with 45 additions and 12 deletions

View File

@ -49,7 +49,7 @@ usage()
{ {
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [nolog] [warn_uninit]" 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]" << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
<< " [-D<variable>[=<value>]] [nostrict] [fast] [minimal_workspace] [output=dynamic|first|second|third] [language=C|C++]" << " [-D<variable>[=<value>]] [-I/path] [nostrict] [fast] [minimal_workspace] [output=dynamic|first|second|third] [language=C|C++]"
#if defined(_WIN32) || defined(__CYGWIN32__) #if defined(_WIN32) || defined(__CYGWIN32__)
<< " [cygwin] [msvc]" << " [cygwin] [msvc]"
#endif #endif
@ -100,6 +100,7 @@ main(int argc, char **argv)
bool check_model_changes = false; bool check_model_changes = false;
bool minimal_workspace = false; bool minimal_workspace = false;
map<string, string> defines; map<string, string> defines;
vector<string> path;
FileOutputType output_mode = none; FileOutputType output_mode = none;
LanguageOutputType language = matlab; LanguageOutputType language = matlab;
@ -205,6 +206,16 @@ main(int argc, char **argv)
defines[key] = "1"; 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)) else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "output", 6))
{ {
if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=') if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=')
@ -271,7 +282,7 @@ main(int argc, char **argv)
MacroDriver m; MacroDriver m;
stringstream macro_output; 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)
{ {
if (save_macro_file.empty()) if (save_macro_file.empty())

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2008-2012 Dynare Team * Copyright (C) 2008-2015 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -37,7 +37,8 @@ MacroDriver::~MacroDriver()
} }
void void
MacroDriver::parse(const string &f, ostream &out, bool debug, bool no_line_macro, map<string, string> defines) MacroDriver::parse(const string &f, ostream &out, bool debug, bool no_line_macro,
map<string, string> defines, vector<string> path)
{ {
file = f; 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; 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); lexer->set_debug(debug);
Macro::parser parser(*this, out); Macro::parser parser(*this, out);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2008-2012 Dynare Team * Copyright (C) 2008-2015 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -78,7 +78,8 @@ private:
//! Should we omit the @#line statements ? //! Should we omit the @#line statements ?
const bool no_line_macro; const bool no_line_macro;
//! The paths to search when looking for .mod files
const vector<string> path;
//! True iff current context is the body of a loop //! True iff current context is the body of a loop
bool is_for_context; bool is_for_context;
//! If current context is the body of a loop, contains the string of the loop body //! 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); void new_loop_body_buffer(Macro::parser::location_type *yylloc);
public: public:
MacroFlex(istream *in, ostream *out, bool no_line_macro_arg); MacroFlex(istream *in, ostream *out, bool no_line_macro_arg, vector<string> path_arg);
//! The main lexing function //! The main lexing function
Macro::parser::token_type lex(Macro::parser::semantic_type *yylval, Macro::parser::token_type lex(Macro::parser::semantic_type *yylval,
@ -176,7 +177,8 @@ public:
//! Starts parsing a file, returns output in out //! Starts parsing a file, returns output in out
/*! \param no_line_macro should we omit the @#line statements ? */ /*! \param no_line_macro should we omit the @#line statements ? */
void parse(const string &f, ostream &out, bool debug, bool no_line_macro, map<string,string> defines); void parse(const string &f, ostream &out, bool debug, bool no_line_macro,
map<string,string> defines, const vector<string> path);
//! Name of main file being parsed //! Name of main file being parsed
string file; string file;

View File

@ -347,8 +347,8 @@ CONT \\\\
<*>. { driver.error(*yylloc, "Macro lexer error: '" + string(yytext) + "'"); } <*>. { driver.error(*yylloc, "Macro lexer error: '" + string(yytext) + "'"); }
%% %%
MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg) MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg, vector<string> path_arg)
: MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), : MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), path(path_arg),
reading_for_statement(false), reading_if_statement(false) reading_for_statement(false), reading_if_statement(false)
{ {
} }
@ -387,11 +387,30 @@ void
MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc, MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc,
MacroDriver &driver) MacroDriver &driver)
{ {
#ifdef _WIN32
string FILESEP = "\\";
#else
string FILESEP = "/";
#endif
save_context(yylloc); save_context(yylloc);
// Open new file // Open new file
input = new ifstream(filename->c_str(), ios::binary); input = new ifstream(filename->c_str(), ios::binary);
if (input->fail()) if (input->fail())
driver.error(*yylloc, "Could not open " + *filename); {
ostringstream dirs;
dirs << "." << FILESEP << endl;
for (vector<string>::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 // Reset location
yylloc->begin.filename = yylloc->end.filename = filename; yylloc->begin.filename = yylloc->end.filename = filename;
yylloc->begin.line = yylloc->end.line = 1; yylloc->begin.line = yylloc->end.line = 1;