diff --git a/macro/MacroDriver.hh b/macro/MacroDriver.hh index 92d90ee4..83828b2e 100644 --- a/macro/MacroDriver.hh +++ b/macro/MacroDriver.hh @@ -79,7 +79,7 @@ private: //! Should we omit the @#line statements ? const bool no_line_macro; //! The paths to search when looking for .mod files - const vector path; + 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 @@ -122,6 +122,10 @@ private: //! Restore last scanning context void restore_context(Macro::parser::location_type *yylloc); + //! pushes the colon-separated paths passed to @#includepath onto the path vector + void push_path(string *includepath, Macro::parser::location_type *yylloc, + MacroDriver &driver); + //! Saves current scanning context and create a new context with content of filename /*! Filename must be a newly allocated string which will be deleted by the lexer */ void create_include_context(string *filename, Macro::parser::location_type *yylloc, @@ -178,7 +182,7 @@ 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, const vector path); + map defines, vector path); //! Name of main file being parsed string file; diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll index 994d2420..9e694eb4 100644 --- a/macro/MacroFlex.ll +++ b/macro/MacroFlex.ll @@ -21,6 +21,9 @@ using namespace std; #include +#include +#include +#include #include "MacroDriver.hh" @@ -68,6 +71,47 @@ CONT \\\\ yylloc->step(); %} +^{SPC}*@#{SPC}*includepath{SPC}+\"([^\"\r\n:;|<>]*){1}(:[^\"\r\n:;|<>]*)*\"{SPC}*{EOL} { + yylloc->lines(1); + yylloc->step(); + + // Get path + string *includepath = new string(yytext); + int dblq_idx1 = includepath->find('"'); + int dblq_idx2 = includepath->find('"', dblq_idx1 + 1); + includepath->erase(dblq_idx2); + includepath->erase(0, dblq_idx1 + 1); + + push_path(includepath, yylloc, driver); + BEGIN(INITIAL); + } + +^{SPC}*@#{SPC}*includepath{SPC}+[^\"\r\n]*{SPC}*{EOL} { + yylloc->lines(1); + yylloc->step(); + + // Get variable name + string pathvar = string(yytext); + int dblq_idx1 = pathvar.find("includepath"); + pathvar.erase(0, dblq_idx1 + 11); + pathvar.erase(0, pathvar.find_first_not_of(" \t")); + size_t p = pathvar.find_last_not_of(" \t\n\r"); + if (string::npos != p) + pathvar.erase(p+1); + + string *includepath = NULL; + try + { + includepath = new string(driver.get_variable(pathvar)->toString()); + } + catch(MacroDriver::UnknownVariable(&e)) + { + driver.error(*yylloc, "Unknown variable: " + pathvar); + } + push_path(includepath, yylloc, driver); + BEGIN(INITIAL); + } + ^{SPC}*@#{SPC}*include{SPC}+\"[^\"\r\n]*\"{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); @@ -383,6 +427,22 @@ MacroFlex::restore_context(Macro::parser::location_type *yylloc) output_line(yylloc); } +void +MacroFlex::push_path(string *includepath, Macro::parser::location_type *yylloc, + MacroDriver &driver) +{ + using namespace boost; + vector tokenizedPath; + split(tokenizedPath, *includepath, is_any_of(":"), token_compress_on); + for (vector::iterator it = tokenizedPath.begin(); + it != tokenizedPath.end(); it++ ) + if (!it->empty()) + { + trim(*it); + path.push_back(*it); + } +} + void MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc, MacroDriver &driver)