diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index 7b3baa055a..75ef089de2 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -414,7 +414,7 @@ public: //- Construct top-level dictionary from Istream, // reading entries until EOF, optionally keeping the header - dictionary(Istream& is, const bool keepHeader); + dictionary(Istream& is, bool keepHeader); //- Construct as copy given the parent dictionary dictionary(const dictionary& parentDict, const dictionary& dict); @@ -765,7 +765,7 @@ public: bool read(Istream& is); //- Read dictionary from Istream, optionally keeping the header - bool read(Istream& is, const bool keepHeader); + bool read(Istream& is, bool keepHeader); // Write diff --git a/src/OpenFOAM/db/dictionary/dictionaryIO.C b/src/OpenFOAM/db/dictionary/dictionaryIO.C index 9c1e36c1b5..d608b74e68 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryIO.C +++ b/src/OpenFOAM/db/dictionary/dictionaryIO.C @@ -55,7 +55,7 @@ Foam::dictionary::dictionary(Istream& is) } -Foam::dictionary::dictionary(Istream& is, const bool keepHeader) +Foam::dictionary::dictionary(Istream& is, bool keepHeader) : dictionaryName(is.name()), parent_(dictionary::null) @@ -77,8 +77,14 @@ Foam::autoPtr Foam::dictionary::New(Istream& is) // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -bool Foam::dictionary::read(Istream& is, const bool keepHeader) +bool Foam::dictionary::read(Istream& is, bool keepHeader) { + // Normally remove FoamFile header when read, but avoid this if it already + // existed prior to the current read. + // We would otherwise lose it with every top-level '#include ...' + + keepHeader = keepHeader || hashedEntries_.found("FoamFile"); + // Check for empty dictionary if (is.eof()) { @@ -103,7 +109,6 @@ bool Foam::dictionary::read(Istream& is, const bool keepHeader) while (!is.eof() && entry::New(*this, is)) {} - // Normally remove the FoamFile header entry if it exists if (!keepHeader) { remove("FoamFile"); diff --git a/src/OpenFOAM/db/dictionary/entry/entryIO.C b/src/OpenFOAM/db/dictionary/entry/entryIO.C index 3e549c9faf..14bf0beb54 100644 --- a/src/OpenFOAM/db/dictionary/entry/entryIO.C +++ b/src/OpenFOAM/db/dictionary/entry/entryIO.C @@ -62,10 +62,8 @@ bool Foam::entry::getKeyword(keyType& keyword, token& keyToken, Istream& is) keyword = keyToken.stringToken(); return true; } - else - { - return false; - } + + return false; } @@ -84,20 +82,17 @@ bool Foam::entry::getKeyword(keyType& keyword, Istream& is) { return false; } - else - { - // Otherwise the token is invalid - cerr<< "--> FOAM Warning :" << nl - << " From function " - << FUNCTION_NAME << nl - << " in file " << __FILE__ - << " at line " << __LINE__ << nl - << " Reading " << is.name().c_str() << nl - << " found " << keyToken << nl - << " expected either " << token::END_BLOCK << " or EOF" - << std::endl; - return false; - } + + // Otherwise the token is invalid + std::cerr + << "--> FOAM Warning :" << nl + << " From function " << FUNCTION_NAME << nl + << " in file " << __FILE__ << " at line " << __LINE__ << nl + << " Reading " << is.name().c_str() << nl + << " found " << keyToken << nl + << " expected either " << token::END_BLOCK << " or EOF" + << std::endl; + return false; } @@ -154,22 +149,20 @@ bool Foam::entry::New false ); } - else - { - // Otherwise the token is invalid - cerr<< "--> FOAM Warning :" << nl - << " From function " - << FUNCTION_NAME << nl - << " in file " << __FILE__ - << " at line " << __LINE__ << nl - << " Reading " << is.name().c_str() << nl - << " found " << keyToken << nl - << " expected either " << token::END_BLOCK << " or EOF" - << std::endl; - return false; - } + + // Otherwise the token is invalid + std::cerr + << "--> FOAM Warning :" << nl + << " From function " << FUNCTION_NAME << nl + << " in file " << __FILE__ << " at line " << __LINE__ << nl + << " Reading " << is.name().c_str() << nl + << " found " << keyToken << nl + << " expected either " << token::END_BLOCK << " or EOF" + << std::endl; + return false; } - else if (keyword[0] == '#') + + if (keyword[0] == '#') { // Function entry @@ -186,17 +179,11 @@ bool Foam::entry::New false ); } - else - { - const word functionName(keyword.substr(1), false); - return functionEntry::execute(functionName, parentDict, is); - } + + const word functionName(keyword.substr(1), false); + return functionEntry::execute(functionName, parentDict, is); } - else if - ( - !disableFunctionEntries - && keyword[0] == '$' - ) + else if (!disableFunctionEntries && keyword[0] == '$') { // Substitution entry @@ -237,14 +224,12 @@ bool Foam::entry::New false ); } - else - { - FatalIOErrorInFunction(is) - << "Attempt to use undefined variable " << varName - << " as keyword" - << exit(FatalIOError); - return false; - } + + FatalIOErrorInFunction(is) + << "Attempt to use undefined variable " << varName + << " as keyword" + << exit(FatalIOError); + return false; } else { @@ -276,9 +261,6 @@ bool Foam::entry::New return false; } - // How to manage duplicate entries - bool mergeEntry = false; - const bool scoped = ( !disableFunctionEntries @@ -293,27 +275,19 @@ bool Foam::entry::New : parentDict.search(keyword, false, false) ); + // How to manage duplicate entries + bool mergeEntry = false; + if (finder.found()) { // Use keyword from the found entry (ie, eliminate scoping chars) const keyType key = finder.ref().keyword(); - if (mode == inputMode::MERGE) + if (mode == inputMode::PROTECT || keyword == "FoamFile") { - mergeEntry = true; - } - else if (mode == inputMode::OVERWRITE) - { - // Clear existing dictionary so merge acts like overwrite - if (finder.isDict()) - { - finder.dict().clear(); - } - mergeEntry = true; - } - else if (mode == inputMode::PROTECT) - { - // Read and discard the entry. + // Read and discard if existing element should be protected, + // or would potentially alter the "FoamFile" header. + // Disable function/variable expansion to avoid side-effects const int oldFlag = entry::disableFunctionEntries; entry::disableFunctionEntries = 1; @@ -330,7 +304,8 @@ bool Foam::entry::New entry::disableFunctionEntries = oldFlag; return true; } - else if (mode == inputMode::ERROR) + + if (mode == inputMode::ERROR) { FatalIOErrorInFunction(is) << "duplicate entry: " << key @@ -339,6 +314,20 @@ bool Foam::entry::New return false; } + if (mode == inputMode::MERGE) + { + mergeEntry = true; + } + else if (mode == inputMode::OVERWRITE) + { + // Clear existing dictionary so merge acts like overwrite + if (finder.isDict()) + { + finder.dict().clear(); + } + mergeEntry = true; + } + // Merge/overwrite data entry if (nextToken == token::BEGIN_BLOCK) diff --git a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C index 37cc203083..88750273e7 100644 --- a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C +++ b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C @@ -49,7 +49,7 @@ bool Foam::primitiveEntry::expandVariable { // Recursive substitution mode. // Content between {} is replaced with expansion. - string expanded = varName.substr(1, varName.size()-2); + string expanded(varName.substr(1, varName.size()-2)); // Substitute dictionary and environment variables. // Do not allow empty substitutions. @@ -57,46 +57,45 @@ bool Foam::primitiveEntry::expandVariable return expandVariable(expanded, dict); } + + // Lookup variable name in the given dictionary WITHOUT pattern matching. + // Having a pattern match means that in this example: + // { + // internalField XXX; + // boundaryField { ".*" {YYY;} movingWall {value $internalField;} + // } + // The $internalField would be matched by the ".*" !!! + + // Recursive, non-patterns + const entry* eptr = dict.lookupScopedEntryPtr(varName, true, false); + if (!eptr) + { + // Not found - revert to environment variable + const string str(getEnv(varName)); + + if (str.empty()) + { + FatalIOErrorInFunction + ( + dict + ) << "Illegal dictionary entry or environment variable name " + << varName << endl << "Valid dictionary entries are " + << dict.toc() << exit(FatalIOError); + + return false; + } + + append(tokenList(IStringStream('(' + str + ')')())); + } + else if (eptr->isDict()) + { + // Found dictionary entry + append(eptr->dict().tokens()); + } else { - // lookup the variable name in the given dictionary.... - // Note: allow wildcards to match? For now disabled since following - // would expand internalField to wildcard match and not expected - // internalField: - // internalField XXX; - // boundaryField { ".*" {YYY;} movingWall {value $internalField;} - const entry* ePtr = dict.lookupScopedEntryPtr(varName, true, false); - - // ...if defined append its tokens into this - if (ePtr) - { - if (ePtr->isDict()) - { - append(ePtr->dict().tokens()); - } - else - { - append(ePtr->stream()); - } - } - else - { - // Not in the dictionary - try an environment variable - const string envStr = getEnv(varName); - - if (envStr.empty()) - { - FatalIOErrorInFunction - ( - dict - ) << "Illegal dictionary entry or environment variable name " - << varName << endl << "Valid dictionary entries are " - << dict.toc() << exit(FatalIOError); - - return false; - } - append(tokenList(IStringStream('(' + envStr + ')')())); - } + // Found primitive entry + append(eptr->stream()); } return true;