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.
This commit is contained in:
parent
55af2fc2c6
commit
1804d3fed5
@ -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;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -51,8 +51,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef calcEntry_H
|
||||
#define calcEntry_H
|
||||
#ifndef functionEntries_calcEntry_H
|
||||
#define functionEntries_calcEntry_H
|
||||
|
||||
#include "codeStream.H"
|
||||
|
||||
|
@ -92,8 +92,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef codeStream_H
|
||||
#define codeStream_H
|
||||
#ifndef functionEntries_codeStream_H
|
||||
#define functionEntries_codeStream_H
|
||||
|
||||
#include "functionEntry.H"
|
||||
|
||||
|
@ -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 '}'?"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -54,8 +54,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ifEntry_H
|
||||
#define ifEntry_H
|
||||
#ifndef functionEntries_ifEntry_H
|
||||
#define functionEntries_ifEntry_H
|
||||
|
||||
#include "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"
|
||||
|
@ -53,8 +53,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef includeEntry_H
|
||||
#define includeEntry_H
|
||||
#ifndef functionEntries_includeEntry_H
|
||||
#define functionEntries_includeEntry_H
|
||||
|
||||
#include "functionEntry.H"
|
||||
|
||||
|
@ -50,8 +50,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef includeEtcEntry_H
|
||||
#define includeEtcEntry_H
|
||||
#ifndef functionEntries_includeEtcEntry_H
|
||||
#define functionEntries_includeEtcEntry_H
|
||||
|
||||
#include "functionEntry.H"
|
||||
|
||||
|
@ -64,8 +64,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef includeFuncEntry_H
|
||||
#define includeFuncEntry_H
|
||||
#ifndef functionEntries_includeFuncEntry_H
|
||||
#define functionEntries_includeFuncEntry_H
|
||||
|
||||
#include "functionEntry.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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
@ -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
|
||||
|
||||
// ************************************************************************* //
|
@ -52,8 +52,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef removeEntry_H
|
||||
#define removeEntry_H
|
||||
#ifndef functionEntries_removeEntry_H
|
||||
#define functionEntries_removeEntry_H
|
||||
|
||||
#include "functionEntry.H"
|
||||
|
||||
|
157
src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C
Normal file
157
src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.C
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
100
src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H
Normal file
100
src/OpenFOAM/db/dictionary/functionEntries/word/wordDirective.H
Normal file
@ -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
|
||||
|
||||
// ************************************************************************* //
|
61
tutorials/IO/dictionary/good-word-expand.dict
Normal file
61
tutorials/IO/dictionary/good-word-expand.dict
Normal file
@ -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();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user