From 00616b72fff2952f69495d385d62af183f1c04a4 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Sun, 7 Feb 2010 13:58:10 +0100
Subject: [PATCH] ENH: Add functionEntry '#calc' to dictionary

- handles basic operations, references to other dictionary entries
  (with '$name' syntax) and assorted mathematical functions:

      pi(), degToRad, radToDeg, asin, acos, atan, sin, cos, tan, log,
      log10, mag, atan2, pow

The basic syntax: #calc{ ... };

NOTE the trailing ';' is required for the primitiveEntry to be
properly defined.
---
 applications/test/dictionary/Make/files       |   4 -
 applications/test/dictionary/Make/options     |   2 +-
 applications/test/dictionary/testDictCalc     |  27 +---
 .../test/dictionary/testDictCalcError         |  46 +++++++
 src/OpenFOAM/Make/files                       |   6 +
 src/OpenFOAM/Make/options                     |   2 +-
 .../functionEntries}/calcEntry/calcEntry.C    |   0
 .../functionEntries}/calcEntry/calcEntry.H    |   0
 .../calcEntry/calcEntryInternal.C             |   0
 .../calcEntry/calcEntryInternal.H             |   0
 .../calcEntry/calcEntryParser.atg             | 124 +++++++++---------
 src/OpenFOAM/db/error/CocoParserErrors.H      |  14 +-
 src/OpenFOAM/primitives/chars/wchar/wchar.H   |   4 +
 src/OpenFOAM/primitives/chars/wchar/wcharIO.C |  24 +++-
 wmake/rules/General/coco                      |   2 +-
 15 files changed, 153 insertions(+), 102 deletions(-)
 create mode 100644 applications/test/dictionary/testDictCalcError
 rename {applications/test/dictionary => src/OpenFOAM/db/dictionary/functionEntries}/calcEntry/calcEntry.C (100%)
 rename {applications/test/dictionary => src/OpenFOAM/db/dictionary/functionEntries}/calcEntry/calcEntry.H (100%)
 rename {applications/test/dictionary => src/OpenFOAM/db/dictionary/functionEntries}/calcEntry/calcEntryInternal.C (100%)
 rename {applications/test/dictionary => src/OpenFOAM/db/dictionary/functionEntries}/calcEntry/calcEntryInternal.H (100%)
 rename {applications/test/dictionary => src/OpenFOAM/db/dictionary/functionEntries}/calcEntry/calcEntryParser.atg (76%)

diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files
index 6f1da0059a6..b9363efb23b 100644
--- a/applications/test/dictionary/Make/files
+++ b/applications/test/dictionary/Make/files
@@ -1,7 +1,3 @@
 dictionaryTest.C
 
-calcEntry/calcEntryParser.atg
-calcEntry/calcEntryInternal.C
-calcEntry/calcEntry.C
-
 EXE = $(FOAM_USER_APPBIN)/dictionaryTest
diff --git a/applications/test/dictionary/Make/options b/applications/test/dictionary/Make/options
index 22051a7c056..41306609f20 100644
--- a/applications/test/dictionary/Make/options
+++ b/applications/test/dictionary/Make/options
@@ -1 +1 @@
-EXE_INC = -IcalcEntry -I$(OBJECTS_DIR)
+EXE_INC =
diff --git a/applications/test/dictionary/testDictCalc b/applications/test/dictionary/testDictCalc
index f1d67650e85..577cbf112d9 100644
--- a/applications/test/dictionary/testDictCalc
+++ b/applications/test/dictionary/testDictCalc
@@ -10,7 +10,7 @@ FoamFile
     version     2.0;
     format      ascii;
     class       dictionary;
-    object      testDictTest;
+    object      testDictCalc;
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -19,28 +19,13 @@ flowRatePerHour 720;
 x       10;
 y       20;
 z       t s v;
-// z       #test{ // this
-//     123 - 456
-//         // comments // are
-//         /* stripped
-//         * 10
-//          * {}
-//          */
-//         + 1 /*100 */  10
-// };
-
-p     this calculation #calc{
-          1 + 2 + 10 * 15 +
-          $x - $y
-        // $x + $y
-}
-is done inplace;
+p       #calc{ 1 + 2 + 10 * 15 + $x - $y };
 
+// this calculation is in-place, but does not work inside a string:
+flowRate    "The flow rate " #calc{ $flowRatePerHour / 3600 } "kg/s";
 
-flowRate    #calc{ $flowRatePerHour / 3600};
+// this is also okay
+x   #calc{ $x * 1E-3 };
 
-xxx         yyy;
-foo         30;
-bar         15;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/applications/test/dictionary/testDictCalcError b/applications/test/dictionary/testDictCalcError
new file mode 100644
index 00000000000..95b90ce8e81
--- /dev/null
+++ b/applications/test/dictionary/testDictCalcError
@@ -0,0 +1,46 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  Any                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      testDictCalcError;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+flowRatePerHour 720;
+
+x       10;
+y       20;
+z       t s v;
+// z       #test{ // this
+//     123 - 456
+//         // comments // are
+//         /* stripped
+//         * 10
+//          * {}
+//          */
+//         + 1 /*100 */  10
+// };
+
+p     this calculation #calc{
+          1xxx1 + 2 + 10 * 15 +
+          $x - $y
+        // $x + $y
+}
+is done inplace;
+
+
+flowRate    #calc{ $flowRatePerHour / 3600};
+
+xxx         yyy;
+foo         30;
+bar         15;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 9c18e725555..d8634de6dfd 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -142,6 +142,12 @@ $(functionEntries)/includeIfPresentEntry/includeIfPresentEntry.C
 $(functionEntries)/inputModeEntry/inputModeEntry.C
 $(functionEntries)/removeEntry/removeEntry.C
 
+calcEntry = $(functionEntries)/calcEntry
+$(calcEntry)/calcEntryParser.atg
+$(calcEntry)/calcEntryInternal.C
+$(calcEntry)/calcEntry.C
+
+
 IOdictionary = db/IOobjects/IOdictionary
 $(IOdictionary)/IOdictionary.C
 $(IOdictionary)/IOdictionaryIO.C
diff --git a/src/OpenFOAM/Make/options b/src/OpenFOAM/Make/options
index 4eba86ae56d..b1cc1a2d10a 100644
--- a/src/OpenFOAM/Make/options
+++ b/src/OpenFOAM/Make/options
@@ -1,4 +1,4 @@
-EXE_INC =
+EXE_INC = -I$(OBJECTS_DIR)
 
 LIB_LIBS = \
     $(FOAM_LIBBIN)/libOSspecific.o \
diff --git a/applications/test/dictionary/calcEntry/calcEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.C
similarity index 100%
rename from applications/test/dictionary/calcEntry/calcEntry.C
rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.C
diff --git a/applications/test/dictionary/calcEntry/calcEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H
similarity index 100%
rename from applications/test/dictionary/calcEntry/calcEntry.H
rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H
diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.C b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.C
similarity index 100%
rename from applications/test/dictionary/calcEntry/calcEntryInternal.C
rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.C
diff --git a/applications/test/dictionary/calcEntry/calcEntryInternal.H b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.H
similarity index 100%
rename from applications/test/dictionary/calcEntry/calcEntryInternal.H
rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.H
diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.atg b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg
similarity index 76%
rename from applications/test/dictionary/calcEntry/calcEntryParser.atg
rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg
index f3751f77d4d..755f539d983 100644
--- a/applications/test/dictionary/calcEntry/calcEntryParser.atg
+++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg
@@ -1,3 +1,8 @@
+/*---------------------------------------------------------------------------*\
+    Attributed Grammar for Coco/R  (-*- C++ -*- version)
+    compile with:
+    coco-cpp  calcEntryParser.atg
+\*---------------------------------------------------------------------------*/
 [copy]
 /*---------------------------------*- C++ -*---------------------------------*\
   =========                 |
@@ -36,13 +41,6 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 [/copy]
-/*---------------------------------------------------------------------------*\
- compile with:
- Coco \
-    [-single] -frames $WM_THIRD_PARTY_DIR/coco-r \
-    calcEntryParser.atg
-\*---------------------------------------------------------------------------*/
-
 #include "dictionary.H"
 #include "wchar.H"
 #include "calcEntryInternal.H"
@@ -52,7 +50,9 @@ COMPILER calcEntry
     // grammar pragmas:
     $prefix=calcEntry
     $namespace=Foam::functionEntries::calcEntryInternal
-    $explicitEOF=true     // grammar handles eof itself
+    $define=EXPLICIT_EOF     // grammar handles eof itself
+    $define=STREAMS_ONLY     // only use STL streams
+    $define=NO_UTF8          // disable UTF8 on input
 
 private:
     //- The parent dictionary
@@ -62,56 +62,7 @@ private:
     scalar val;
 
     //- lookup dictionary entry
-    scalar getDictLookup() const
-    {
-        if (!dict_)
-        {
-            FatalErrorIn
-            (
-                "calcEntry::getDictEntry() const"
-            )   << "No dictionary attached!"
-                << exit(FatalError);
-
-            return 0;
-        }
-
-        char* str = coco_string_create_char
-        (
-            t->val,
-            1,
-            (coco_string_length(t->val) - 1)
-        );
-        word keyword(str);
-        coco_string_delete(str);
-
-        scalar dictValue = 0;
-
-        entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
-        if (entryPtr && !entryPtr->isDict())
-        {
-            if (entryPtr->stream().size() != 1)
-            {
-                FatalErrorIn
-                (
-                    "calcEntry::getDictEntry() const"
-                )   << "keyword " << keyword << " has "
-                    << entryPtr->stream().size() << " values in dictionary "
-                    << exit(FatalError);
-            }
-            entryPtr->stream() >> dictValue;
-        }
-        else
-        {
-            FatalErrorIn
-            (
-                "calcEntry::getDictEntry() const"
-            )   << "keyword " << keyword << " is undefined in dictionary "
-                << exit(FatalError);
-        }
-
-        return dictValue;
-    }
-
+    scalar getDictLookup(const word&) const;
 
 public:
 
@@ -128,11 +79,57 @@ public:
     }
 
 
-[initialize]
+/*---------------------------------------------------------------------------*/
+
+[initialize]        // add to Parser constructor
     dict_ = 0;
     val = 0;
 [/initialize]
 
+/*---------------------------------------------------------------------------*/
+[code]
+Foam::scalar Parser::getDictLookup(const word& keyword) const
+{
+    if (!dict_)
+    {
+        FatalErrorIn
+        (
+            "calcEntry::getDictEntry(const word&) const"
+        )   << "No dictionary attached!"
+            << exit(FatalError);
+
+        return 0;
+    }
+
+    scalar dictValue = 0;
+
+    entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
+    if (entryPtr && !entryPtr->isDict())
+    {
+        if (entryPtr->stream().size() != 1)
+        {
+            FatalErrorIn
+            (
+                "calcEntry::getDictEntry(const word&) const"
+            )   << "keyword " << keyword << " has "
+                << entryPtr->stream().size() << " values in dictionary "
+                << exit(FatalError);
+        }
+        entryPtr->stream() >> dictValue;
+    }
+    else
+    {
+        FatalErrorIn
+        (
+            "calcEntry::getDictEntry(const word&) const"
+        )   << "keyword " << keyword << " is undefined in dictionary "
+            << exit(FatalError);
+    }
+
+    return dictValue;
+}
+[/code]
+
 /*---------------------------------------------------------------------------*/
 
 CHARACTERS
@@ -226,7 +223,10 @@ Factor<scalar& val>             (. bool negative = false; .)
   ]
   (
       Func<val> | '(' Expr<val> ')'
-    | variable                  (. val = getDictLookup(); .)
+    | variable                  (.
+                                   // skip leading '$' for the keyword
+                                   val = getDictLookup(t->toString(1, t->length()-1));
+                                 .)
     | number                    (. val = coco_string_toDouble(t->val); .)
   )                             (. if (negative) { val = -val; } .)
 .
@@ -238,9 +238,7 @@ Factor<scalar& val>             (. bool negative = false; .)
 Func<scalar& val>
 =
   ident                         (.
-                                  char* str = coco_string_create_char(t->val);
-                                  word funcName(str);
-                                  coco_string_delete(str);
+                                  word funcName(t->toString());
                                   DynamicList<scalar> stack(4);
                                  .)
   '('
diff --git a/src/OpenFOAM/db/error/CocoParserErrors.H b/src/OpenFOAM/db/error/CocoParserErrors.H
index d9d2155db26..97d503204f1 100644
--- a/src/OpenFOAM/db/error/CocoParserErrors.H
+++ b/src/OpenFOAM/db/error/CocoParserErrors.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2009-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2010-2010 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -45,7 +45,7 @@ namespace Foam
                       Class CocoParserErrors Declaration
 \*---------------------------------------------------------------------------*/
 
-template<class BaseClass, class CharClass=wchar_t>
+template<class BaseClass, class StringClass=std::wstring>
 class CocoParserErrors
 :
     public BaseClass
@@ -90,14 +90,14 @@ public:
     // Error Handling
 
         //- Handle a general warning 'msg'
-        virtual void Warning(const CharClass* msg)
+        virtual void Warning(const StringClass& msg)
         {
             WarningIn(name_)
                 << msg << endl;
         }
 
         //- Handle a general warning 'msg'
-        virtual void Warning(int line, int col, const CharClass* msg)
+        virtual void Warning(int line, int col, const StringClass& msg)
         {
             WarningIn(name_)
                 <<"line " << line << " col " << col << ": "
@@ -105,7 +105,7 @@ public:
         }
 
         //- Handle general error 'msg' (eg, a semantic error)
-        virtual void Error(int line, int col, const CharClass* msg)
+        virtual void Error(int line, int col, const StringClass& msg)
         {
             FatalErrorIn(name_)
                 << "line " << line << " col " << col <<": " << msg << endl
@@ -113,7 +113,7 @@ public:
         }
 
         //- Handle general error 'msg' (eg, a semantic error)
-        virtual void Error(const CharClass* msg)
+        virtual void Error(const StringClass& msg)
         {
             FatalErrorIn(name_)
                 << msg << endl
@@ -121,7 +121,7 @@ public:
         }
 
         //- Handle a general exception 'msg'
-        virtual void Exception(const CharClass* msg)
+        virtual void Exception(const StringClass& msg)
         {
             this->Error(msg);
         }
diff --git a/src/OpenFOAM/primitives/chars/wchar/wchar.H b/src/OpenFOAM/primitives/chars/wchar/wchar.H
index 61519a51d34..d4df7a61eaa 100644
--- a/src/OpenFOAM/primitives/chars/wchar/wchar.H
+++ b/src/OpenFOAM/primitives/chars/wchar/wchar.H
@@ -41,6 +41,7 @@ SeeAlso
 #define wchar_H
 
 #include <cwchar>
+#include <string>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -58,6 +59,9 @@ Ostream& operator<<(Ostream&, const wchar_t);
 //- Output wide character (Unicode) string as UTF-8
 Ostream& operator<<(Ostream&, const wchar_t*);
 
+//- Output wide character (Unicode) string as UTF-8
+Ostream& operator<<(Ostream&, const std::wstring&);
+
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C
index 9796d4b6eb9..37f81321efd 100644
--- a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C
+++ b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C
@@ -101,13 +101,13 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t wc)
 }
 
 
-Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws)
+Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* wstr)
 {
-    if (ws)
+    if (wstr)
     {
-        for (const wchar_t* p = ws; *p; ++p)
+        for (const wchar_t* iter = wstr; *iter; ++iter)
         {
-            os  << *p;
+            os  << *iter;
         }
     }
 
@@ -115,4 +115,20 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws)
 }
 
 
+Foam::Ostream& Foam::operator<<(Ostream& os, const std::wstring& wstr)
+{
+    for
+    (
+        std::wstring::const_iterator iter = wstr.begin();
+        iter != wstr.end();
+        ++iter
+    )
+    {
+        os  << *iter;
+    }
+
+    return os;
+}
+
+
 // ************************************************************************* //
diff --git a/wmake/rules/General/coco b/wmake/rules/General/coco
index ca07810bdb1..7f7bd2ff29b 100644
--- a/wmake/rules/General/coco
+++ b/wmake/rules/General/coco
@@ -3,7 +3,7 @@
 .SUFFIXES: .atg
 
 atgtoo =  \
-    $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/$(WM_ARCH)/bin/coco-cpp \
+    $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/$(WM_ARCH)$(WM_COMPILER)/bin/coco-cpp \
     -single \
     -frames $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/share/coco-cpp \
     $$SOURCE -o $(OBJECTS_DIR) && \
-- 
GitLab