diff --git a/opm/parser/eclipse/IntegrationTests/CMakeLists.txt b/opm/parser/eclipse/IntegrationTests/CMakeLists.txt index df18451f4..33176dea2 100644 --- a/opm/parser/eclipse/IntegrationTests/CMakeLists.txt +++ b/opm/parser/eclipse/IntegrationTests/CMakeLists.txt @@ -52,7 +52,6 @@ add_test(NAME runIncludeTest WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} COMMAND - add_executable(runParseEQUIL ParseEQUIL.cpp) target_link_libraries(runParseEQUIL Parser ${Boost_LIBRARIES}) add_test(NAME runParseEQUIL diff --git a/opm/parser/eclipse/IntegrationTests/IncludeTest.cpp b/opm/parser/eclipse/IntegrationTests/IncludeTest.cpp index 61364ab4f..0fa331f16 100644 --- a/opm/parser/eclipse/IntegrationTests/IncludeTest.cpp +++ b/opm/parser/eclipse/IntegrationTests/IncludeTest.cpp @@ -40,10 +40,13 @@ createDeckWithInclude(path& datafile, std::string addEndKeyword) { path root = unique_path("/tmp/%%%%-%%%%"); path absoluteInclude = root / "absolute.include"; - path includePath = root / "include"; + path includePath1 = root / "include"; + path includePath2 = root / "include2"; + path pathIncludeFile = "path.file"; create_directories(root); - create_directories(includePath); + create_directories(includePath1); + create_directories(includePath2); { datafile = root / "TEST.DATA"; @@ -63,6 +66,23 @@ createDeckWithInclude(path& datafile, std::string addEndKeyword) of << "INCLUDE" << std::endl; of << " \'include/nested.include\' /" << std::endl; + of << std::endl; + + of << "PATHS" << std::endl; + of << "PATH1 '" << includePath1.string() << "' /" << std::endl; + of << "PATH2 '" << includePath2.string() << "' /" << std::endl; + of << "/" << std::endl; + + of << std::endl; + + of << "INCLUDE" << std::endl; + of << " \'$PATH1/" << pathIncludeFile.string() << "\' /" << std::endl; + + of << std::endl; + + of << "INCLUDE" << std::endl; + of << " \'$PATH2/" << pathIncludeFile.string() << "\' /" << std::endl; + of.close(); } @@ -87,8 +107,8 @@ createDeckWithInclude(path& datafile, std::string addEndKeyword) } { - path nestedInclude = includePath / "nested.include"; - path gridInclude = includePath / "grid.include"; + path nestedInclude = includePath1 / "nested.include"; + path gridInclude = includePath1 / "grid.include"; std::ofstream of(nestedInclude.string().c_str()); of << "INCLUDE" << std::endl; @@ -100,6 +120,21 @@ createDeckWithInclude(path& datafile, std::string addEndKeyword) of2 << "/" << std::endl; of2.close(); } + + { + path fullPathToPathIncludeFile1 = includePath1 / pathIncludeFile; + std::ofstream of1(fullPathToPathIncludeFile1.string().c_str()); + of1 << "TITLE" << std::endl; + of1 << "This is the title /" << std::endl; + of1.close(); + + path fullPathToPathIncludeFile2 = includePath2 / pathIncludeFile; + std::ofstream of2(fullPathToPathIncludeFile2.string().c_str()); + of2 << "BOX" << std::endl; + of2 << " 1 2 3 4 5 6 /" << std::endl; + of2.close(); + } + std::cout << datafile << std::endl; @@ -140,3 +175,14 @@ BOOST_AUTO_TEST_CASE(parse_fileWithENDKeyword_deckReturned) { BOOST_CHECK( !deck->hasKeyword("DIMENS")); BOOST_CHECK( !deck->hasKeyword("GRIDUNIT")); } + +BOOST_AUTO_TEST_CASE(parse_fileWithPathsKeyword_IncludeExtendsPath) { + path datafile; + ParserPtr parser(new Parser()); + createDeckWithInclude (datafile, ""); + DeckConstPtr deck = parser->parseFile(datafile.string()); + + BOOST_CHECK( deck->hasKeyword("TITLE")); + BOOST_CHECK( deck->hasKeyword("BOX")); +} + diff --git a/opm/parser/eclipse/Parser/Parser.cpp b/opm/parser/eclipse/Parser/Parser.cpp index d87bf76dd..cf40c10a9 100644 --- a/opm/parser/eclipse/Parser/Parser.cpp +++ b/opm/parser/eclipse/Parser/Parser.cpp @@ -32,6 +32,7 @@ namespace Opm { DeckPtr deck; boost::filesystem::path dataFile; boost::filesystem::path rootPath; + std::map pathMap; size_t lineNR; std::shared_ptr inputstream; RawKeywordPtr rawKeyword; @@ -179,6 +180,29 @@ namespace Opm { } + boost::filesystem::path Parser::getIncludeFilePath(std::shared_ptr parserState, std::string path) const + { + const std::string pathKeywordPrefix("$"); + const std::string validPathNameCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"); + + size_t positionOfPathName = path.find(pathKeywordPrefix); + + if ( positionOfPathName != std::string::npos) { + std::string stringStartingAtPathName = path.substr(positionOfPathName+1); + size_t cutOffPosition = stringStartingAtPathName.find_first_not_of(validPathNameCharacters); + std::string stringToFind = stringStartingAtPathName.substr(0, cutOffPosition); + std::string stringToReplace = parserState->pathMap[stringToFind]; + boost::replace_all(path, pathKeywordPrefix + stringToFind, stringToReplace); + } + + boost::filesystem::path includeFilePath(path); + + if (includeFilePath.is_relative()) + includeFilePath = parserState->rootPath / includeFilePath; + + return includeFilePath; + } + bool Parser::parseStream(std::shared_ptr parserState) const { bool verbose = false; bool stopParsing = false; @@ -194,17 +218,22 @@ namespace Opm { else if (parserState->rawKeyword->getKeywordName() == Opm::RawConsts::endinclude) { break; } + else if (parserState->rawKeyword->getKeywordName() == Opm::RawConsts::paths) { + for (size_t i = 0; i < parserState->rawKeyword->size(); i++) { + RawRecordConstPtr record = parserState->rawKeyword->getRecord(i); + std::string pathName = record->getItem(0); + std::string pathValue = record->getItem(1); + parserState->pathMap.insert(std::pair(pathName, pathValue)); + } + } else if (parserState->rawKeyword->getKeywordName() == Opm::RawConsts::include) { RawRecordConstPtr firstRecord = parserState->rawKeyword->getRecord(0); - std::string includeFileString = firstRecord->getItem(0); - boost::filesystem::path includeFile(includeFileString); - - if (includeFile.is_relative()) - includeFile = parserState->rootPath / includeFile; - + std::string includeFileAsString = firstRecord->getItem(0); + boost::filesystem::path includeFile = getIncludeFilePath(parserState, includeFileAsString); + if (verbose) std::cout << parserState->rawKeyword->getKeywordName() << " " << includeFile << std::endl; - + std::shared_ptr newParserState (new ParserState(includeFile.string(), parserState->deck, parserState->rootPath, parserState->strictParsing)); stopParsing = parseStream(newParserState); if (stopParsing) break; diff --git a/opm/parser/eclipse/Parser/Parser.hpp b/opm/parser/eclipse/Parser/Parser.hpp index b1ea42ad0..d2f41eeae 100644 --- a/opm/parser/eclipse/Parser/Parser.hpp +++ b/opm/parser/eclipse/Parser/Parser.hpp @@ -75,6 +75,7 @@ namespace Opm { RawKeywordPtr createRawKeyword(const std::string& keywordString, std::shared_ptr parserState) const; void addDefaultKeywords(); + boost::filesystem::path getIncludeFilePath(std::shared_ptr parserState, std::string path) const; boost::filesystem::path getRootPathFromFile(const boost::filesystem::path &inputDataFile) const; std::string doSpecialHandlingForTitleKeyword(std::string line, std::shared_ptr parserState) const; }; diff --git a/opm/parser/eclipse/RawDeck/RawConsts.hpp b/opm/parser/eclipse/RawDeck/RawConsts.hpp index 477b40f07..108584333 100644 --- a/opm/parser/eclipse/RawDeck/RawConsts.hpp +++ b/opm/parser/eclipse/RawDeck/RawConsts.hpp @@ -31,6 +31,7 @@ namespace Opm { const std::string include = "INCLUDE"; const std::string end = "END"; const std::string endinclude = "ENDINC"; + const std::string paths = "PATHS"; const unsigned int maxKeywordLength = 8; } } diff --git a/opm/parser/share/keywords/P/PATHS b/opm/parser/share/keywords/P/PATHS new file mode 100644 index 000000000..85f354012 --- /dev/null +++ b/opm/parser/share/keywords/P/PATHS @@ -0,0 +1,5 @@ +{"name" : "PATHS" , "items" : + [ + {"name" : "PathName" , "value_type" : "STRING"}, + {"name" : "PathValue" , "value_type" : "STRING"} + ]}