Verified Commit 031bc62f authored by Houtan Bastani's avatar Houtan Bastani
Browse files

macro processor: use filesystem after move to C++17, closes #31

ancillary to this change is the move of `paths` out of the Driver class into an argument to parsing/evaluation #32
parent d7e70a40
......@@ -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 &macro_output);
bool no_line_macro, bool no_empty_line_macro, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, stringstream &macro_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;
......
......@@ -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 &macro_output)
bool no_line_macro_arg, bool no_empty_line_macro, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, stringstream &macro_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())
......
......@@ -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;
}
}
......
......@@ -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
......@@ -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);
}
}
......
......@@ -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;
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment