From 1804d3fed55a4310c98326e947a6c44f7daabd2b Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 23 Nov 2021 21:03:21 +0100 Subject: [PATCH] ENH: additional #word and #message dictionary directives (#2276) - use `#word` to concatenate, expand content with the resulting string being treated as a word token. Can be used in dictionary or primitive context. In dictionary context, it fills the gap for constructing dictionary names on-the-fly. For example, ``` #word "some_prefix_solverInfo_${application}" { type solverInfo; libs (utilityFunctionObjects); ... } ``` The '#word' directive will automatically squeeze out non-word characters. In the block content form, it will also strip out comments. This means that this type of content should also work: ``` #word { some_prefix_solverInfo /* Appended with application name (if defined) */ ${application:+_} // Use '_' separator ${application} // The application } { type solverInfo; libs (utilityFunctionObjects); ... } ``` This is admittedly quite ugly, but illustrates its capabilities. - use `#message` to report expanded string content to stderr. For example, ``` T { solver PBiCG; preconditioner DILU; tolerance 1e-10; relTol 0; #message "using solver: $solver" } ``` Only reports on the master node. --- applications/test/dictionary/testDict | 57 ++++++- src/OpenFOAM/Make/files | 6 +- src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C | 136 ++++++++++++++- src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H | 15 +- .../db/dictionary/functionEntries/README | 17 +- .../functionEntries/calcEntry/calcEntry.H | 4 +- .../functionEntries/codeStream/codeStream.H | 4 +- .../functionEntries/evalEntry/evalEntry.C | 102 +----------- .../functionEntries/evalEntry/evalEntry.H | 5 +- .../functionEntry/functionEntry.C | 14 ++ .../functionEntry/functionEntry.H | 9 + .../functionEntries/ifEntry/ifEntry.C | 6 +- .../functionEntries/ifEntry/ifEntry.H | 4 +- .../functionEntries/ifeqEntry/ifeqEntry.H | 4 +- .../includeEntry/includeEntry.H | 4 +- .../includeEtcEntry/includeEtcEntry.H | 4 +- .../includeFuncEntry/includeFuncEntry.H | 4 +- .../functionEntries/inputMode/inputMode.H | 4 +- .../message/messageDirective.C | 145 ++++++++++++++++ .../message/messageDirective.H | 101 +++++++++++ .../functionEntries/removeEntry/removeEntry.H | 4 +- .../functionEntries/word/wordDirective.C | 157 ++++++++++++++++++ .../functionEntries/word/wordDirective.H | 100 +++++++++++ tutorials/IO/dictionary/good-word-expand.dict | 61 +++++++ .../laminar/movingCone/system/blockMeshDict | 4 +- 25 files changed, 837 insertions(+), 134 deletions(-) create mode 100644 src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.C create mode 100644 src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.H create mode 100644 src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C create mode 100644 src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H create mode 100644 tutorials/IO/dictionary/good-word-expand.dict diff --git a/applications/test/dictionary/testDict b/applications/test/dictionary/testDict index ab8b85d3f2b..eee439527fd 100644 --- a/applications/test/dictionary/testDict +++ b/applications/test/dictionary/testDict @@ -18,6 +18,8 @@ FoamFile #sinclude "$FOAM_CASE/someUnknownFile" #includeIfPresent "$FOAM_CASE/someUnknownFile-$FOAM_CASENAME" +zeroVelocity uniform (0 0 0); + internalField uniform 1; // supply defaults @@ -48,7 +50,7 @@ x 5; varName x; -//Indirection for keys +// Indirection for keys key inlet_9; @@ -67,13 +69,17 @@ boundaryField inlet_5 { $inactive } inlet_6a { $...inactive } // Relative scoping - fairly horrible to use inlet_6b { $^inactive } // Absolute scoping + inlet_6c { key ${/key}; } // Absolute scoping + inlet_7 { ${inactive}} // Test variable expansion inlet_8 { $inactive } + + // Variable expansion for a keyword ${key} { $inactive } #include "testDictInc" - outlet + outletBase { type inletOutlet; inletValue $internalField; @@ -83,16 +89,36 @@ boundaryField y 6; } - // this should have no effect + outlet + { + $outletBase + } + + Default_Boundary_Region + { + valueOut $zeroVelocity; + } + + // this should have no effect (not in scope) #remove inactive - inlet_7 { ${${varType}}} // Test indirection/recursive expansion - inlet_8 { $active } + // But this should work to remove things in different scopes + #remove "/zeroVelocity" + + inlet_7 { ${inactive} } // Test variable expansion + inlet_8 { $inactive } + + inlet_7a { ${${varType}} } // Test indirection/recursive expansion + inlet_7b { ${${varType}} } // Test indirection/recursive expansion #overwrite inlet_8 { type none; } } +// No patterns with scoped removal +// #remove "/boundaryField/outletB.*" +#remove "/boundaryField/outletBase" + #include "testDict2" verbatim #{ @@ -123,10 +149,25 @@ baz $active } -// this should work -#remove active +// This should work +#remove x -// this should work too +// This should work too #remove ( bar baz ) +// Remove a sub-dictionary entry +#remove "/anynumber.*/value" + +// Removal does not auto-vivify +#remove "/nonExistentDict/value" + +// Add into existing dictionary +"/anynumber.*/someValue" 100; + +// Auto-vivify +// - but currently cannot auto-vivify entries with dictionary patterns +"/abd/someValue" 100; +"/def/'someValue.*" 100; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 7e4850fc44c..79cd748121b 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -303,13 +303,15 @@ $(functionEntries)/calcEntry/calcEntry.C $(functionEntries)/codeStream/codeStream.C $(functionEntries)/evalEntry/evalEntry.C $(functionEntries)/functionEntry/functionEntry.C +$(functionEntries)/ifEntry/ifEntry.C +$(functionEntries)/ifeqEntry/ifeqEntry.C $(functionEntries)/includeEntry/includeEntry.C $(functionEntries)/includeEtcEntry/includeEtcEntry.C $(functionEntries)/includeFuncEntry/includeFuncEntry.C $(functionEntries)/inputMode/inputMode.C +$(functionEntries)/message/messageDirective.C $(functionEntries)/removeEntry/removeEntry.C -$(functionEntries)/ifeqEntry/ifeqEntry.C -$(functionEntries)/ifEntry/ifEntry.C +$(functionEntries)/word/wordDirective.C IOdictionary = db/IOobjects/IOdictionary $(IOdictionary)/baseIOdictionary.C diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C index bdb22307ae1..ad422dc7c8a 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C @@ -37,6 +37,7 @@ License // Truncate error message for readability static constexpr const unsigned errLen = 80; + // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // namespace @@ -55,6 +56,21 @@ inline bool validVariableChar(char c) return (Foam::word::valid(c) || c == '/'); } + +inline void inplaceTrimRight(std::string& s) +{ + auto end = s.length(); + if (end) + { + while (end && Foam::isspace(s[end-1])) + { + --end; + } + + s.erase(end); + } +} + } // End anonymous namespace @@ -123,7 +139,7 @@ char Foam::ISstream::nextValid() // C-style comment: discard through to "*/" ending if (!seekCommentEnd_Cstyle()) { - return 0; + return 0; // Premature end of stream } } else @@ -390,17 +406,133 @@ static token::tokenType readVariable return token::tokenType::ERROR; } + +// Raw, low-level get into a string. +// Continues reading after an initial opening delimiter (eg, '{') +// until it finds the matching closing delimiter (eg, '}') +static bool readUntilBalancedDelimiter +( + ISstream& is, + std::string& str, + const bool stripComments, + const char delimOpen, + const char delimClose +) +{ + constexpr const unsigned bufLen = 1024; + static char buf[bufLen]; + + unsigned nChar = 0; + unsigned depth = 1; // Initial '{' already seen by caller + char c = 0; + + str.clear(); + while (is.get(c)) + { + if ((str.empty() && !nChar) && isspace(c)) + { + continue; // Ignore leading whitespace + } + + buf[nChar++] = c; + + // Note: no '\' escape handling needed at the moment + + if (c == delimOpen) + { + ++depth; + } + else if (c == delimClose) + { + --depth; + if (!depth) + { + // Closing character - do not include in output + --nChar; + str.append(buf, nChar); + inplaceTrimRight(str); // Remove trailing whitespace + return true; + } + } + else if (stripComments && c == '/') + { + // Strip C/C++ comments from expressions + // Note: could also peek instead of get/putback + + if (!is.get(c)) + { + break; // Premature end of stream + } + else if (c == '/') + { + --nChar; // Remove initial '/' from buffer + + // C++ comment: discard through newline + (void) is.getLine(nullptr, '\n'); + } + else if (c == '*') + { + --nChar; // Remove initial '/' from buffer + + // C-style comment: discard through to "*/" ending + if (!is.seekCommentEnd_Cstyle()) + { + break; // Premature end of stream + } + } + else + { + // Reanalyze the char + is.putback(c); + } + } + + if (nChar == bufLen) + { + str.append(buf, nChar); // Flush full buffer + nChar = 0; + } + } + + + // Abnormal exit of the loop + + str.append(buf, nChar); // Finalize pending content + inplaceTrimRight(str); // Remove trailing whitespace + + // Exhausted stream without finding closing sequence + return false; +} + } // End namespace Foam // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +bool Foam::ISstream::continueReadUntilRightBrace +( + std::string& str, + const bool stripComments +) +{ + return + readUntilBalancedDelimiter + ( + *this, + str, + stripComments, + token::BEGIN_BLOCK, + token::END_BLOCK + ); +} + + Foam::Istream& Foam::ISstream::read(token& t) { constexpr const unsigned bufLen = 128; // Max length for labels/scalars static char buf[bufLen]; - // Return the put back token if it exists + // Return the putback token if it exists if (Istream::getBack(t)) { return *this; diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H index db8bba40fa4..67894c86454 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H @@ -66,7 +66,8 @@ class ISstream // Private Member Functions - //- Get the next valid character + //- Get the next valid (non-whitespace) character, + //- after skipping any C/C++ comments. char nextValid(); //- No copy assignment @@ -131,6 +132,18 @@ public: // \return False if stream exhausted before finding the comment end bool seekCommentEnd_Cstyle(); + //- Raw, low-level get into a string. + //- Continues reading \b after an initial left-brace until it finds + //- the matching closing right-brace. + // Tracks balanced pairs, trims out leading/trailing whitespace. + // + // \return False if stream exhausted before finding closing brace + bool continueReadUntilRightBrace + ( + std::string& str, + const bool stripComments = true + ); + // Read Functions diff --git a/src/OpenFOAM/db/dictionary/functionEntries/README b/src/OpenFOAM/db/dictionary/functionEntries/README index b114ac121d0..98969e2dec0 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/README +++ b/src/OpenFOAM/db/dictionary/functionEntries/README @@ -6,23 +6,32 @@ #overwrite | dict | entry introducer #warn | dict | entry introducer #error | dict | entry introducer - | | #remove | dict | keyType or List<keyType> | | #include | dict/primitive | string #sinclude | dict/primitive | string - #includeIfPresent | dict/primitive | string #includeEtc | dict/primitive | string #sincludeEtc | dict/primitive | string #includeFunc | dict | word | | + #message | dict/primitive | string or braced content + #word | dict/primitive | string or braced content + #eval | primitive | string or braced content + | | #calc | dict/primitive | string #codeStream | dict/primitive | dictionary #if | dict | string #ifeq | dict | entry entry -Pending future extensions +Deprecated + +| directive | comments | +|-------------------|---------------------------------------| + #includeIfPresent | same as #sinclude | + + +Pending future extensions (considered reserved) | directive | context | content | line oriented? |-------------------|-------------------|-------------------|----------------- @@ -31,4 +40,4 @@ Pending future extensions #undef | dict | keyType or List<keyType> -2019-08-21 +2021-11-24 diff --git a/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H index 34d0ab4c6c5..0f2792855b7 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H @@ -51,8 +51,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef calcEntry_H -#define calcEntry_H +#ifndef functionEntries_calcEntry_H +#define functionEntries_calcEntry_H #include "codeStream.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H index 691be4ceecb..036c260faf6 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H @@ -92,8 +92,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef codeStream_H -#define codeStream_H +#ifndef functionEntries_codeStream_H +#define functionEntries_codeStream_H #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C index 89d153a31ae..1efaa7790c0 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C @@ -56,96 +56,6 @@ namespace functionEntries } // End namespace Foam -// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Slurp a string until a closing '}' is found. -// Track balanced bracket/brace pairs, with max stack depth of 60. -static bool slurpUntilBalancedBrace(ISstream& is, std::string& str) -{ - constexpr const unsigned bufLen = 1024; - static char buf[bufLen]; - - is.fatalCheck(FUNCTION_NAME); - - unsigned nChar = 0; - unsigned depth = 1; // Initial '{' already seen by caller - char c; - - str.clear(); - while (is.get(c)) - { - buf[nChar++] = c; - - if (c == token::BEGIN_BLOCK) - { - ++depth; - } - else if (c == token::END_BLOCK) - { - --depth; - if (!depth) - { - // Closing '}' character - do not include in output - --nChar; - str.append(buf, nChar); - return true; - } - } - else if (c == '/') - { - // Strip C/C++ comments from expressions - // Note: could also peek instead of get/putback - - if (!is.get(c)) - { - break; // Premature end of stream - } - else if (c == '/') - { - --nChar; // Remove initial '/' from buffer - - // C++ comment: discard through newline - (void) is.getLine(nullptr, '\n'); - } - else if (c == '*') - { - --nChar; // Remove initial '/' from buffer - - // C-style comment: discard through to "*/" ending - if (!is.seekCommentEnd_Cstyle()) - { - break; // Premature end of stream - } - } - else - { - // Reanalyze the char - is.putback(c); - } - } - - if (nChar == bufLen) - { - str.append(buf, nChar); // Flush full buffer - nChar = 0; - } - } - - - // Abnormal exit of the loop - - str.append(buf, nChar); // Finalize pending content - - is.fatalCheck(FUNCTION_NAME); - return false; -} - -} // End namespace Foam - - // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // Foam::tokenList Foam::functionEntries::evalEntry::evaluate @@ -292,8 +202,11 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate is >> tok; } - string str; // The string to evaluate - if (tok.isString()) + + // The string to evaluate + string str; + + if (tok.isStringType()) // Also accepts a single bare word { // - #eval "expr" // - #eval #{ expr #} @@ -303,12 +216,13 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate else if (tok.isPunctuation(token::BEGIN_BLOCK)) { // - #eval { expr } - if (!slurpUntilBalancedBrace(dynamic_cast<ISstream&>(is), str)) + // strip comments + if (!continueReadUntilRightBrace(is, str, true)) { reportReadWarning ( is, - "Premature end while reading expression - missing '}'?" + "Premature end while reading #eval - missing '}'?" ); } } diff --git a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.H index 58d450dd9f5..858696a5584 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.H @@ -65,8 +65,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef evalEntry_H -#define evalEntry_H +#ifndef functionEntries_evalEntry_H +#define functionEntries_evalEntry_H #include "functionEntry.H" @@ -98,6 +98,7 @@ class evalEntry //- Evaluate and return a token list static tokenList evaluate(const dictionary& parentDict, Istream& is); + public: //- Execute in a primitiveEntry context, extracts token or line diff --git a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C index c363b63f875..d23aaeb1392 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C @@ -47,6 +47,7 @@ namespace Foam execute, primitiveEntryIstream ); + } // End namespace Foam @@ -61,6 +62,19 @@ Foam::token Foam::functionEntry::readLine(const word& key, Istream& is) } +bool Foam::functionEntry::continueReadUntilRightBrace +( + Istream& is, + std::string& str, + const bool stripComments +) +{ + return + dynamic_cast<ISstream&>(is) + .continueReadUntilRightBrace(str, stripComments); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::functionEntry::functionEntry diff --git a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.H index 9b796f3f60c..99c3efbf762 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.H @@ -80,6 +80,15 @@ protected: template<class StringType> static List<StringType> readStringList(Istream& is); + //- Slurp a string until a closing '}' is found. + // Track balanced bracket/brace pairs, with max stack depth of 60. + static bool continueReadUntilRightBrace + ( + Istream& is, + std::string& str, + const bool stripComments = true + ); + //- No copy construct functionEntry(const functionEntry&) = delete; diff --git a/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.C index ca6ca8f8c2c..f33e531dcd5 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.C @@ -50,13 +50,13 @@ namespace functionEntries } // End namespace Foam -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // bool Foam::functionEntries::ifEntry::isTrue(ITstream& its) { Switch logic; - if (its.size() && its.first().isScalar()) + if (its.peekFirst().isScalar()) { // Use default rounding tolerance logic = Switch(its.first().scalarToken()); @@ -70,6 +70,8 @@ bool Foam::functionEntries::ifEntry::isTrue(ITstream& its) } +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + bool Foam::functionEntries::ifEntry::execute ( DynamicList<filePos>& stack, diff --git a/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.H index 364247dad9b..6f1679751cd 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/ifEntry/ifEntry.H @@ -54,8 +54,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef ifEntry_H -#define ifEntry_H +#ifndef functionEntries_ifEntry_H +#define functionEntries_ifEntry_H #include "ifeqEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H index a925964fcda..0cf864fa5db 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H @@ -69,8 +69,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef ifeqEntry_H -#define ifeqEntry_H +#ifndef functionEntries_ifeqEntry_H +#define functionEntries_ifeqEntry_H #include "functionEntry.H" #include "DynamicList.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.H index d6747fe5d1c..00d28c6bb25 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.H @@ -53,8 +53,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef includeEntry_H -#define includeEntry_H +#ifndef functionEntries_includeEntry_H +#define functionEntries_includeEntry_H #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.H index 4b7507a3c73..8c545643695 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.H @@ -50,8 +50,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef includeEtcEntry_H -#define includeEtcEntry_H +#ifndef functionEntries_includeEtcEntry_H +#define functionEntries_includeEtcEntry_H #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H index ddb205839f0..7a430ee7f3f 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H @@ -64,8 +64,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef includeFuncEntry_H -#define includeFuncEntry_H +#ifndef functionEntries_includeFuncEntry_H +#define functionEntries_includeFuncEntry_H #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H index 3c6ad960407..9259c63db3a 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H @@ -55,8 +55,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef inputMode_H -#define inputMode_H +#ifndef functionEntries_inputMode_H +#define functionEntries_inputMode_H #include "entry.H" #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.C b/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.C new file mode 100644 index 00000000000..a150da5ee3f --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.C @@ -0,0 +1,145 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "messageDirective.H" +#include "dictionary.H" +#include "stringOps.H" +#include "addToMemberFunctionSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + messageDirective, + execute, + dictionaryIstream, + message + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + messageDirective, + execute, + primitiveEntryIstream, + message + ); + +} // End namespace functionEntry +} // End namespace Foam + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +bool Foam::functionEntries::messageDirective::evaluate +( + const dictionary& parentDict, + Istream& is +) +{ + token tok(is); + + // The string to evaluate + string str; + + if (tok.isStringType()) // Also accepts a single bare word + { + // - #message expr + // - #message "expr" + // - #message #{ expr #} + str = tok.stringToken(); + } + else if (tok.isPunctuation(token::BEGIN_BLOCK)) + { + // - #message { expr } + // strip comments + if (!continueReadUntilRightBrace(is, str, true)) + { + reportReadWarning + ( + is, + "Premature end while reading #message - missing '}'?" + ); + } + } + else + { + FatalIOErrorInFunction(is) + << "Invalid input for #message." + " Expecting a string or block to expand, but found" << nl + << tok.info() << endl + << exit(FatalIOError); + } + + stringOps::inplaceExpand(str, parentDict); + stringOps::inplaceTrim(str); + + if (!str.empty() && error::master()) + { + // Use stderr directly, in case message should be part of startup + std::cerr + << str << " (file: \"" + << parentDict.relativeName() << "\" line: " + << tok.lineNumber() << ")\n" << std::flush; + } + + return true; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionEntries::messageDirective::execute +( + dictionary& parentDict, + Istream& is +) +{ + evaluate(parentDict, is); + + return true; +} + + +bool Foam::functionEntries::messageDirective::execute +( + const dictionary& parentDict, + primitiveEntry& entry, + Istream& is +) +{ + evaluate(parentDict, is); + + return true; +} + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.H b/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.H new file mode 100644 index 00000000000..d396957d6fd --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/message/messageDirective.H @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::functionEntries::messageDirective + +Description + Expands string content and reports as a message on stderr. + + For example, + \verbatim + T + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-10; + relTol 0; + #message "using solver: $solver" + } + \endverbatim + +SourceFiles + messageDirective.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionEntries_messageDirective_H +#define functionEntries_messageDirective_H + +#include "functionEntry.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ + +/*---------------------------------------------------------------------------*\ + Class messageDirective Declaration +\*---------------------------------------------------------------------------*/ + +class messageDirective +: + public functionEntry +{ + // Private Member Functions + + //- Evaluate + static bool evaluate(const dictionary& parentDict, Istream& is); + + +public: + + //- Execute in a primitiveEntry context. + // Reports message string (after expansion) - does not alter entry. + static bool execute + ( + const dictionary& parentDict, + primitiveEntry& entry, + Istream& is + ); + + //- Execute in a sub-dict context. + // Reports message string (after expansion) - does not alter dictionary. + static bool execute(dictionary& parentDict, Istream& is); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionEntries +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H index 918084313d8..1db53b72eba 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H @@ -52,8 +52,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef removeEntry_H -#define removeEntry_H +#ifndef functionEntries_removeEntry_H +#define functionEntries_removeEntry_H #include "functionEntry.H" diff --git a/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C b/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C new file mode 100644 index 00000000000..7342250e626 --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "wordDirective.H" +#include "dictionary.H" +#include "stringOps.H" +#include "addToMemberFunctionSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + wordDirective, + execute, + dictionaryIstream, + word + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + wordDirective, + execute, + primitiveEntryIstream, + word + ); + +} // End namespace functionEntries +} // End namespace Foam + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::token Foam::functionEntries::wordDirective::evaluate +( + const dictionary& parentDict, + Istream& is +) +{ + token tok(is); + + // The string to evaluate + string str; + + if (tok.isStringType()) // Also accepts a single bare word + { + // - #word expr + // - #word "expr" + // - #word #{ expr #} + str = tok.stringToken(); + } + else if (tok.isPunctuation(token::BEGIN_BLOCK)) + { + // - #word { expr } + // strip comments + if (!continueReadUntilRightBrace(is, str, true)) + { + reportReadWarning + ( + is, + "Premature end while reading #word - missing '}'?" + ); + } + } + else + { + FatalIOErrorInFunction(is) + << "Invalid input for #word." + " Expecting a string or block to expand, but found" << nl + << tok.info() << endl + << exit(FatalIOError); + } + + stringOps::inplaceExpand(str, parentDict); + + word result(word::validate(str)); // Includes trimming etc. + + if (!result.empty()) + { + tok = std::move(result); + return tok; + } + + // Expanded to nothing - treat as a no-op + return token::undefinedToken; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionEntries::wordDirective::execute +( + const dictionary& parentDict, + primitiveEntry& entry, + Istream& is +) +{ + token tok(evaluate(parentDict, is)); + + if (tok.good()) + { + // Can add evaluated value directly into primitiveEntry + entry.append(std::move(tok), true); // Lazy resizing + } + + return true; +} + + +bool Foam::functionEntries::wordDirective::execute +( + dictionary& parentDict, + Istream& is +) +{ + token tok(evaluate(parentDict, is)); + + if (tok.good()) + { + // Using putBack to insert evaluated value into stream + is.putBack(tok); + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H b/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H new file mode 100644 index 00000000000..69e81ac8497 --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::functionEntries::wordDirective + +Description + Converts/expands string content to a word. + This can be useful for composition of names. + + For example, + \verbatim + #word "some_prefix_solverInfo_${application}_${{10 * 5}}" + { + type solverInfo; + libs (utilityFunctionObjects); + fields (".*"); + + returnName #word solver$type; + } + \endverbatim + +SourceFiles + wordDirective.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionEntries_wordDirective_H +#define functionEntries_wordDirective_H + +#include "functionEntry.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ + +/*---------------------------------------------------------------------------*\ + Class wordDirective Declaration +\*---------------------------------------------------------------------------*/ + +class wordDirective +: + public functionEntry +{ + // Private Member Functions + + //- Evaluate + static token evaluate(const dictionary& parentDict, Istream& is); + + +public: + + //- Execute in a primitiveEntry context + static bool execute + ( + const dictionary& parentDict, + primitiveEntry& entry, + Istream& is + ); + + //- Execute in a sub-dict context. + static bool execute(dictionary& parentDict, Istream& is); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionEntries +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/tutorials/IO/dictionary/good-word-expand.dict b/tutorials/IO/dictionary/good-word-expand.dict new file mode 100644 index 00000000000..4c398afe5d1 --- /dev/null +++ b/tutorials/IO/dictionary/good-word-expand.dict @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2112 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object dictionary; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// message from a word +#message message-word + +// message from a string +#message "message string [] from ${FOAM_API:-unset}" + +// message from a braced-block string +#message { message block string from ${FOAM_API:-unset} } + + +// word in primitive entry + +foamApi using #word "_ ${FOAM_API:-unset}" version; + + +// word as dictionary entry (string syntax) + +#word "dict1entry_ ${FOAM_API:-unset}" +{ + value1 10; +} + + +// word as dictionary entry (braced-block string) + +#word { dict2entry_ ${FOAM_API:-unset} } +{ + value1 20; +} + +#word +{ + dict3entry + ${FOAM_API:+_} // Use '_' separator + ${FOAM_API} // The value (if any) +} +{ + // This is a funny corner-case for #eval. + // It also accepts a single word ... not that many make sense though + + value1 #eval pi(); +} + + +// ************************************************************************* // diff --git a/tutorials/incompressible/pimpleFoam/laminar/movingCone/system/blockMeshDict b/tutorials/incompressible/pimpleFoam/laminar/movingCone/system/blockMeshDict index a467b741933..433dac2dce0 100644 --- a/tutorials/incompressible/pimpleFoam/laminar/movingCone/system/blockMeshDict +++ b/tutorials/incompressible/pimpleFoam/laminar/movingCone/system/blockMeshDict @@ -1,7 +1,7 @@ /*--------------------------------*- C++ -*----------------------------------*\ | ========= | | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: v2106 | +| \\ / O peration | Version: v2112 | | \\ / A nd | Website: www.openfoam.com | | \\/ M anipulation | | \*---------------------------------------------------------------------------*/ @@ -16,6 +16,8 @@ FoamFile mergeType points; // Wedge geometry - Merge points instead of topology +#message "Using mergeType: ${mergeType:-default}" + scale 0.001; vertices -- GitLab