ifeqEntryTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2018-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "ifEntry.H"
27 #include "elifEntry.H"
28 #include "elseEntry.H"
29 #include "endifEntry.H"
30 #include "Switch.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class Context>
35 bool Foam::functionEntries::ifeqEntry::evaluate
36 (
37  const bool doIf,
38  DynamicList<filePos>& stack,
39  const dictionary& contextDict,
40  Context& context,
41  Istream& is
42 ) const
43 {
44  while (!is.eof())
45  {
46  token t;
47  readToken(t, is);
48 
49  if (t.isFunctionName() && t.functionNameToken() == ifeqEntry::typeName)
50  {
51  // Recurse to evaluate
52  execute(stack, contextDict, context, is);
53  }
54  else if
55  (
56  t.isFunctionName()
57  && t.functionNameToken() == ifEntry::typeName
58  )
59  {
60  // Recurse to evaluate
61  const ifEntry ife(is.lineNumber(), contextDict, is);
62  ife.execute(stack, contextDict, context, is);
63  }
64  else if
65  (
66  doIf
67  && t.isFunctionName()
68  && (
69  t.functionNameToken() == elseEntry::typeName
70  || t.functionNameToken() == elifEntry::typeName
71  )
72  )
73  {
74  // Now skip until #endif
75  skipUntil(stack, contextDict, endifEntry::typeName, is);
76  stack.remove();
77  break;
78  }
79  else if
80  (
81  t.isFunctionName()
82  && t.functionNameToken() == endifEntry::typeName
83  )
84  {
85  stack.remove();
86  break;
87  }
88  else
89  {
90  const bool ok = insert(contextDict, context, t, is);
91  if (!ok)
92  {
93  return false;
94  }
95  }
96  }
97 
98  return true;
99 }
100 
101 
102 template<class Context>
103 bool Foam::functionEntries::ifeqEntry::execute
104 (
105  const bool doIf,
106  DynamicList<filePos>& stack,
107  const dictionary& contextDict,
108  Context& context,
109  Istream& is
110 ) const
111 {
112  if (doIf)
113  {
114  evaluate(true, stack, contextDict, context, is);
115  }
116  else
117  {
118  // Fast-forward to #else
119  token t;
120  while (!is.eof())
121  {
122  readToken(t, is);
123 
124  if (t.isFunctionName())
125  {
126  if
127  (
130  )
131  {
132  stack.append(filePos(is.name(), is.lineNumber()));
133  skipUntil(stack, contextDict, endifEntry::typeName, is);
134  stack.remove();
135  }
136  else if (t.functionNameToken() == elseEntry::typeName)
137  {
138  break;
139  }
140  else if (t.functionNameToken() == elifEntry::typeName)
141  {
142  // Read elif argument by constructing an ifEntry
143  const ifEntry ife(is.lineNumber(), contextDict, is);
144  const string arg
145  (
146  ife[1].stringToken() + char(token::END_STATEMENT)
147  );
148  IStringStream argStream(arg);
149  argStream.lineNumber() = ife[1].lineNumber();
150  const primitiveEntry e("elifEntry", contextDict, argStream);
151  const Switch doIf(e.stream());
152 
153  if (doIf)
154  {
155  break;
156  }
157  }
158  else if (t.functionNameToken() == endifEntry::typeName)
159  {
160  stack.remove();
161  break;
162  }
163  }
164  }
165 
167  {
168  // Evaluate until we hit #endif
169  evaluate(false, stack, contextDict, context, is);
170  }
171  else if (t.functionNameToken() == elifEntry::typeName)
172  {
173  // Evaluate until we hit #else or #endif
174  evaluate(true, stack, contextDict, context, is);
175  }
176  }
177  return true;
178 }
179 
180 
181 template<class Context>
182 bool Foam::functionEntries::ifeqEntry::execute
183 (
184  DynamicList<filePos>& stack,
185  const dictionary& contextDict,
186  Context& context,
187  Istream& is
188 ) const
189 {
190  const label nNested = stack.size();
191 
192  stack.append(filePos(is.name(), is.lineNumber()));
193 
194  // Read first token and expand if a variable
195  token cond1(operator[](1));
196  cond1 = expand(contextDict, cond1);
197 
198  // Read second token and expand if a variable
199  token cond2(operator[](2));
200  cond2 = expand(contextDict, cond2);
201 
202  const bool equal = equalToken(cond1, cond2);
203 
204  // Info<< "Using #" << typeName << " " << cond1
205  // << " == " << cond2
206  // << " at line " << stack.last().second()
207  // << " in file " << stack.last().first() << endl;
208 
209  bool ok = ifeqEntry::execute(equal, stack, contextDict, context, is);
210 
211  if (stack.size() != nNested)
212  {
213  FatalIOErrorInFunction(contextDict)
214  << "Did not find matching #endif for "
215  << typeName << " condition starting"
216  << " at line " << stack.last().second()
217  << " in file " << stack.last().first() << exit(FatalIOError);
218  }
219 
220  return ok;
221 }
222 
223 
224 // ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
T remove()
Remove and return the top element.
Definition: DynamicListI.H:351
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
label lineNumber() const
Return current stream line number.
Definition: IOstream.H:450
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
Input from memory buffer stream.
Definition: IStringStream.H:52
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
bool eof() const
Return true if end of input seen.
Definition: Istream.H:107
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
T & last()
Return the last element of the list.
Definition: UListI.H:128
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Conditional parsing of and within dictionary entries.
Definition: ifEntry.H:83
static bool insert(const dictionary &parentDict, dictionary &contextDict, const token &t, Istream &is)
Read entry starting from token t and insert into contextDict.
A keyword and a list of tokens is a 'primitiveEntry'. An primitiveEntry can be read,...
A token holds items read from Istream.
Definition: token.H:74
const functionName & functionNameToken() const
Definition: tokenI.H:365
@ END_STATEMENT
Definition: token.H:109
bool isFunctionName() const
Definition: tokenI.H:360
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
bool equal(const T &s1, const T &s2)
Definition: doubleFloat.H:62
const doubleScalar e
Definition: doubleScalar.H:106
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
void evaluate(GeometricField< Type, GeoMesh > &result, const Function1< Type > &func, const GeometricField< Type, GeoMesh > &x)
IOerror FatalIOError
string expand(const string &s, string::size_type &index, const dictionary &dict, const bool allowEnvVars, const bool allowEmpty)
Definition: stringOps.C:146