]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Update bundled muParser to 2.3.3
authorDavid Wells <drwells@email.unc.edu>
Mon, 28 Mar 2022 16:46:40 +0000 (12:46 -0400)
committerDavid Wells <drwells@email.unc.edu>
Mon, 28 Mar 2022 17:02:11 +0000 (13:02 -0400)
47 files changed:
bundled/muparser_v2_2_4/License.txt [deleted file]
bundled/muparser_v2_2_4/include/muParser.h [deleted file]
bundled/muparser_v2_2_4/include/muParserBase.h [deleted file]
bundled/muparser_v2_2_4/include/muParserBytecode.h [deleted file]
bundled/muparser_v2_2_4/include/muParserCallback.h [deleted file]
bundled/muparser_v2_2_4/include/muParserDef.h [deleted file]
bundled/muparser_v2_2_4/include/muParserError.h [deleted file]
bundled/muparser_v2_2_4/include/muParserFixes.h [deleted file]
bundled/muparser_v2_2_4/include/muParserInt.h [deleted file]
bundled/muparser_v2_2_4/include/muParserTemplateMagic.h [deleted file]
bundled/muparser_v2_2_4/include/muParserTest.h [deleted file]
bundled/muparser_v2_2_4/include/muParserToken.h [deleted file]
bundled/muparser_v2_2_4/include/muParserTokenReader.h [deleted file]
bundled/muparser_v2_2_4/src/muParser.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserBase.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserBytecode.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserCallback.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserError.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserInt.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserTest.cpp [deleted file]
bundled/muparser_v2_2_4/src/muParserTokenReader.cpp [deleted file]
bundled/muparser_v2_3_3/CHANGELOG [moved from bundled/muparser_v2_2_4/Changes.txt with 82% similarity]
bundled/muparser_v2_3_3/CMakeLists.txt [moved from bundled/muparser_v2_2_4/CMakeLists.txt with 95% similarity]
bundled/muparser_v2_3_3/LICENSE [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParser.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserBase.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserBytecode.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserCallback.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserDef.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserError.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserFixes.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserInt.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserStack.h [moved from bundled/muparser_v2_2_4/include/muParserStack.h with 100% similarity]
bundled/muparser_v2_3_3/include/muParserTemplateMagic.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserTest.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserToken.h [new file with mode: 0644]
bundled/muparser_v2_3_3/include/muParserTokenReader.h [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParser.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserBase.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserBytecode.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserCallback.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserError.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserInt.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserTest.cpp [new file with mode: 0644]
bundled/muparser_v2_3_3/src/muParserTokenReader.cpp [new file with mode: 0644]
bundled/setup_bundled.cmake
doc/news/changes/minor/20220328DavidWells [new file with mode: 0644]

diff --git a/bundled/muparser_v2_2_4/License.txt b/bundled/muparser_v2_2_4/License.txt
deleted file mode 100644 (file)
index c4c0d2b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#######################################################################\r
-#                                                                     #\r
-#                                                                     #\r
-#                 __________                                          #\r
-#    _____   __ __\______   \_____  _______  ______  ____ _______     #\r
-#   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \    #\r
-#  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/    #\r
-#  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|       #\r
-#        \/                       \/            \/      \/            #\r
-#                                        Fast math parser Library    #\r
-#                                                                     #\r
-#  Copyright (C) 2011 Ingo Berg                                       #\r
-#                                                                     #\r
-#  Web:     muparser.beltoforion.de                                   #\r
-#  e-mail:  muparser@beltoforion.de                                   #\r
-#                                                                     #\r
-#                                                                     #\r
-#######################################################################\r
-\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-  OR OTHER DEALINGS IN THE SOFTWARE.\r
diff --git a/bundled/muparser_v2_2_4/include/muParser.h b/bundled/muparser_v2_2_4/include/muParser.h
deleted file mode 100644 (file)
index a1caec4..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#ifndef MU_PARSER_H\r
-#define MU_PARSER_H\r
-\r
-//--- Standard includes ------------------------------------------------------------------------\r
-#include <vector>\r
-\r
-//--- Parser includes --------------------------------------------------------------------------\r
-#include "muParserBase.h"\r
-#include "muParserTemplateMagic.h"\r
-\r
-/** \file\r
-    \brief Definition of the standard floating point parser.\r
-*/\r
-\r
-namespace mu\r
-{\r
-  /** \brief Mathematical expressions parser.\r
-    \r
-    Standard implementation of the mathematical expressions parser. \r
-    Can be used as a reference implementation for subclassing the parser.\r
-\r
-    <small>\r
-    (C) 2011 Ingo Berg<br>\r
-    muparser(at)beltoforion.de\r
-    </small>\r
-  */\r
-  /* final */ class Parser : public ParserBase\r
-  {\r
-  public:\r
-\r
-    Parser();\r
-\r
-    virtual void InitCharSets() override;\r
-    virtual void InitFun() override;\r
-    virtual void InitConst() override;\r
-    virtual void InitOprt() override;\r
-    virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd) override;\r
-\r
-    value_type Diff(value_type *a_Var, \r
-                    value_type a_fPos, \r
-                    value_type a_fEpsilon = 0) const;\r
-\r
-  protected:\r
-\r
-    // Trigonometric functions\r
-    static value_type  Sin(value_type);\r
-    static value_type  Cos(value_type);\r
-    static value_type  Tan(value_type);\r
-    static value_type  Tan2(value_type, value_type);\r
-    // arcus functions\r
-    static value_type  ASin(value_type);\r
-    static value_type  ACos(value_type);\r
-    static value_type  ATan(value_type);\r
-    static value_type  ATan2(value_type, value_type);\r
-\r
-    // hyperbolic functions\r
-    static value_type  Sinh(value_type);\r
-    static value_type  Cosh(value_type);\r
-    static value_type  Tanh(value_type);\r
-    // arcus hyperbolic functions\r
-    static value_type  ASinh(value_type);\r
-    static value_type  ACosh(value_type);\r
-    static value_type  ATanh(value_type);\r
-    // Logarithm functions\r
-    static value_type  Log2(value_type);  // Logarithm Base 2\r
-    static value_type  Log10(value_type); // Logarithm Base 10\r
-    static value_type  Ln(value_type);    // Logarithm Base e (natural logarithm)\r
-    // misc\r
-    static value_type  Exp(value_type);\r
-    static value_type  Abs(value_type);\r
-    static value_type  Sqrt(value_type);\r
-    static value_type  Rint(value_type);\r
-    static value_type  Sign(value_type);\r
-\r
-    // Prefix operators\r
-    // !!! Unary Minus is a MUST if you want to use negative signs !!!\r
-    static value_type  UnaryMinus(value_type);\r
-    static value_type  UnaryPlus(value_type);\r
-\r
-    // Functions with variable number of arguments\r
-    static value_type Sum(const value_type*, int);  // sum\r
-    static value_type Avg(const value_type*, int);  // mean value\r
-    static value_type Min(const value_type*, int);  // minimum\r
-    static value_type Max(const value_type*, int);  // maximum\r
-\r
-    static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal);\r
-  };\r
-} // namespace mu\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserBase.h b/bundled/muparser_v2_2_4/include/muParserBase.h
deleted file mode 100644 (file)
index 871724b..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#ifndef MU_PARSER_BASE_H\r
-#define MU_PARSER_BASE_H\r
-\r
-//--- Standard includes ------------------------------------------------------------------------\r
-#include <cmath>\r
-#include <string>\r
-#include <iostream>\r
-#include <map>\r
-#include <memory>\r
-#include <locale>\r
-#include <limits.h>\r
-\r
-//--- Parser includes --------------------------------------------------------------------------\r
-#include "muParserDef.h"\r
-#include "muParserStack.h"\r
-#include "muParserTokenReader.h"\r
-#include "muParserBytecode.h"\r
-#include "muParserError.h"\r
-\r
-\r
-namespace mu\r
-{\r
-/** \file\r
-    \brief This file contains the class definition of the muparser engine.\r
-*/\r
-\r
-//--------------------------------------------------------------------------------------------------\r
-/** \brief Mathematical expressions parser (base parser engine).\r
-    \author (C) 2013 Ingo Berg\r
-\r
-  This is the implementation of a bytecode based mathematical expressions parser. \r
-  The formula will be parsed from string and converted into a bytecode. \r
-  Future calculations will be done with the bytecode instead the formula string\r
-  resulting in a significant performance increase. \r
-  Complementary to a set of internally implemented functions the parser is able to handle \r
-  user defined functions and variables. \r
-*/\r
-class ParserBase \r
-{\r
-friend class ParserTokenReader;\r
-\r
-private:\r
-\r
-    /** \brief Typedef for the parse functions. \r
-    \r
-      The parse function do the actual work. The parser exchanges\r
-      the function pointer to the parser function depending on \r
-      which state it is in. (i.e. bytecode parser vs. string parser)\r
-    */\r
-    typedef value_type (ParserBase::*ParseFunction)() const;  \r
-\r
-    /** \brief Type used for storing an array of values. */\r
-    typedef std::vector<value_type> valbuf_type;\r
-\r
-    /** \brief Type for a vector of strings. */\r
-    typedef std::vector<string_type> stringbuf_type;\r
-\r
-    /** \brief Typedef for the token reader. */\r
-    typedef ParserTokenReader token_reader_type;\r
-    \r
-    /** \brief Type used for parser tokens. */\r
-    typedef ParserToken<value_type, string_type> token_type;\r
-\r
-    /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */\r
-    static const int s_MaxNumOpenMPThreads = 16;\r
-\r
- public:\r
-\r
-    /** \brief Type of the error class. \r
-    \r
-      Included for backwards compatibility.\r
-    */\r
-    typedef ParserError exception_type;\r
-\r
-    static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);\r
-\r
-    ParserBase(); \r
-    ParserBase(const ParserBase &a_Parser);\r
-    ParserBase& operator=(const ParserBase &a_Parser);\r
-\r
-    virtual ~ParserBase();\r
-    \r
-         value_type  Eval() const;\r
-    value_type* Eval(int &nStackSize) const;\r
-    void Eval(value_type *results, int nBulkSize);\r
-\r
-    int GetNumResults() const;\r
-\r
-    void SetExpr(const string_type &a_sExpr);\r
-    void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);\r
-\r
-    void SetDecSep(char_type cDecSep);\r
-    void SetThousandsSep(char_type cThousandsSep = 0);\r
-    void ResetLocale();\r
-\r
-    void EnableOptimizer(bool a_bIsOn=true);\r
-    void EnableBuiltInOprt(bool a_bIsOn=true);\r
-\r
-    bool HasBuiltInOprt() const;\r
-    void AddValIdent(identfun_type a_pCallback);\r
-\r
-    /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) \r
-        \brief Define a parser function without arguments.\r
-        \param a_strName Name of the function\r
-        \param a_pFun Pointer to the callback function\r
-        \param a_bAllowOpt A flag indicating this function may be optimized\r
-    */\r
-    template<typename T>\r
-    void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)\r
-    {\r
-      AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );\r
-    }\r
-\r
-    void DefineOprt(const string_type &a_strName, \r
-                    fun_type2 a_pFun, \r
-                    unsigned a_iPri=0, \r
-                    EOprtAssociativity a_eAssociativity = oaLEFT,\r
-                    bool a_bAllowOpt = false);\r
-    void DefineConst(const string_type &a_sName, value_type a_fVal);\r
-    void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);\r
-    void DefineVar(const string_type &a_sName, value_type *a_fVar);\r
-    void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);\r
-    void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);\r
-\r
-    // Clear user defined variables, constants or functions\r
-    void ClearVar();\r
-    void ClearFun();\r
-    void ClearConst();\r
-    void ClearInfixOprt();\r
-    void ClearPostfixOprt();\r
-    void ClearOprt();\r
-    \r
-    void RemoveVar(const string_type &a_strVarName);\r
-    const varmap_type& GetUsedVar() const;\r
-    const varmap_type& GetVar() const;\r
-    const valmap_type& GetConst() const;\r
-    const string_type& GetExpr() const;\r
-    const funmap_type& GetFunDef() const;\r
-    string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;\r
-\r
-    const char_type ** GetOprtDef() const;\r
-    void DefineNameChars(const char_type *a_szCharset);\r
-    void DefineOprtChars(const char_type *a_szCharset);\r
-    void DefineInfixOprtChars(const char_type *a_szCharset);\r
-\r
-    const char_type* ValidNameChars() const;\r
-    const char_type* ValidOprtChars() const;\r
-    const char_type* ValidInfixOprtChars() const;\r
-\r
-    void SetArgSep(char_type cArgSep);\r
-    char_type GetArgSep() const;\r
-    \r
-    void  Error(EErrorCodes a_iErrc, \r
-                int a_iPos = (int)mu::string_type::npos, \r
-                const string_type &a_strTok = string_type() ) const;\r
-\r
- protected:\r
-         \r
-    void Init();\r
-\r
-    virtual void InitCharSets() = 0;\r
-    virtual void InitFun() = 0;\r
-    virtual void InitConst() = 0;\r
-    virtual void InitOprt() = 0; \r
-\r
-    virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);\r
-\r
-    static const char_type *c_DefaultOprt[]; \r
-    static std::locale s_locale;  ///< The locale used by the parser\r
-    static bool g_DbgDumpCmdCode;\r
-    static bool g_DbgDumpStack;\r
-\r
-    /** \brief A facet class used to change decimal and thousands separator. */\r
-    template<class TChar>\r
-    class change_dec_sep : public std::numpunct<TChar>\r
-    {\r
-    public:\r
-      \r
-      explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
-        :std::numpunct<TChar>()\r
-        ,m_nGroup(nGroup)\r
-        ,m_cDecPoint(cDecSep)\r
-        ,m_cThousandsSep(cThousandsSep)\r
-      {}\r
-      \r
-    protected:\r
-      \r
-      virtual char_type do_decimal_point() const override\r
-      {\r
-        return m_cDecPoint;\r
-      }\r
-\r
-      virtual char_type do_thousands_sep() const override\r
-      {\r
-        return m_cThousandsSep;\r
-      }\r
-\r
-      virtual std::string do_grouping() const override\r
-      { \r
-               // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4\r
-               // courtesy of Jens Bartsch\r
-               // original code:\r
-               //        return std::string(1, (char)m_nGroup); \r
-               // new code:\r
-               return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));\r
-      }\r
-\r
-    private:\r
-\r
-      int m_nGroup;\r
-      char_type m_cDecPoint;  \r
-      char_type m_cThousandsSep;\r
-    };\r
-\r
- private:\r
-\r
-    void Assign(const ParserBase &a_Parser);\r
-    void InitTokenReader();\r
-    void ReInit() const;\r
-\r
-    void AddCallback( const string_type &a_strName, \r
-                      const ParserCallback &a_Callback, \r
-                      funmap_type &a_Storage,\r
-                      const char_type *a_szCharSet );\r
-\r
-    void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt,\r
-                                ParserStack<token_type> &a_stVal) const;\r
-    void ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
-                      ParserStack<token_type> &a_stVal) const;\r
-\r
-    void ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
-                     ParserStack<token_type> &a_stVal) const;\r
-\r
-    void ApplyFunc(ParserStack<token_type> &a_stOpt,\r
-                   ParserStack<token_type> &a_stVal, \r
-                   int iArgCount) const; \r
-\r
-    token_type ApplyStrFunc(const token_type &a_FunTok,\r
-                            const std::vector<token_type> &a_vArg) const;\r
-\r
-    int GetOprtPrecedence(const token_type &a_Tok) const;\r
-    EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;\r
-\r
-    void CreateRPN() const;\r
-\r
-    value_type ParseString() const; \r
-    value_type ParseCmdCode() const;\r
-    value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;\r
-\r
-    void  CheckName(const string_type &a_strName, const string_type &a_CharSet) const;\r
-    void  CheckOprt(const string_type &a_sName,\r
-                    const ParserCallback &a_Callback,\r
-                    const string_type &a_szCharSet) const;\r
-\r
-    void StackDump(const ParserStack<token_type > &a_stVal, \r
-                   const ParserStack<token_type > &a_stOprt) const;\r
-\r
-    /** \brief Pointer to the parser function. \r
-    \r
-      Eval() calls the function whose address is stored there.\r
-    */\r
-    mutable ParseFunction  m_pParseFormula;\r
-    mutable ParserByteCode m_vRPN;        ///< The Bytecode class.\r
-    mutable stringbuf_type  m_vStringBuf; ///< String buffer, used for storing string function arguments\r
-    stringbuf_type  m_vStringVarBuf;\r
-\r
-    std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.\r
-\r
-    funmap_type  m_FunDef;         ///< Map of function names and pointers.\r
-    funmap_type  m_PostOprtDef;    ///< Postfix operator callbacks\r
-    funmap_type  m_InfixOprtDef;   ///< unary infix operator.\r
-    funmap_type  m_OprtDef;        ///< Binary operator callbacks\r
-    valmap_type  m_ConstDef;       ///< user constants.\r
-    strmap_type  m_StrVarDef;      ///< user defined string constants\r
-    varmap_type  m_VarDef;         ///< user defind variables.\r
-\r
-    bool m_bBuiltInOp;             ///< Flag that can be used for switching built in operators on and off\r
-\r
-    string_type m_sNameChars;      ///< Charset for names\r
-    string_type m_sOprtChars;      ///< Charset for postfix/ binary operator tokens\r
-    string_type m_sInfixOprtChars; ///< Charset for infix operator tokens\r
-    \r
-    mutable int m_nIfElseCounter;  ///< Internal counter for keeping track of nested if-then-else clauses\r
-\r
-    // items merely used for caching state information\r
-    mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine\r
-    mutable int m_nFinalResultIdx;\r
-};\r
-\r
-} // namespace mu\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserBytecode.h b/bundled/muparser_v2_2_4/include/muParserBytecode.h
deleted file mode 100644 (file)
index f7bf9c6..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#ifndef MU_PARSER_BYTECODE_H\r
-#define MU_PARSER_BYTECODE_H\r
-\r
-#include <cassert>\r
-#include <string>\r
-#include <stack>\r
-#include <vector>\r
-\r
-#include "muParserDef.h"\r
-#include "muParserError.h"\r
-#include "muParserToken.h"\r
-\r
-/** \file\r
-    \brief Definition of the parser bytecode class.\r
-*/\r
-\r
-\r
-namespace mu\r
-{\r
-  struct SToken\r
-  {\r
-    ECmdCode Cmd;\r
-    int StackPos;\r
-\r
-    union\r
-    {\r
-      struct //SValData\r
-      {\r
-        value_type *ptr;\r
-        value_type  data;\r
-        value_type  data2;\r
-      } Val;\r
-\r
-      struct //SFunData\r
-      {\r
-        // Note: generic_fun_type is merely a placeholder. The real type could be \r
-        //       anything between gun_type1 and fun_type9. I can't use a void\r
-        //       pointer due to constraints in the ANSI standard which allows\r
-        //       data pointers and function pointers to differ in size.\r
-        generic_fun_type ptr;\r
-        int   argc;\r
-        int   idx;\r
-      } Fun;\r
-\r
-      struct //SOprtData\r
-      {\r
-        value_type *ptr;\r
-        int offset;\r
-      } Oprt;\r
-    } u;\r
-  };\r
-  \r
-  \r
-  /** \brief Bytecode implementation of the Math Parser.\r
-\r
-  The bytecode contains the formula converted to revers polish notation stored in a continious\r
-  memory area. Associated with this data are operator codes, variable pointers, constant \r
-  values and function pointers. Those are necessary in order to calculate the result.\r
-  All those data items will be casted to the underlying datatype of the bytecode.\r
-\r
-  \author (C) 2004-2013 Ingo Berg \r
-*/\r
-class ParserByteCode\r
-{\r
-private:\r
-\r
-    /** \brief Token type for internal use only. */\r
-    typedef ParserToken<value_type, string_type> token_type;\r
-\r
-    /** \brief Token vector for storing the RPN. */\r
-    typedef std::vector<SToken> rpn_type;\r
-\r
-    /** \brief Position in the Calculation array. */\r
-    unsigned m_iStackPos;\r
-\r
-    /** \brief Maximum size needed for the stack. */\r
-    std::size_t m_iMaxStackSize;\r
-    \r
-    /** \brief The actual rpn storage. */\r
-    rpn_type  m_vRPN;\r
-\r
-    bool m_bEnableOptimizer;\r
-\r
-    void ConstantFolding(ECmdCode a_Oprt);\r
-\r
-public:\r
-\r
-    ParserByteCode();\r
-    ParserByteCode(const ParserByteCode &a_ByteCode);\r
-    ParserByteCode& operator=(const ParserByteCode &a_ByteCode);\r
-    void Assign(const ParserByteCode &a_ByteCode);\r
-\r
-    void AddVar(value_type *a_pVar);\r
-    void AddVal(value_type a_fVal);\r
-    void AddOp(ECmdCode a_Oprt);\r
-    void AddIfElse(ECmdCode a_Oprt);\r
-    void AddAssignOp(value_type *a_pVar);\r
-    void AddFun(generic_fun_type a_pFun, int a_iArgc);\r
-    void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);\r
-    void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);\r
-\r
-    void EnableOptimizer(bool bStat);\r
-\r
-    void Finalize();\r
-    void clear();\r
-    std::size_t GetMaxStackSize() const;\r
-    std::size_t GetSize() const;\r
-\r
-    const SToken* GetBase() const;\r
-    void AsciiDump();\r
-};\r
-\r
-} // namespace mu\r
-\r
-#endif\r
-\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserCallback.h b/bundled/muparser_v2_2_4/include/muParserCallback.h
deleted file mode 100644 (file)
index cdaffbb..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_CALLBACK_H\r
-#define MU_PARSER_CALLBACK_H\r
-\r
-#include "muParserDef.h"\r
-\r
-/** \file\r
-    \brief Definition of the parser callback class.\r
-*/\r
-\r
-namespace mu\r
-{\r
-\r
-/** \brief Encapsulation of prototypes for a numerical parser function.\r
-\r
-    Encapsulates the prototyp for numerical parser functions. The class\r
-    stores the number of arguments for parser functions as well\r
-    as additional flags indication the function is non optimizeable.\r
-    The pointer to the callback function pointer is stored as void* \r
-    and needs to be casted according to the argument count.\r
-    Negative argument counts indicate a parser function with a variable number\r
-    of arguments. \r
-\r
-    \author (C) 2004-2011 Ingo Berg\r
-*/\r
-class ParserCallback\r
-{\r
-public:\r
-    ParserCallback(fun_type0  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type1  a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);\r
-    ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);\r
-    ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type3  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type4  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type5  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type6  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type7  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type8  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type9  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);\r
-\r
-    ParserCallback(bulkfun_type0  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type1  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type2  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type3  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type4  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type5  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type6  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type7  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type8  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type9  a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);\r
-\r
-    ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);\r
-    ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);\r
-    ParserCallback();\r
-    ParserCallback(const ParserCallback &a_Fun);\r
-\r
-    // deall.II: added the following line to remove Wdeprecated-copy warnings:\r
-    ParserCallback& operator=(const ParserCallback&)=default;\r
-    \r
-    ParserCallback* Clone() const;\r
-\r
-    bool  IsOptimizable() const;\r
-    void* GetAddr() const;\r
-    ECmdCode  GetCode() const;\r
-    ETypeCode GetType() const;\r
-    int GetPri()  const;\r
-    EOprtAssociativity GetAssociativity() const;\r
-    int GetArgc() const;\r
-\r
-private:\r
-    void *m_pFun;                   ///< Pointer to the callback function, casted to void\r
-    \r
-    /** \brief Number of numeric function arguments\r
-    \r
-        This number is negative for functions with variable number of arguments. in this cases\r
-        they represent the actual number of arguments found.\r
-    */\r
-    int   m_iArgc;      \r
-    int   m_iPri;                   ///< Valid only for binary and infix operators; Operator precedence.\r
-    EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators \r
-    ECmdCode  m_iCode;\r
-    ETypeCode m_iType;\r
-    bool  m_bAllowOpti;             ///< Flag indication optimizeability \r
-};\r
-\r
-//------------------------------------------------------------------------------\r
-/** \brief Container for Callback objects. */\r
-typedef std::map<string_type, ParserCallback> funmap_type; \r
-\r
-} // namespace mu\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserDef.h b/bundled/muparser_v2_2_4/include/muParserDef.h
deleted file mode 100644 (file)
index 5842921..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2014 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#ifndef MUP_DEF_H\r
-#define MUP_DEF_H\r
-\r
-#include <iostream>\r
-#include <string>\r
-#include <sstream>\r
-#include <map>\r
-\r
-#include "muParserFixes.h"\r
-\r
-/** \file\r
-    \brief This file contains standard definitions used by the parser.\r
-*/\r
-\r
-#define MUP_VERSION _T("2.2.4")\r
-#define MUP_VERSION_DATE _T("20141210; GC")\r
-\r
-#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")\r
-\r
-/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */\r
-//#define MUP_MATH_EXCEPTIONS\r
-\r
-/** \brief Define the base datatype for values.\r
-\r
-  This datatype must be a built in value type. You can not use custom classes.\r
-  It should be working with all types except "int"!\r
-*/\r
-#define MUP_BASETYPE double\r
-\r
-/** \brief Activate this option in order to compile with OpenMP support. \r
-\r
-  OpenMP is used only in the bulk mode it may increase the performance a bit. \r
-*/\r
-//#define MUP_USE_OPENMP\r
-\r
-#if defined(_UNICODE)\r
-  /** \brief Definition of the basic parser string type. */\r
-  #define MUP_STRING_TYPE std::wstring\r
-\r
-  #if !defined(_T)\r
-    #define _T(x) L##x\r
-  #endif // not defined _T\r
-#else\r
-  #ifndef _T\r
-  #define _T(x) x\r
-  #endif\r
-  \r
-  /** \brief Definition of the basic parser string type. */\r
-  #define MUP_STRING_TYPE std::string\r
-#endif\r
-\r
-#if defined(_DEBUG)\r
-  /** \brief Debug macro to force an abortion of the programm with a certain message.\r
-  */\r
-  #define MUP_FAIL(MSG)     \\r
-          {                 \\r
-            bool MSG=false; \\r
-            assert(MSG);    \\r
-          }\r
-\r
-    /** \brief An assertion that does not kill the program.\r
-\r
-        This macro is neutralised in UNICODE builds. It's\r
-        too difficult to translate.\r
-    */\r
-    #define MUP_ASSERT(COND)                         \\r
-            if (!(COND))                             \\r
-            {                                        \\r
-              stringstream_type ss;                  \\r
-              ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \\r
-                 << __FILE__ << _T(" line ")         \\r
-                 << __LINE__ << _T(".");             \\r
-              throw ParserError( ss.str() );         \\r
-            }\r
-#else\r
-  #define MUP_FAIL(MSG)\r
-  #define MUP_ASSERT(COND)\r
-#endif\r
-\r
-\r
-namespace mu\r
-{\r
-#if defined(_UNICODE)\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Encapsulate wcout. */\r
-  inline std::wostream& console()\r
-  {\r
-    return std::wcout;\r
-  }\r
-\r
-  /** \brief Encapsulate cin. */\r
-  inline std::wistream& console_in()\r
-  {\r
-    return std::wcin;\r
-  }\r
-\r
-#else\r
-\r
-  /** \brief Encapsulate cout. \r
-  \r
-    Used for supporting UNICODE more easily.\r
-  */\r
-  inline std::ostream& console()\r
-  {\r
-    return std::cout;\r
-  }\r
-\r
-  /** \brief Encapsulate cin. \r
-\r
-    Used for supporting UNICODE more easily.\r
-  */\r
-  inline std::istream& console_in()\r
-  {\r
-    return std::cin;\r
-  }\r
-\r
-#endif\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Bytecode values.\r
-\r
-      \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!\r
-  */\r
-  enum ECmdCode\r
-  {\r
-    // The following are codes for built in binary operators\r
-    // apart from built in operators the user has the opportunity to\r
-    // add user defined operators.\r
-    cmLE            = 0,   ///< Operator item:  less or equal\r
-    cmGE            = 1,   ///< Operator item:  greater or equal\r
-    cmNEQ           = 2,   ///< Operator item:  not equal\r
-    cmEQ            = 3,   ///< Operator item:  equals\r
-    cmLT            = 4,   ///< Operator item:  less than\r
-    cmGT            = 5,   ///< Operator item:  greater than\r
-    cmADD           = 6,   ///< Operator item:  add\r
-    cmSUB           = 7,   ///< Operator item:  subtract\r
-    cmMUL           = 8,   ///< Operator item:  multiply\r
-    cmDIV           = 9,   ///< Operator item:  division\r
-    cmPOW           = 10,  ///< Operator item:  y to the power of ...\r
-    cmLAND          = 11,\r
-    cmLOR           = 12,\r
-    cmASSIGN        = 13,  ///< Operator item:  Assignment operator\r
-    cmBO            = 14,  ///< Operator item:  opening bracket\r
-    cmBC            = 15,  ///< Operator item:  closing bracket\r
-    cmIF            = 16,  ///< For use in the ternary if-then-else operator\r
-    cmELSE          = 17,  ///< For use in the ternary if-then-else operator\r
-    cmENDIF         = 18,  ///< For use in the ternary if-then-else operator\r
-    cmARG_SEP       = 19,  ///< function argument separator\r
-    cmVAR           = 20,  ///< variable item\r
-    cmVAL           = 21,  ///< value item\r
-\r
-    // For optimization purposes\r
-    cmVARPOW2,\r
-    cmVARPOW3,\r
-    cmVARPOW4,\r
-    cmVARMUL,\r
-    cmPOW2,\r
-\r
-    // operators and functions\r
-    cmFUNC,                ///< Code for a generic function item\r
-    cmFUNC_STR,            ///< Code for a function with a string parameter\r
-    cmFUNC_BULK,           ///< Special callbacks for Bulk mode with an additional parameter for the bulk index \r
-    cmSTRING,              ///< Code for a string token\r
-    cmOPRT_BIN,            ///< user defined binary operator\r
-    cmOPRT_POSTFIX,        ///< code for postfix operators\r
-    cmOPRT_INFIX,          ///< code for infix operators\r
-    cmEND,                 ///< end of formula\r
-    cmUNKNOWN              ///< uninitialized item\r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Types internally used by the parser.\r
-  */\r
-  enum ETypeCode\r
-  {\r
-    tpSTR  = 0,     ///< String type (Function arguments and constants only, no string variables)\r
-    tpDBL  = 1,     ///< Floating point variables\r
-    tpVOID = 2      ///< Undefined type.\r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  enum EParserVersionInfo\r
-  {\r
-    pviBRIEF,\r
-    pviFULL\r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Parser operator precedence values. */\r
-  enum EOprtAssociativity\r
-  {\r
-    oaLEFT  = 0,\r
-    oaRIGHT = 1,\r
-    oaNONE  = 2\r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Parser operator precedence values. */\r
-  enum EOprtPrecedence\r
-  {\r
-    // binary operators\r
-    prLOR     = 1,\r
-    prLAND    = 2,\r
-    prLOGIC   = 3,  ///< logic operators\r
-    prCMP     = 4,  ///< comparsion operators\r
-    prADD_SUB = 5,  ///< addition\r
-    prMUL_DIV = 6,  ///< multiplication/division\r
-    prPOW     = 7,  ///< power operator priority (highest)\r
-\r
-    // infix operators\r
-    prINFIX   = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator\r
-    prPOSTFIX = 6  ///< Postfix operator priority (currently unused)\r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  // basic types\r
-\r
-  /** \brief The numeric datatype used by the parser. \r
-  \r
-    Normally this is a floating point type either single or double precision.\r
-  */\r
-  typedef MUP_BASETYPE value_type;\r
-\r
-  /** \brief The stringtype used by the parser. \r
-\r
-    Depends on wether UNICODE is used or not.\r
-  */\r
-  typedef MUP_STRING_TYPE string_type;\r
-\r
-  /** \brief The character type used by the parser. \r
-  \r
-    Depends on wether UNICODE is used or not.\r
-  */\r
-  typedef string_type::value_type char_type;\r
-\r
-  /** \brief Typedef for easily using stringstream that respect the parser stringtype. */\r
-  typedef std::basic_stringstream<char_type,\r
-                                  std::char_traits<char_type>,\r
-                                  std::allocator<char_type> > stringstream_type;\r
-\r
-  // Data container types\r
-\r
-  /** \brief Type used for storing variables. */\r
-  typedef std::map<string_type, value_type*> varmap_type;\r
-  \r
-  /** \brief Type used for storing constants. */\r
-  typedef std::map<string_type, value_type> valmap_type;\r
-  \r
-  /** \brief Type for assigning a string name to an index in the internal string table. */\r
-  typedef std::map<string_type, std::size_t> strmap_type;\r
-\r
-  // Parser callbacks\r
-  \r
-  /** \brief Callback type used for functions without arguments. */\r
-  typedef value_type (*generic_fun_type)();\r
-\r
-  /** \brief Callback type used for functions without arguments. */\r
-  typedef value_type (*fun_type0)();\r
-\r
-  /** \brief Callback type used for functions with a single arguments. */\r
-  typedef value_type (*fun_type1)(value_type);\r
-\r
-  /** \brief Callback type used for functions with two arguments. */\r
-  typedef value_type (*fun_type2)(value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with three arguments. */\r
-  typedef value_type (*fun_type3)(value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with four arguments. */\r
-  typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions without arguments. */\r
-  typedef value_type (*bulkfun_type0)(int, int);\r
-\r
-  /** \brief Callback type used for functions with a single arguments. */\r
-  typedef value_type (*bulkfun_type1)(int, int, value_type);\r
-\r
-  /** \brief Callback type used for functions with two arguments. */\r
-  typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with three arguments. */\r
-  typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with four arguments. */\r
-  typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with five arguments. */\r
-  typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
-\r
-  /** \brief Callback type used for functions with a variable argument list. */\r
-  typedef value_type (*multfun_type)(const value_type*, int);\r
-\r
-  /** \brief Callback type used for functions taking a string as an argument. */\r
-  typedef value_type (*strfun_type1)(const char_type*);\r
-\r
-  /** \brief Callback type used for functions taking a string and a value as arguments. */\r
-  typedef value_type (*strfun_type2)(const char_type*, value_type);\r
-\r
-  /** \brief Callback type used for functions taking a string and two values as arguments. */\r
-  typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);\r
-\r
-  /** \brief Callback used for functions that identify values in a string. */\r
-  typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal);\r
-\r
-  /** \brief Callback used for variable creation factory functions. */\r
-  typedef value_type* (*facfun_type)(const char_type*, void*);\r
-} // end of namespace\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserError.h b/bundled/muparser_v2_2_4/include/muParserError.h
deleted file mode 100644 (file)
index 7f88e99..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_ERROR_H\r
-#define MU_PARSER_ERROR_H\r
-\r
-#include <cassert>\r
-#include <stdexcept>\r
-#include <string>\r
-#include <sstream>\r
-#include <vector>\r
-#include <memory>\r
-\r
-#include "muParserDef.h"\r
-\r
-/** \file \r
-    \brief This file defines the error class used by the parser.\r
-*/\r
-\r
-namespace mu\r
-{\r
-\r
-/** \brief Error codes. */\r
-enum EErrorCodes\r
-{\r
-  // Formula syntax errors\r
-  ecUNEXPECTED_OPERATOR    = 0,  ///< Unexpected binary operator found\r
-  ecUNASSIGNABLE_TOKEN     = 1,  ///< Token cant be identified.\r
-  ecUNEXPECTED_EOF         = 2,  ///< Unexpected end of formula. (Example: "2+sin(")\r
-  ecUNEXPECTED_ARG_SEP     = 3,  ///< An unexpected comma has been found. (Example: "1,23")\r
-  ecUNEXPECTED_ARG         = 4,  ///< An unexpected argument has been found\r
-  ecUNEXPECTED_VAL         = 5,  ///< An unexpected value token has been found\r
-  ecUNEXPECTED_VAR         = 6,  ///< An unexpected variable token has been found\r
-  ecUNEXPECTED_PARENS      = 7,  ///< Unexpected Parenthesis, opening or closing\r
-  ecUNEXPECTED_STR         = 8,  ///< A string has been found at an inapropriate position\r
-  ecSTRING_EXPECTED        = 9,  ///< A string function has been called with a different type of argument\r
-  ecVAL_EXPECTED           = 10, ///< A numerical function has been called with a non value type of argument\r
-  ecMISSING_PARENS         = 11, ///< Missing parens. (Example: "3*sin(3")\r
-  ecUNEXPECTED_FUN         = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")\r
-  ecUNTERMINATED_STRING    = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")\r
-  ecTOO_MANY_PARAMS        = 14, ///< Too many function parameters\r
-  ecTOO_FEW_PARAMS         = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")\r
-  ecOPRT_TYPE_CONFLICT     = 16, ///< binary operators may only be applied to value items of the same type\r
-  ecSTR_RESULT             = 17, ///< result is a string\r
-\r
-  // Invalid Parser input Parameters\r
-  ecINVALID_NAME           = 18, ///< Invalid function, variable or constant name.\r
-  ecINVALID_BINOP_IDENT    = 19, ///< Invalid binary operator identifier\r
-  ecINVALID_INFIX_IDENT    = 20, ///< Invalid function, variable or constant name.\r
-  ecINVALID_POSTFIX_IDENT  = 21, ///< Invalid function, variable or constant name.\r
-\r
-  ecBUILTIN_OVERLOAD       = 22, ///< Trying to overload builtin operator\r
-  ecINVALID_FUN_PTR        = 23, ///< Invalid callback function pointer \r
-  ecINVALID_VAR_PTR        = 24, ///< Invalid variable pointer \r
-  ecEMPTY_EXPRESSION       = 25, ///< The Expression is empty\r
-  ecNAME_CONFLICT          = 26, ///< Name conflict\r
-  ecOPT_PRI                = 27, ///< Invalid operator priority\r
-  // \r
-  ecDOMAIN_ERROR           = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)\r
-  ecDIV_BY_ZERO            = 29, ///< Division by zero (currently unused)\r
-  ecGENERIC                = 30, ///< Generic error\r
-  ecLOCALE                 = 31, ///< Conflict with current locale\r
-\r
-  ecUNEXPECTED_CONDITIONAL = 32,\r
-  ecMISSING_ELSE_CLAUSE    = 33, \r
-  ecMISPLACED_COLON        = 34,\r
-\r
-  ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35,\r
-\r
-  // internal errors\r
-  ecINTERNAL_ERROR         = 36, ///< Internal error of any kind.\r
-  \r
-  // The last two are special entries \r
-  ecCOUNT,                      ///< This is no error code, It just stores just the total number of error codes\r
-  ecUNDEFINED              = -1  ///< Undefined message, placeholder to detect unassigned error messages\r
-};\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief A class that handles the error messages.\r
-*/\r
-class ParserErrorMsg\r
-{\r
-public:\r
-    typedef ParserErrorMsg self_type;\r
-\r
-    ParserErrorMsg& operator=(const ParserErrorMsg &);\r
-    ParserErrorMsg(const ParserErrorMsg&);\r
-    ParserErrorMsg();\r
-\r
-   ~ParserErrorMsg();\r
-\r
-    static const ParserErrorMsg& Instance();\r
-    string_type operator[](unsigned a_iIdx) const;\r
-\r
-private:\r
-    std::vector<string_type>  m_vErrMsg;  ///< A vector with the predefined error messages\r
-    static const self_type m_Instance;    ///< The instance pointer\r
-};\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief Error class of the parser. \r
-    \author Ingo Berg\r
-\r
-  Part of the math parser package.\r
-*/\r
-class ParserError\r
-{\r
-private:\r
-\r
-    /** \brief Replace all ocuurences of a substring with another string. */\r
-    void ReplaceSubString( string_type &strSource, \r
-                           const string_type &strFind,\r
-                           const string_type &strReplaceWith);\r
-    void Reset();\r
-\r
-public:\r
-\r
-    ParserError();\r
-    explicit ParserError(EErrorCodes a_iErrc);\r
-    explicit ParserError(const string_type &sMsg);\r
-    ParserError( EErrorCodes a_iErrc,\r
-                 const string_type &sTok,\r
-                 const string_type &sFormula = string_type(),\r
-                 int a_iPos = -1);\r
-    ParserError( EErrorCodes a_iErrc, \r
-                 int a_iPos, \r
-                 const string_type &sTok);\r
-    ParserError( const char_type *a_szMsg, \r
-                 int a_iPos = -1, \r
-                 const string_type &sTok = string_type());\r
-    ParserError(const ParserError &a_Obj);\r
-    ParserError& operator=(const ParserError &a_Obj);\r
-   ~ParserError();\r
-\r
-    void SetFormula(const string_type &a_strFormula);\r
-    const string_type& GetExpr() const;\r
-    const string_type& GetMsg() const;\r
-    int GetPos() const;\r
-    const string_type& GetToken() const;\r
-    EErrorCodes GetCode() const;\r
-\r
-private:\r
-    string_type m_strMsg;     ///< The message string\r
-    string_type m_strFormula; ///< Formula string\r
-    string_type m_strTok;     ///< Token related with the error\r
-    int m_iPos;               ///< Formula position related to the error \r
-    EErrorCodes m_iErrc;      ///< Error code\r
-    const ParserErrorMsg &m_ErrMsg;\r
-};             \r
-\r
-} // namespace mu\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserFixes.h b/bundled/muparser_v2_2_4/include/muParserFixes.h
deleted file mode 100644 (file)
index 1cd15e0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_FIXES_H\r
-#define MU_PARSER_FIXES_H\r
-\r
-/** \file\r
-    \brief This file contains compatibility fixes for some platforms.\r
-*/\r
-\r
-//\r
-// Compatibility fixes\r
-//\r
-\r
-//---------------------------------------------------------------------------\r
-//\r
-// Intel Compiler\r
-//\r
-//---------------------------------------------------------------------------\r
-\r
-#ifdef __INTEL_COMPILER\r
-\r
-// remark #981: operands are evaluated in unspecified order\r
-// disabled -> completely pointless if the functions do not have side effects\r
-//\r
-#pragma warning(disable:981)\r
-\r
-// remark #383: value copied to temporary, reference to temporary used\r
-#pragma warning(disable:383)\r
-\r
-// remark #1572: floating-point equality and inequality comparisons are unreliable\r
-// disabled -> everyone knows it, the parser passes this problem\r
-//             deliberately to the user\r
-#pragma warning(disable:1572)\r
-\r
-#endif\r
-\r
-#endif // include guard\r
-\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserInt.h b/bundled/muparser_v2_2_4/include/muParserInt.h
deleted file mode 100644 (file)
index 61e7740..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_INT_H\r
-#define MU_PARSER_INT_H\r
-\r
-#include "muParserBase.h"\r
-#include <vector>\r
-\r
-\r
-/** \file\r
-    \brief Definition of a parser using integer value.\r
-*/\r
-\r
-\r
-namespace mu\r
-{\r
-\r
-/** \brief Mathematical expressions parser.\r
-  \r
-  This version of the parser handles only integer numbers. It disables the built in operators thus it is \r
-  slower than muParser. Integer values are stored in the double value_type and converted if needed.\r
-*/\r
-class ParserInt : public ParserBase\r
-{\r
-private:\r
-    static int  Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };\r
-  \r
-    static value_type  Abs(value_type);\r
-    static value_type  Sign(value_type);\r
-    static value_type  Ite(value_type, value_type, value_type);\r
-    // !! The unary Minus is a MUST, otherwise you cant use negative signs !!\r
-    static value_type  UnaryMinus(value_type);\r
-    // Functions with variable number of arguments\r
-    static value_type  Sum(const value_type* a_afArg, int a_iArgc);  // sum\r
-    static value_type  Min(const value_type* a_afArg, int a_iArgc);  // minimum\r
-    static value_type  Max(const value_type* a_afArg, int a_iArgc);  // maximum\r
-    // binary operator callbacks\r
-    static value_type  Add(value_type v1, value_type v2);\r
-    static value_type  Sub(value_type v1, value_type v2);\r
-    static value_type  Mul(value_type v1, value_type v2);\r
-    static value_type  Div(value_type v1, value_type v2);\r
-    static value_type  Mod(value_type v1, value_type v2);\r
-    static value_type  Pow(value_type v1, value_type v2);\r
-    static value_type  Shr(value_type v1, value_type v2);\r
-    static value_type  Shl(value_type v1, value_type v2);\r
-    static value_type  LogAnd(value_type v1, value_type v2);\r
-    static value_type  LogOr(value_type v1, value_type v2);\r
-    static value_type  And(value_type v1, value_type v2);\r
-    static value_type  Or(value_type v1, value_type v2);\r
-    static value_type  Xor(value_type v1, value_type v2);\r
-    static value_type  Less(value_type v1, value_type v2);\r
-    static value_type  Greater(value_type v1, value_type v2);\r
-    static value_type  LessEq(value_type v1, value_type v2);\r
-    static value_type  GreaterEq(value_type v1, value_type v2);\r
-    static value_type  Equal(value_type v1, value_type v2);\r
-    static value_type  NotEqual(value_type v1, value_type v2);\r
-    static value_type  Not(value_type v1);\r
-\r
-    static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
-    static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
-    static int IsVal   (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
-\r
-    /** \brief A facet class used to change decimal and thousands separator. */\r
-    template<class TChar>\r
-    class change_dec_sep : public std::numpunct<TChar>\r
-    {\r
-    public:\r
-      \r
-      explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
-        :std::numpunct<TChar>()\r
-        ,m_cDecPoint(cDecSep)\r
-        ,m_cThousandsSep(cThousandsSep)\r
-        ,m_nGroup(nGroup)\r
-      {}\r
-      \r
-    protected:\r
-      \r
-      virtual char_type do_decimal_point() const\r
-      {\r
-        return m_cDecPoint;\r
-      }\r
-\r
-      virtual char_type do_thousands_sep() const\r
-      {\r
-        return m_cThousandsSep;\r
-      }\r
-\r
-      virtual std::string do_grouping() const \r
-      { \r
-        // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4\r
-        // courtesy of Jens Bartsch\r
-        // original code:\r
-        //        return std::string(1, (char)m_nGroup); \r
-        // new code:\r
-        return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));\r
-      }\r
-\r
-    private:\r
-\r
-      int m_nGroup;\r
-      char_type m_cDecPoint;  \r
-      char_type m_cThousandsSep;\r
-    };\r
-\r
-public:\r
-    ParserInt();\r
-\r
-    virtual void InitFun() override;\r
-    virtual void InitOprt() override;\r
-    virtual void InitConst() override;\r
-    virtual void InitCharSets() override;\r
-};\r
-\r
-} // namespace mu\r
-\r
-#endif\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserTemplateMagic.h b/bundled/muparser_v2_2_4/include/muParserTemplateMagic.h
deleted file mode 100644 (file)
index 1626cae..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef MU_PARSER_TEMPLATE_MAGIC_H\r
-#define MU_PARSER_TEMPLATE_MAGIC_H\r
-\r
-#include <cmath>\r
-#include "muParserError.h"\r
-\r
-\r
-namespace mu\r
-{\r
-  //-----------------------------------------------------------------------------------------------\r
-  //\r
-  // Compile time type detection\r
-  //\r
-  //-----------------------------------------------------------------------------------------------\r
-\r
-  /** \brief A class singling out integer types at compile time using \r
-             template meta programming.\r
-  */\r
-  template<typename T>\r
-  struct TypeInfo\r
-  {\r
-    static bool IsInteger() { return false; }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<char>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<short>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<int>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<long>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<unsigned char>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<unsigned short>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<unsigned int>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-  template<>\r
-  struct TypeInfo<unsigned long>\r
-  {\r
-    static bool IsInteger() { return true;  }\r
-  };\r
-\r
-\r
-  //-----------------------------------------------------------------------------------------------\r
-  //\r
-  // Standard math functions with dummy overload for integer types\r
-  //\r
-  //-----------------------------------------------------------------------------------------------\r
-\r
-  /** \brief A template class for providing wrappers for essential math functions.\r
-\r
-    This template is spezialized for several types in order to provide a unified interface\r
-    for parser internal math function calls regardless of the data type.\r
-  */\r
-  template<typename T>\r
-  struct MathImpl\r
-  {\r
-    static T Sin(T v)   { return sin(v);  }\r
-    static T Cos(T v)   { return cos(v);  }\r
-    static T Tan(T v)   { return tan(v);  }\r
-    static T ASin(T v)  { return asin(v); }\r
-    static T ACos(T v)  { return acos(v); }\r
-    static T ATan(T v)  { return atan(v); }\r
-    static T ATan2(T v1, T v2) { return atan2(v1, v2); }\r
-    static T Sinh(T v)  { return sinh(v); }\r
-    static T Cosh(T v)  { return cosh(v); }\r
-    static T Tanh(T v)  { return tanh(v); }\r
-    static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }\r
-    static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }\r
-    static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }\r
-    static T Log(T v)   { return log(v); } \r
-    static T Log2(T v)  { return log(v)/log((T)2); } // Logarithm base 2\r
-    static T Log10(T v) { return log10(v); }         // Logarithm base 10\r
-    static T Exp(T v)   { return exp(v);   }\r
-    static T Abs(T v)   { return (v>=0) ? v : -v; }\r
-    static T Sqrt(T v)  { return sqrt(v); }\r
-    static T Rint(T v)  { return floor(v + (T)0.5); }\r
-    static T Sign(T v)  { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); }\r
-    static T Pow(T v1, T v2) { return std::pow(v1, v2); }\r
-  };\r
-}\r
-\r
-#endif\r
diff --git a/bundled/muparser_v2_2_4/include/muParserTest.h b/bundled/muparser_v2_2_4/include/muParserTest.h
deleted file mode 100644 (file)
index c02b021..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_TEST_H\r
-#define MU_PARSER_TEST_H\r
-\r
-#include <string>\r
-#include <cstdlib>\r
-#include <numeric> // for accumulate\r
-#include "muParser.h"\r
-#include "muParserInt.h"\r
-\r
-/** \file\r
-    \brief This file contains the parser test class.\r
-*/\r
-\r
-namespace mu\r
-{\r
-  /** \brief Namespace for test cases. */\r
-  namespace Test\r
-  {\r
-    //------------------------------------------------------------------------------\r
-    /** \brief Test cases for unit testing.\r
-\r
-      (C) 2004-2011 Ingo Berg\r
-    */\r
-    class ParserTester // final\r
-    {\r
-    private:\r
-        static int c_iCount;\r
-\r
-        // Multiarg callbacks\r
-        static value_type f1of1(value_type v) { return v;};\r
-       \r
-        static value_type f1of2(value_type v, value_type  ) {return v;};\r
-        static value_type f2of2(value_type  , value_type v) {return v;};\r
-\r
-        static value_type f1of3(value_type v, value_type  , value_type  ) {return v;};\r
-        static value_type f2of3(value_type  , value_type v, value_type  ) {return v;};\r
-        static value_type f3of3(value_type  , value_type  , value_type v) {return v;};\r
-       \r
-        static value_type f1of4(value_type v, value_type,   value_type  , value_type  ) {return v;}\r
-        static value_type f2of4(value_type  , value_type v, value_type  , value_type  ) {return v;}\r
-        static value_type f3of4(value_type  , value_type,   value_type v, value_type  ) {return v;}\r
-        static value_type f4of4(value_type  , value_type,   value_type  , value_type v) {return v;}\r
-\r
-        static value_type f1of5(value_type v, value_type,   value_type  , value_type  , value_type  ) { return v; }\r
-        static value_type f2of5(value_type  , value_type v, value_type  , value_type  , value_type  ) { return v; }\r
-        static value_type f3of5(value_type  , value_type,   value_type v, value_type  , value_type  ) { return v; }\r
-        static value_type f4of5(value_type  , value_type,   value_type  , value_type v, value_type  ) { return v; }\r
-        static value_type f5of5(value_type  , value_type,   value_type  , value_type  , value_type v) { return v; }\r
-\r
-        static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }\r
-           static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }\r
-\r
-        static value_type plus2(value_type v1) { return v1+2; }\r
-        static value_type times3(value_type v1) { return v1*3; }\r
-        static value_type sqr(value_type v1) { return v1*v1; }\r
-        static value_type sign(value_type v) { return -v; }\r
-        static value_type add(value_type v1, value_type v2) { return v1+v2; }\r
-        static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }\r
-        \r
-\r
-        static value_type FirstArg(const value_type* a_afArg, int a_iArgc)\r
-        {\r
-          if (!a_iArgc)        \r
-            throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") );\r
-\r
-          return  a_afArg[0];\r
-        }\r
-\r
-        static value_type LastArg(const value_type* a_afArg, int a_iArgc)\r
-        {\r
-          if (!a_iArgc)        \r
-            throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") );\r
-\r
-          return  a_afArg[a_iArgc-1];\r
-        }\r
-\r
-        static value_type Sum(const value_type* a_afArg, int a_iArgc)\r
-        { \r
-          if (!a_iArgc)        \r
-            throw mu::Parser::exception_type( _T("too few arguments for function sum.") );\r
-\r
-          value_type fRes=0;\r
-          for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
-          return fRes;\r
-        }\r
-\r
-        static value_type Rnd(value_type v)\r
-        {\r
-          return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));\r
-        }\r
-\r
-        static value_type RndWithString(const char_type*)\r
-        {\r
-          return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );\r
-        }\r
-\r
-        static value_type Ping()\r
-        { \r
-          return 10; \r
-        }\r
-\r
-        static value_type ValueOf(const char_type*)      \r
-        { \r
-          return 123; \r
-        }\r
-\r
-        static value_type StrFun1(const char_type* v1)                               \r
-        { \r
-          int val(0);\r
-          stringstream_type(v1) >> val;\r
-          return (value_type)val;\r
-        }\r
-\r
-        static value_type StrFun2(const char_type* v1, value_type v2)                \r
-        { \r
-          int val(0);\r
-          stringstream_type(v1) >> val;\r
-          return (value_type)(val + v2);\r
-        }\r
-        \r
-        static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) \r
-        { \r
-          int val(0);\r
-          stringstream_type(v1) >> val;\r
-          return val + v2 + v3;\r
-        }\r
-\r
-        static value_type StrToFloat(const char_type* a_szMsg)\r
-        {\r
-          value_type val(0);\r
-          stringstream_type(a_szMsg) >> val;\r
-          return val;\r
-        }\r
-\r
-        // postfix operator callback\r
-        static value_type Mega(value_type a_fVal)  { return a_fVal * (value_type)1e6; }\r
-        static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; }\r
-        static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }\r
-\r
-        // Custom value recognition\r
-        static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal);\r
-\r
-        int TestNames();\r
-        int TestSyntax();\r
-        int TestMultiArg();\r
-        int TestPostFix();\r
-        int TestExpression();\r
-        int TestInfixOprt();\r
-        int TestBinOprt();\r
-        int TestVarConst();\r
-        int TestInterface();\r
-        int TestException();\r
-        int TestStrArg();\r
-        int TestIfThenElse();\r
-        int TestBulkMode();\r
-\r
-        void Abort() const;\r
-\r
-    public:\r
-        typedef int (ParserTester::*testfun_type)();\r
-\r
-             ParserTester();\r
-             void Run();\r
-\r
-    private:\r
-        std::vector<testfun_type> m_vTestFun;\r
-             void AddTest(testfun_type a_pFun);\r
-\r
-        // Test Double Parser\r
-        int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);\r
-        int EqnTestWithVarChange(const string_type& a_str, \r
-                                 double a_fRes1, \r
-                                 double a_fVar1, \r
-                                 double a_fRes2, \r
-                                 double a_fVar2);\r
-        int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);\r
-\r
-        // Test Int Parser\r
-        int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);\r
-\r
-        // Test Bulkmode\r
-        int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass);\r
-    };\r
-  } // namespace Test\r
-} // namespace mu\r
-\r
-#endif\r
-\r
-\r
diff --git a/bundled/muparser_v2_2_4/include/muParserToken.h b/bundled/muparser_v2_2_4/include/muParserToken.h
deleted file mode 100644 (file)
index 0cca469..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_TOKEN_H\r
-#define MU_PARSER_TOKEN_H\r
-\r
-#include <cassert>\r
-#include <string>\r
-#include <stack>\r
-#include <vector>\r
-#include <memory>\r
-\r
-#include "muParserError.h"\r
-#include "muParserCallback.h"\r
-\r
-/** \file\r
-    \brief This file contains the parser token definition.\r
-*/\r
-\r
-namespace mu\r
-{\r
-  /** \brief Encapsulation of the data for a single formula token. \r
-\r
-    Formula token implementation. Part of the Math Parser Package.\r
-    Formula tokens can be either one of the following:\r
-    <ul>\r
-      <li>value</li>\r
-      <li>variable</li>\r
-      <li>function with numerical arguments</li>\r
-      <li>functions with a string as argument</li>\r
-      <li>prefix operators</li>\r
-      <li>infix operators</li>\r
-           <li>binary operator</li>\r
-    </ul>\r
-\r
-   \author (C) 2004-2013 Ingo Berg \r
-  */\r
-  template<typename TBase, typename TString>\r
-  class ParserToken\r
-  {\r
-  private:\r
-\r
-      ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.\r
-      ETypeCode m_iType;\r
-      void  *m_pTok;      ///< Stores Token pointer; not applicable for all tokens\r
-      int  m_iIdx;        ///< An otional index to an external buffer storing the token data\r
-      TString m_strTok;   ///< Token string\r
-      TString m_strVal;   ///< Value for string variables\r
-      value_type m_fVal;  ///< the value \r
-      std::unique_ptr<ParserCallback> m_pCallback;\r
-\r
-  public:\r
-\r
-      //---------------------------------------------------------------------------\r
-      /** \brief Constructor (default).\r
-        \r
-          Sets token to an neutral state of type cmUNKNOWN.\r
-          \throw nothrow\r
-          \sa ECmdCode\r
-      */\r
-      ParserToken()\r
-        :m_iCode(cmUNKNOWN)\r
-        ,m_iType(tpVOID)\r
-        ,m_pTok(0)\r
-        ,m_iIdx(-1)\r
-        ,m_strTok()\r
-               ,m_strVal()\r
-               ,m_fVal(0)\r
-        ,m_pCallback()\r
-      {}\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Create token from another one.\r
-      \r
-          Implemented by calling Assign(...)\r
-          \throw nothrow\r
-          \post m_iType==cmUNKNOWN\r
-          \sa #Assign\r
-      */\r
-      ParserToken(const ParserToken &a_Tok)\r
-      {\r
-        Assign(a_Tok);\r
-      }\r
-      \r
-      //------------------------------------------------------------------------------\r
-      /** \brief Assignement operator. \r
-      \r
-          Copy token state from another token and return this.\r
-          Implemented by calling Assign(...).\r
-          \throw nothrow\r
-      */\r
-      ParserToken& operator=(const ParserToken &a_Tok)\r
-      {\r
-        Assign(a_Tok);\r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Copy token information from argument.\r
-      \r
-          \throw nothrow\r
-      */\r
-      void Assign(const ParserToken &a_Tok)\r
-      {\r
-        m_iCode = a_Tok.m_iCode;\r
-        m_pTok = a_Tok.m_pTok;\r
-        m_strTok = a_Tok.m_strTok;\r
-        m_iIdx = a_Tok.m_iIdx;\r
-        m_strVal = a_Tok.m_strVal;\r
-        m_iType = a_Tok.m_iType;\r
-        m_fVal = a_Tok.m_fVal;\r
-        // create new callback object if a_Tok has one \r
-        m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Assign a token type. \r
-\r
-        Token may not be of type value, variable or function. Those have seperate set functions. \r
-\r
-        \pre [assert] a_iType!=cmVAR\r
-        \pre [assert] a_iType!=cmVAL\r
-        \pre [assert] a_iType!=cmFUNC\r
-        \post m_fVal = 0\r
-        \post m_pTok = 0\r
-      */\r
-      ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())\r
-      {\r
-        // The following types cant be set this way, they have special Set functions\r
-        assert(a_iType!=cmVAR);\r
-        assert(a_iType!=cmVAL);\r
-        assert(a_iType!=cmFUNC);\r
-\r
-        m_iCode = a_iType;\r
-        m_iType = tpVOID;\r
-        m_pTok = 0;\r
-        m_strTok = a_strTok;\r
-        m_iIdx = -1;\r
-\r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Set Callback type. */\r
-      ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)\r
-      {\r
-        assert(a_pCallback.GetAddr());\r
-\r
-        m_iCode = a_pCallback.GetCode();\r
-        m_iType = tpVOID;\r
-        m_strTok = a_sTok;\r
-        m_pCallback.reset(new ParserCallback(a_pCallback));\r
-\r
-        m_pTok = 0;\r
-        m_iIdx = -1;\r
-        \r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Make this token a value token. \r
-      \r
-          Member variables not necessary for value tokens will be invalidated.\r
-          \throw nothrow\r
-      */\r
-      ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())\r
-      {\r
-        m_iCode = cmVAL;\r
-        m_iType = tpDBL;\r
-        m_fVal = a_fVal;\r
-        m_strTok = a_strTok;\r
-        m_iIdx = -1;\r
-        \r
-        m_pTok = 0;\r
-        m_pCallback.reset(0);\r
-\r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief make this token a variable token. \r
-      \r
-          Member variables not necessary for variable tokens will be invalidated.\r
-          \throw nothrow\r
-      */\r
-      ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)\r
-      {\r
-        m_iCode = cmVAR;\r
-        m_iType = tpDBL;\r
-        m_strTok = a_strTok;\r
-        m_iIdx = -1;\r
-        m_pTok = (void*)a_pVar;\r
-        m_pCallback.reset(0);\r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Make this token a variable token. \r
-      \r
-          Member variables not necessary for variable tokens will be invalidated.\r
-          \throw nothrow\r
-      */\r
-      ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)\r
-      {\r
-        m_iCode = cmSTRING;\r
-        m_iType = tpSTR;\r
-        m_strTok = a_strTok;\r
-        m_iIdx = static_cast<int>(a_iSize);\r
-\r
-        m_pTok = 0;\r
-        m_pCallback.reset(0);\r
-        return *this;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Set an index associated with the token related data. \r
-      \r
-          In cmSTRFUNC - This is the index to a string table in the main parser.\r
-          \param a_iIdx The index the string function result will take in the bytecode parser.\r
-          \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING\r
-      */\r
-      void SetIdx(int a_iIdx)\r
-      {\r
-        if (m_iCode!=cmSTRING || a_iIdx<0)\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-        \r
-        m_iIdx = a_iIdx;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Return Index associated with the token related data. \r
-      \r
-          In cmSTRFUNC - This is the index to a string table in the main parser.\r
-\r
-          \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING\r
-          \return The index the result will take in the Bytecode calculatin array (#m_iIdx).\r
-      */\r
-      int GetIdx() const\r
-      {\r
-        if (m_iIdx<0 || m_iCode!=cmSTRING )\r
-          throw ParserError(ecINTERNAL_ERROR);\r
-\r
-        return m_iIdx;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Return the token type.\r
-      \r
-          \return #m_iType\r
-          \throw nothrow\r
-      */\r
-      ECmdCode GetCode() const\r
-      {\r
-        if (m_pCallback.get())\r
-        {\r
-          return m_pCallback->GetCode();\r
-        }\r
-        else\r
-        {\r
-          return m_iCode;\r
-        }\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      ETypeCode GetType() const\r
-      {\r
-        if (m_pCallback.get())\r
-        {\r
-          return m_pCallback->GetType();\r
-        }\r
-        else\r
-        {\r
-          return m_iType;\r
-        }\r
-      }\r
-      \r
-      //------------------------------------------------------------------------------\r
-      int GetPri() const\r
-      {\r
-        if ( !m_pCallback.get())\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-            \r
-        if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-\r
-        return m_pCallback->GetPri();\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      EOprtAssociativity GetAssociativity() const\r
-      {\r
-        if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-\r
-        return m_pCallback->GetAssociativity();\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Return the address of the callback function assoziated with\r
-                 function and operator tokens.\r
-\r
-          \return The pointer stored in #m_pTok.\r
-          \throw exception_type if token type is non of:\r
-                 <ul>\r
-                   <li>cmFUNC</li>\r
-                   <li>cmSTRFUNC</li>\r
-                   <li>cmPOSTOP</li>\r
-                   <li>cmINFIXOP</li>\r
-                   <li>cmOPRT_BIN</li>\r
-                 </ul>\r
-          \sa ECmdCode\r
-      */\r
-      generic_fun_type GetFuncAddr() const\r
-      {\r
-        return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \biref Get value of the token.\r
-        \r
-          Only applicable to variable and value tokens.\r
-          \throw exception_type if token is no value/variable token.\r
-      */\r
-      TBase GetVal() const\r
-      {\r
-        switch (m_iCode)\r
-        {\r
-          case cmVAL:  return m_fVal;\r
-          case cmVAR:  return *((TBase*)m_pTok);\r
-          default:     throw ParserError(ecVAL_EXPECTED);\r
-        }\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Get address of a variable token.\r
-\r
-        Valid only if m_iType==CmdVar.\r
-        \throw exception_type if token is no variable token.\r
-      */\r
-      TBase* GetVar() const\r
-      {\r
-        if (m_iCode!=cmVAR)\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-\r
-        return (TBase*)m_pTok;\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Return the number of function arguments. \r
-\r
-        Valid only if m_iType==CmdFUNC.\r
-      */\r
-      int GetArgCount() const\r
-      {\r
-        assert(m_pCallback.get());\r
-\r
-        if (!m_pCallback->GetAddr())\r
-               throw ParserError(ecINTERNAL_ERROR);\r
-\r
-        return m_pCallback->GetArgc();\r
-      }\r
-\r
-      //------------------------------------------------------------------------------\r
-      /** \brief Return the token identifier. \r
-          \r
-          If #m_iType is cmSTRING the token identifier is the value of the string argument\r
-          for a string function.\r
-          \return #m_strTok\r
-          \throw nothrow\r
-          \sa m_strTok\r
-      */\r
-      const TString& GetAsString() const\r
-      {\r
-        return m_strTok;\r
-      }\r
-  };\r
-} // namespace mu\r
-\r
-#endif\r
diff --git a/bundled/muparser_v2_2_4/include/muParserTokenReader.h b/bundled/muparser_v2_2_4/include/muParserTokenReader.h
deleted file mode 100644 (file)
index 9d96225..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#ifndef MU_PARSER_TOKEN_READER_H\r
-#define MU_PARSER_TOKEN_READER_H\r
-\r
-#include <cassert>\r
-#include <cstdio>\r
-#include <cstring>\r
-#include <list>\r
-#include <map>\r
-#include <memory>\r
-#include <stack>\r
-#include <string>\r
-\r
-#include "muParserDef.h"\r
-#include "muParserToken.h"\r
-\r
-/** \file\r
-    \brief This file contains the parser token reader definition.\r
-*/\r
-\r
-\r
-namespace mu\r
-{\r
-  // Forward declaration\r
-  class ParserBase;\r
-\r
-  /** \brief Token reader for the ParserBase class.\r
-\r
-  */\r
-  class ParserTokenReader \r
-  {\r
-  private:\r
-\r
-      typedef ParserToken<value_type, string_type> token_type;\r
-\r
-  public:\r
-\r
-      ParserTokenReader(ParserBase *a_pParent);\r
-      ParserTokenReader* Clone(ParserBase *a_pParent) const;\r
-\r
-      void AddValIdent(identfun_type a_pCallback);\r
-      void SetVarCreator(facfun_type a_pFactory, void *pUserData);\r
-      void SetFormula(const string_type &a_strFormula);\r
-      void SetArgSep(char_type cArgSep);\r
-\r
-      int GetPos() const;\r
-      const string_type& GetExpr() const;\r
-      varmap_type& GetUsedVar();\r
-      char_type GetArgSep() const;\r
-\r
-      void IgnoreUndefVar(bool bIgnore);\r
-      void ReInit();\r
-      token_type ReadNextToken();\r
-\r
-  private:\r
-\r
-      /** \brief Syntax codes. \r
-       \r
-               The syntax codes control the syntax check done during the first time parsing of \r
-          the expression string. They are flags that indicate which tokens are allowed next\r
-          if certain tokens are identified.\r
-         */\r
-      enum ESynCodes\r
-      {\r
-        noBO      = 1 << 0,  ///< to avoid i.e. "cos(7)(" \r
-        noBC      = 1 << 1,  ///< to avoid i.e. "sin)" or "()"\r
-        noVAL     = 1 << 2,  ///< to avoid i.e. "tan 2" or "sin(8)3.14"\r
-        noVAR     = 1 << 3,  ///< to avoid i.e. "sin a" or "sin(8)a"\r
-        noARG_SEP = 1 << 4,  ///< to avoid i.e. ",," or "+," ...\r
-        noFUN     = 1 << 5,  ///< to avoid i.e. "sqrt cos" or "(1)sin" \r
-        noOPT     = 1 << 6,  ///< to avoid i.e. "(+)"\r
-        noPOSTOP  = 1 << 7,  ///< to avoid i.e. "(5!!)" "sin!"\r
-             noINFIXOP = 1 << 8,  ///< to avoid i.e. "++4" "!!4"\r
-        noEND     = 1 << 9,  ///< to avoid unexpected end of formula\r
-        noSTR     = 1 << 10, ///< to block numeric arguments on string functions\r
-        noASSIGN  = 1 << 11, ///< to block assignement to constant i.e. "4=7"\r
-        noIF      = 1 << 12,\r
-        noELSE    = 1 << 13,\r
-        sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,\r
-        noANY     = ~0       ///< All of he above flags set\r
-      };       \r
-\r
-      ParserTokenReader(const ParserTokenReader &a_Reader);\r
-      ParserTokenReader& operator=(const ParserTokenReader &a_Reader);\r
-      void Assign(const ParserTokenReader &a_Reader);\r
-\r
-      void SetParent(ParserBase *a_pParent);\r
-      int ExtractToken(const char_type *a_szCharSet, \r
-                       string_type &a_strTok, \r
-                       int a_iPos) const;\r
-      int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;\r
-\r
-      bool IsBuiltIn(token_type &a_Tok);\r
-      bool IsArgSep(token_type &a_Tok);\r
-      bool IsEOF(token_type &a_Tok);\r
-      bool IsInfixOpTok(token_type &a_Tok);\r
-      bool IsFunTok(token_type &a_Tok);\r
-      bool IsPostOpTok(token_type &a_Tok);\r
-      bool IsOprt(token_type &a_Tok);\r
-      bool IsValTok(token_type &a_Tok);\r
-      bool IsVarTok(token_type &a_Tok);\r
-      bool IsStrVarTok(token_type &a_Tok);\r
-      bool IsUndefVarTok(token_type &a_Tok);\r
-      bool IsString(token_type &a_Tok);\r
-      void Error(EErrorCodes a_iErrc, \r
-                 int a_iPos = -1, \r
-                 const string_type &a_sTok = string_type() ) const;\r
-\r
-      token_type& SaveBeforeReturn(const token_type &tok);\r
-\r
-      ParserBase *m_pParser;\r
-      string_type m_strFormula;\r
-      int  m_iPos;\r
-      int  m_iSynFlags;\r
-      bool m_bIgnoreUndefVar;\r
-\r
-      const funmap_type *m_pFunDef;\r
-      const funmap_type *m_pPostOprtDef;\r
-      const funmap_type *m_pInfixOprtDef;\r
-      const funmap_type *m_pOprtDef;\r
-      const valmap_type *m_pConstDef;\r
-      const strmap_type *m_pStrVarDef;\r
-      varmap_type *m_pVarDef;  ///< The only non const pointer to parser internals\r
-      facfun_type m_pFactory;\r
-      void *m_pFactoryData;\r
-      std::list<identfun_type> m_vIdentFun; ///< Value token identification function\r
-      varmap_type m_UsedVar;\r
-      value_type m_fZero;      ///< Dummy value of zero, referenced by undefined variables\r
-      int m_iBrackets;\r
-      token_type m_lastTok;\r
-      char_type m_cArgSep;     ///< The character used for separating function arguments\r
-  };\r
-} // namespace mu\r
-\r
-#endif\r
-\r
-\r
diff --git a/bundled/muparser_v2_2_4/src/muParser.cpp b/bundled/muparser_v2_2_4/src/muParser.cpp
deleted file mode 100644 (file)
index eaa8449..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/* \r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-\r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#include "muParser.h"\r
-#include "muParserTemplateMagic.h"\r
-\r
-//--- Standard includes ------------------------------------------------------------------------\r
-#include <cmath>\r
-#include <algorithm>\r
-#include <numeric>\r
-\r
-/** \brief Pi (what else?). */\r
-#define PARSER_CONST_PI  3.141592653589793238462643\r
-\r
-/** \brief The eulerian number. */\r
-#define PARSER_CONST_E   2.718281828459045235360287\r
-\r
-using namespace std;\r
-\r
-/** \file\r
-    \brief Implementation of the standard floating point parser.\r
-*/\r
-\r
-\r
-\r
-/** \brief Namespace for mathematical applications. */\r
-namespace mu\r
-{\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  // Trigonometric function\r
-  value_type Parser::Sin(value_type v)   { return MathImpl<value_type>::Sin(v);  }\r
-  value_type Parser::Cos(value_type v)   { return MathImpl<value_type>::Cos(v);  }\r
-  value_type Parser::Tan(value_type v)   { return MathImpl<value_type>::Tan(v);  }\r
-  value_type Parser::ASin(value_type v)  { return MathImpl<value_type>::ASin(v); }\r
-  value_type Parser::ACos(value_type v)  { return MathImpl<value_type>::ACos(v); }\r
-  value_type Parser::ATan(value_type v)  { return MathImpl<value_type>::ATan(v); }\r
-  value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }\r
-  value_type Parser::Sinh(value_type v)  { return MathImpl<value_type>::Sinh(v); }\r
-  value_type Parser::Cosh(value_type v)  { return MathImpl<value_type>::Cosh(v); }\r
-  value_type Parser::Tanh(value_type v)  { return MathImpl<value_type>::Tanh(v); }\r
-  value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }\r
-  value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }\r
-  value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }\r
-\r
-  //---------------------------------------------------------------------------\r
-  // Logarithm functions\r
-\r
-  // Logarithm base 2\r
-  value_type Parser::Log2(value_type v)  \r
-  { \r
-    #ifdef MUP_MATH_EXCEPTIONS\r
-        if (v<=0)\r
-          throw ParserError(ecDOMAIN_ERROR, _T("Log2"));\r
-    #endif\r
-\r
-    return MathImpl<value_type>::Log2(v);  \r
-  }  \r
-\r
-  // Logarithm base 10\r
-  value_type Parser::Log10(value_type v) \r
-  { \r
-    #ifdef MUP_MATH_EXCEPTIONS\r
-        if (v<=0)\r
-          throw ParserError(ecDOMAIN_ERROR, _T("Log10"));\r
-    #endif\r
-\r
-    return MathImpl<value_type>::Log10(v); \r
-  } \r
-\r
-// Logarithm base e (natural logarithm)\r
-  value_type Parser::Ln(value_type v)    \r
-  { \r
-    #ifdef MUP_MATH_EXCEPTIONS\r
-        if (v<=0)\r
-          throw ParserError(ecDOMAIN_ERROR, _T("Ln"));\r
-    #endif\r
-\r
-    return MathImpl<value_type>::Log(v);   \r
-  } \r
-\r
-  //---------------------------------------------------------------------------\r
-  //  misc\r
-  value_type Parser::Exp(value_type v)  { return MathImpl<value_type>::Exp(v);  }\r
-  value_type Parser::Abs(value_type v)  { return MathImpl<value_type>::Abs(v);  }\r
-  value_type Parser::Sqrt(value_type v) \r
-  { \r
-    #ifdef MUP_MATH_EXCEPTIONS\r
-        if (v<0)\r
-          throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));\r
-    #endif\r
-\r
-    return MathImpl<value_type>::Sqrt(v); \r
-  }\r
-  value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }\r
-  value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for the unary minus operator.\r
-      \param v The value to negate\r
-      \return -v\r
-  */\r
-  value_type Parser::UnaryMinus(value_type v) \r
-  { \r
-    return -v; \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for the unary minus operator.\r
-      \param v The value to negate\r
-      \return -v\r
-  */\r
-  value_type Parser::UnaryPlus(value_type v) \r
-  { \r
-    return v; \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for adding multiple values. \r
-      \param [in] a_afArg Vector with the function arguments\r
-      \param [in] a_iArgc The size of a_afArg\r
-  */\r
-  value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)\r
-  { \r
-    if (!a_iArgc)      \r
-      throw exception_type(_T("too few arguments for function sum."));\r
-\r
-    value_type fRes=0;\r
-    for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
-    return fRes;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for averaging multiple values. \r
-      \param [in] a_afArg Vector with the function arguments\r
-      \param [in] a_iArgc The size of a_afArg\r
-  */\r
-  value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)\r
-  { \r
-    if (!a_iArgc)      \r
-      throw exception_type(_T("too few arguments for function sum."));\r
-\r
-    value_type fRes=0;\r
-    for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
-    return fRes/(value_type)a_iArgc;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for determining the minimum value out of a vector. \r
-      \param [in] a_afArg Vector with the function arguments\r
-      \param [in] a_iArgc The size of a_afArg\r
-  */\r
-  value_type Parser::Min(const value_type *a_afArg, int a_iArgc)\r
-  { \r
-    if (!a_iArgc)      \r
-      throw exception_type(_T("too few arguments for function min."));\r
-\r
-    value_type fRes=a_afArg[0];\r
-    for (int i=0; i<a_iArgc; ++i) \r
-      fRes = std::min(fRes, a_afArg[i]);\r
-\r
-    return fRes;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Callback for determining the maximum value out of a vector. \r
-      \param [in] a_afArg Vector with the function arguments\r
-      \param [in] a_iArgc The size of a_afArg\r
-  */\r
-  value_type Parser::Max(const value_type *a_afArg, int a_iArgc)\r
-  { \r
-    if (!a_iArgc)      \r
-      throw exception_type(_T("too few arguments for function min."));\r
-\r
-    value_type fRes=a_afArg[0];\r
-    for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);\r
-\r
-    return fRes;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Default value recognition callback. \r
-      \param [in] a_szExpr Pointer to the expression\r
-      \param [in, out] a_iPos Pointer to an index storing the current position within the expression\r
-      \param [out] a_fVal Pointer where the value should be stored in case one is found.\r
-      \return 1 if a value was found 0 otherwise.\r
-  */\r
-  int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)\r
-  {\r
-    value_type fVal(0);\r
-\r
-    stringstream_type stream(a_szExpr);\r
-    stream.seekg(0);        // todo:  check if this really is necessary\r
-    stream.imbue(Parser::s_locale);\r
-    stream >> fVal;\r
-    stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading\r
-\r
-    if (iEnd==(stringstream_type::pos_type)-1)\r
-      return 0;\r
-\r
-    *a_iPos += (int)iEnd;\r
-    *a_fVal = fVal;\r
-    return 1;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Constructor. \r
-\r
-    Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
-  */\r
-  Parser::Parser()\r
-    :ParserBase()\r
-  {\r
-    AddValIdent(IsVal);\r
-\r
-    InitCharSets();\r
-    InitFun();\r
-    InitConst();\r
-    InitOprt();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define the character sets. \r
-      \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars\r
-    \r
-    This function is used for initializing the default character sets that define\r
-    the characters to be useable in function and variable names and operators.\r
-  */\r
-  void Parser::InitCharSets()\r
-  {\r
-    DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
-    DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );\r
-    DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize the default functions. */\r
-  void Parser::InitFun()\r
-  {\r
-    if (mu::TypeInfo<mu::value_type>::IsInteger())\r
-    {\r
-      // When setting MUP_BASETYPE to an integer type\r
-      // Place functions for dealing with integer values here\r
-      // ...\r
-      // ...\r
-      // ...\r
-    }\r
-    else\r
-    {\r
-      // trigonometric functions\r
-      DefineFun(_T("sin"), Sin);\r
-      DefineFun(_T("cos"), Cos);\r
-      DefineFun(_T("tan"), Tan);\r
-      // arcus functions\r
-      DefineFun(_T("asin"), ASin);\r
-      DefineFun(_T("acos"), ACos);\r
-      DefineFun(_T("atan"), ATan);\r
-      DefineFun(_T("atan2"), ATan2);\r
-      // hyperbolic functions\r
-      DefineFun(_T("sinh"), Sinh);\r
-      DefineFun(_T("cosh"), Cosh);\r
-      DefineFun(_T("tanh"), Tanh);\r
-      // arcus hyperbolic functions\r
-      DefineFun(_T("asinh"), ASinh);\r
-      DefineFun(_T("acosh"), ACosh);\r
-      DefineFun(_T("atanh"), ATanh);\r
-      // Logarithm functions\r
-      DefineFun(_T("log2"), Log2);\r
-      DefineFun(_T("log10"), Log10);\r
-      DefineFun(_T("log"), Ln);\r
-      DefineFun(_T("ln"), Ln);\r
-      // misc\r
-      DefineFun(_T("exp"), Exp);\r
-      DefineFun(_T("sqrt"), Sqrt);\r
-      DefineFun(_T("sign"), Sign);\r
-      DefineFun(_T("rint"), Rint);\r
-      DefineFun(_T("abs"), Abs);\r
-      // Functions with variable number of arguments\r
-      DefineFun(_T("sum"), Sum);\r
-      DefineFun(_T("avg"), Avg);\r
-      DefineFun(_T("min"), Min);\r
-      DefineFun(_T("max"), Max);\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize constants.\r
-  \r
-    By default the parser recognizes two constants. Pi ("pi") and the eulerian\r
-    number ("_e").\r
-  */\r
-  void Parser::InitConst()\r
-  {\r
-    DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);\r
-    DefineConst(_T("_e"), (value_type)PARSER_CONST_E);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize operators. \r
-  \r
-    By default only the unary minus operator is added.\r
-  */\r
-  void Parser::InitOprt()\r
-  {\r
-    DefineInfixOprt(_T("-"), UnaryMinus);\r
-    DefineInfixOprt(_T("+"), UnaryPlus);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
-  {\r
-    // this is just sample code to illustrate modifying variable names on the fly.\r
-    // I'm not sure anyone really needs such a feature...\r
-    /*\r
-\r
-\r
-    string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);\r
-    string sRepl = std::string("_") + sVar + "_";\r
-  \r
-    int nOrigVarEnd = nEnd;\r
-    cout << "variable detected!\n";\r
-    cout << "  Expr: " << *pExpr << "\n";\r
-    cout << "  Start: " << nStart << "\n";\r
-    cout << "  End: " << nEnd << "\n";\r
-    cout << "  Var: \"" << sVar << "\"\n";\r
-    cout << "  Repl: \"" << sRepl << "\"\n";\r
-    nEnd = nStart + sRepl.length();\r
-    cout << "  End: " << nEnd << "\n";\r
-    pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);\r
-    cout << "  New expr: " << *pExpr << "\n";\r
-    */\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Numerically differentiate with regard to a variable. \r
-      \param [in] a_Var Pointer to the differentiation variable.\r
-      \param [in] a_fPos Position at which the differentiation should take place.\r
-      \param [in] a_fEpsilon Epsilon used for the numerical differentiation.\r
-\r
-    Numerical differentiation uses a 5 point operator yielding a 4th order \r
-    formula. The default value for epsilon is 0.00074 which is\r
-    numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser\r
-    forum:\r
-\r
-    http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843\r
-  */\r
-  value_type Parser::Diff(value_type *a_Var, \r
-                          value_type  a_fPos, \r
-                          value_type  a_fEpsilon) const\r
-  {\r
-    value_type fRes(0), \r
-               fBuf(*a_Var),\r
-               f[4] = {0,0,0,0},\r
-               fEpsilon(a_fEpsilon);\r
-\r
-    // Backwards compatible calculation of epsilon inc case the user doesnt provide\r
-    // his own epsilon\r
-    if (fEpsilon==0)\r
-      fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;\r
-\r
-    *a_Var = a_fPos+2 * fEpsilon;  f[0] = Eval();\r
-    *a_Var = a_fPos+1 * fEpsilon;  f[1] = Eval();\r
-    *a_Var = a_fPos-1 * fEpsilon;  f[2] = Eval();\r
-    *a_Var = a_fPos-2 * fEpsilon;  f[3] = Eval();\r
-    *a_Var = fBuf; // restore variable\r
-\r
-    fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);\r
-    return fRes;\r
-  }\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserBase.cpp b/bundled/muparser_v2_2_4/src/muParserBase.cpp
deleted file mode 100644 (file)
index 09b0230..0000000
+++ /dev/null
@@ -1,1780 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#include "muParserBase.h"\r
-#include "muParserTemplateMagic.h"\r
-\r
-//--- Standard includes ------------------------------------------------------------------------\r
-#include <cassert>\r
-#include <algorithm>\r
-#include <cmath>\r
-#include <memory>\r
-#include <vector>\r
-#include <deque>\r
-#include <sstream>\r
-#include <locale>\r
-\r
-#ifdef MUP_USE_OPENMP\r
-  #include <omp.h>\r
-#endif\r
-\r
-using namespace std;\r
-\r
-/** \file\r
-    \brief This file contains the basic implementation of the muparser engine.\r
-*/\r
-\r
-namespace mu\r
-{\r
-  std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));\r
-\r
-  bool ParserBase::g_DbgDumpCmdCode = false;\r
-  bool ParserBase::g_DbgDumpStack = false;\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Identifiers for built in binary operators. \r
-\r
-      When defining custom binary operators with #AddOprt(...) make sure not to choose \r
-      names conflicting with these definitions. \r
-  */\r
-  const char_type* ParserBase::c_DefaultOprt[] = \r
-  { \r
-    _T("<="), _T(">="),  _T("!="), \r
-    _T("=="), _T("<"),   _T(">"), \r
-    _T("+"),  _T("-"),   _T("*"), \r
-    _T("/"),  _T("^"),   _T("&&"), \r
-    _T("||"), _T("="),   _T("("),  \r
-    _T(")"),   _T("?"),  _T(":"), 0 \r
-  };\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Constructor.\r
-      \param a_szFormula the formula to interpret.\r
-      \throw ParserException if a_szFormula is null.\r
-  */\r
-  ParserBase::ParserBase()\r
-    :m_pParseFormula(&ParserBase::ParseString)\r
-    ,m_vRPN()\r
-    ,m_vStringBuf()\r
-    ,m_pTokenReader()\r
-    ,m_FunDef()\r
-    ,m_PostOprtDef()\r
-    ,m_InfixOprtDef()\r
-    ,m_OprtDef()\r
-    ,m_ConstDef()\r
-    ,m_StrVarDef()\r
-    ,m_VarDef()\r
-    ,m_bBuiltInOp(true)\r
-    ,m_sNameChars()\r
-    ,m_sOprtChars()\r
-    ,m_sInfixOprtChars()\r
-    ,m_nIfElseCounter(0)\r
-    ,m_vStackBuffer()\r
-    ,m_nFinalResultIdx(0)\r
-  {\r
-    InitTokenReader();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy constructor. \r
-\r
-    Tha parser can be safely copy constructed but the bytecode is reset during\r
-    copy construction.\r
-  */\r
-  ParserBase::ParserBase(const ParserBase &a_Parser)\r
-    :m_pParseFormula(&ParserBase::ParseString)\r
-    ,m_vRPN()\r
-    ,m_vStringBuf()\r
-    ,m_pTokenReader()\r
-    ,m_FunDef()\r
-    ,m_PostOprtDef()\r
-    ,m_InfixOprtDef()\r
-    ,m_OprtDef()\r
-    ,m_ConstDef()\r
-    ,m_StrVarDef()\r
-    ,m_VarDef()\r
-    ,m_bBuiltInOp(true)\r
-    ,m_sNameChars()\r
-    ,m_sOprtChars()\r
-    ,m_sInfixOprtChars()\r
-    ,m_nIfElseCounter(0)\r
-  {\r
-    m_pTokenReader.reset(new token_reader_type(this));\r
-    Assign(a_Parser);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserBase::~ParserBase()\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Assignement operator. \r
-\r
-    Implemented by calling Assign(a_Parser). Self assignement is suppressed.\r
-    \param a_Parser Object to copy to this.\r
-    \return *this\r
-    \throw nothrow\r
-  */\r
-  ParserBase& ParserBase::operator=(const ParserBase &a_Parser)\r
-  {\r
-    Assign(a_Parser);\r
-    return *this;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy state of a parser object to this. \r
-\r
-    Clears Variables and Functions of this parser.\r
-    Copies the states of all internal variables.\r
-    Resets parse function to string parse mode.\r
-\r
-    \param a_Parser the source object.\r
-  */\r
-  void ParserBase::Assign(const ParserBase &a_Parser)\r
-  {\r
-    if (&a_Parser==this)\r
-      return;\r
-\r
-    // Don't copy bytecode instead cause the parser to create new bytecode\r
-    // by resetting the parse function.\r
-    ReInit();\r
-\r
-    m_ConstDef        = a_Parser.m_ConstDef;         // Copy user define constants\r
-    m_VarDef          = a_Parser.m_VarDef;           // Copy user defined variables\r
-    m_bBuiltInOp      = a_Parser.m_bBuiltInOp;\r
-    m_vStringBuf      = a_Parser.m_vStringBuf;\r
-    m_vStackBuffer    = a_Parser.m_vStackBuffer;\r
-    m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;\r
-    m_StrVarDef       = a_Parser.m_StrVarDef;\r
-    m_vStringVarBuf   = a_Parser.m_vStringVarBuf;\r
-    m_nIfElseCounter  = a_Parser.m_nIfElseCounter;\r
-    m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));\r
-\r
-    // Copy function and operator callbacks\r
-    m_FunDef = a_Parser.m_FunDef;             // Copy function definitions\r
-    m_PostOprtDef = a_Parser.m_PostOprtDef;   // post value unary operators\r
-    m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation\r
-    m_OprtDef = a_Parser.m_OprtDef;           // binary operators\r
-\r
-    m_sNameChars = a_Parser.m_sNameChars;\r
-    m_sOprtChars = a_Parser.m_sOprtChars;\r
-    m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Set the decimal separator.\r
-      \param cDecSep Decimal separator as a character value.\r
-      \sa SetThousandsSep\r
-\r
-      By default muparser uses the "C" locale. The decimal separator of this\r
-      locale is overwritten by the one provided here.\r
-  */\r
-  void ParserBase::SetDecSep(char_type cDecSep)\r
-  {\r
-    char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();\r
-    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
-  }\r
-  \r
-  //---------------------------------------------------------------------------\r
-  /** \brief Sets the thousands operator. \r
-      \param cThousandsSep The thousands separator as a character\r
-      \sa SetDecSep\r
-\r
-      By default muparser uses the "C" locale. The thousands separator of this\r
-      locale is overwritten by the one provided here.\r
-  */\r
-  void ParserBase::SetThousandsSep(char_type cThousandsSep)\r
-  {\r
-    char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();\r
-    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Resets the locale. \r
-\r
-    The default locale used "." as decimal separator, no thousands separator and\r
-    "," as function argument separator.\r
-  */\r
-  void ParserBase::ResetLocale()\r
-  {\r
-    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));\r
-    SetArgSep(',');\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize the token reader. \r
-\r
-    Create new token reader object and submit pointers to function, operator,\r
-    constant and variable definitions.\r
-\r
-    \post m_pTokenReader.get()!=0\r
-    \throw nothrow\r
-  */\r
-  void ParserBase::InitTokenReader()\r
-  {\r
-    m_pTokenReader.reset(new token_reader_type(this));\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Reset parser to string parsing mode and clear internal buffers.\r
-\r
-      Clear bytecode, reset the token reader.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ReInit() const\r
-  {\r
-    m_pParseFormula = &ParserBase::ParseString;\r
-    m_vStringBuf.clear();\r
-    m_vRPN.clear();\r
-    m_pTokenReader->ReInit();\r
-    m_nIfElseCounter = 0;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Returns the version of muparser. \r
-      \param eInfo A flag indicating whether the full version info should be \r
-                   returned or not.\r
-\r
-    Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS\r
-    are returned only if eInfo==pviFULL.\r
-  */\r
-  string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const\r
-  {\r
-    stringstream_type ss;\r
-\r
-    ss << MUP_VERSION;\r
-\r
-    if (eInfo==pviFULL)\r
-    {\r
-      ss << _T(" (") << MUP_VERSION_DATE;\r
-      ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT");\r
-\r
-#ifdef _DEBUG\r
-      ss << _T("; DEBUG");\r
-#else \r
-      ss << _T("; RELEASE");\r
-#endif\r
-\r
-#ifdef _UNICODE\r
-      ss << _T("; UNICODE");\r
-#else\r
-  #ifdef _MBCS\r
-      ss << _T("; MBCS");\r
-  #else\r
-      ss << _T("; ASCII");\r
-  #endif\r
-#endif\r
-\r
-#ifdef MUP_USE_OPENMP\r
-      ss << _T("; OPENMP");\r
-//#else\r
-//      ss << _T("; NO_OPENMP");\r
-#endif\r
-\r
-#if defined(MUP_MATH_EXCEPTIONS)\r
-      ss << _T("; MATHEXC");\r
-//#else\r
-//      ss << _T("; NO_MATHEXC");\r
-#endif\r
-\r
-      ss << _T(")");\r
-    }\r
-\r
-    return ss.str();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a value parsing function. \r
-      \r
-      When parsing an expression muParser tries to detect values in the expression\r
-      string using different valident callbacks. Thuis it's possible to parse\r
-      for hex values, binary values and floating point values. \r
-  */\r
-  void ParserBase::AddValIdent(identfun_type a_pCallback)\r
-  {\r
-    m_pTokenReader->AddValIdent(a_pCallback);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Set a function that can create variable pointer for unknown expression variables. \r
-      \param a_pFactory A pointer to the variable factory.\r
-      \param pUserData A user defined context pointer.\r
-  */\r
-  void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData)\r
-  {\r
-    m_pTokenReader->SetVarCreator(a_pFactory, pUserData);  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a function or operator callback to the parser. */\r
-  void ParserBase::AddCallback( const string_type &a_strName,\r
-                                const ParserCallback &a_Callback, \r
-                                funmap_type &a_Storage,\r
-                                const char_type *a_szCharSet )\r
-  {\r
-    if (a_Callback.GetAddr()==0)\r
-        Error(ecINVALID_FUN_PTR);\r
-\r
-    const funmap_type *pFunMap = &a_Storage;\r
-\r
-    // Check for conflicting operator or function names\r
-    if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )\r
-      Error(ecNAME_CONFLICT, -1, a_strName);\r
-\r
-    if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )\r
-      Error(ecNAME_CONFLICT, -1, a_strName);\r
-\r
-    if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )\r
-      Error(ecNAME_CONFLICT, -1, a_strName);\r
-\r
-    if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )\r
-      Error(ecNAME_CONFLICT, -1, a_strName);\r
-\r
-    CheckOprt(a_strName, a_Callback, a_szCharSet);\r
-    a_Storage[a_strName] = a_Callback;\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a name contains invalid characters. \r
-\r
-      \throw ParserException if the name contains invalid charakters.\r
-  */\r
-  void ParserBase::CheckOprt(const string_type &a_sName,\r
-                             const ParserCallback &a_Callback,\r
-                             const string_type &a_szCharSet) const\r
-  {\r
-    if ( !a_sName.length() ||\r
-        (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
-        (a_sName[0]>='0' && a_sName[0]<='9'))\r
-    {\r
-      switch(a_Callback.GetCode())\r
-      {\r
-      case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName);\r
-      case cmOPRT_INFIX:   Error(ecINVALID_INFIX_IDENT, -1, a_sName);\r
-      default:             Error(ecINVALID_NAME, -1, a_sName);\r
-      }\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a name contains invalid characters. \r
-\r
-      \throw ParserException if the name contains invalid charakters.\r
-  */\r
-  void ParserBase::CheckName(const string_type &a_sName,\r
-                             const string_type &a_szCharSet) const\r
-  {\r
-    if ( !a_sName.length() ||\r
-        (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
-        (a_sName[0]>='0' && a_sName[0]<='9'))\r
-    {\r
-      Error(ecINVALID_NAME);\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Set the formula. \r
-      \param a_strFormula Formula as string_type\r
-      \throw ParserException in case of syntax errors.\r
-\r
-      Triggers first time calculation thus the creation of the bytecode and\r
-      scanning of used variables.\r
-  */\r
-  void ParserBase::SetExpr(const string_type &a_sExpr)\r
-  {\r
-    // Check locale compatibility\r
-    std::locale loc;\r
-    if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point())\r
-      Error(ecLOCALE);\r
-\r
-    // <ibg> 20060222: Bugfix for Borland-Kylix:\r
-    // adding a space to the expression will keep Borlands KYLIX from going wild\r
-    // when calling tellg on a stringstream created from the expression after \r
-    // reading a value at the end of an expression. (mu::Parser::IsVal function)\r
-    // (tellg returns -1 otherwise causing the parser to ignore the value)\r
-    string_type sBuf(a_sExpr + _T(" ") );\r
-    m_pTokenReader->SetFormula(sBuf);\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Get the default symbols used for the built in operators. \r
-      \sa c_DefaultOprt\r
-  */\r
-  const char_type** ParserBase::GetOprtDef() const\r
-  {\r
-    return (const char_type **)(&c_DefaultOprt[0]);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define the set of valid characters to be used in names of\r
-             functions, variables, constants.\r
-  */\r
-  void ParserBase::DefineNameChars(const char_type *a_szCharset)\r
-  {\r
-    m_sNameChars = a_szCharset;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define the set of valid characters to be used in names of\r
-             binary operators and postfix operators.\r
-  */\r
-  void ParserBase::DefineOprtChars(const char_type *a_szCharset)\r
-  {\r
-    m_sOprtChars = a_szCharset;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define the set of valid characters to be used in names of\r
-             infix operators.\r
-  */\r
-  void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset)\r
-  {\r
-    m_sInfixOprtChars = a_szCharset;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Virtual function that defines the characters allowed in name identifiers. \r
-      \sa #ValidOprtChars, #ValidPrefixOprtChars\r
-  */ \r
-  const char_type* ParserBase::ValidNameChars() const\r
-  {\r
-    assert(m_sNameChars.size());\r
-    return m_sNameChars.c_str();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Virtual function that defines the characters allowed in operator definitions. \r
-      \sa #ValidNameChars, #ValidPrefixOprtChars\r
-  */\r
-  const char_type* ParserBase::ValidOprtChars() const\r
-  {\r
-    assert(m_sOprtChars.size());\r
-    return m_sOprtChars.c_str();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Virtual function that defines the characters allowed in infix operator definitions.\r
-      \sa #ValidNameChars, #ValidOprtChars\r
-  */\r
-  const char_type* ParserBase::ValidInfixOprtChars() const\r
-  {\r
-    assert(m_sInfixOprtChars.size());\r
-    return m_sInfixOprtChars.c_str();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a user defined operator. \r
-      \post Will reset the Parser to string parsing mode.\r
-  */\r
-  void ParserBase::DefinePostfixOprt(const string_type &a_sName, \r
-                                     fun_type1 a_pFun,\r
-                                     bool a_bAllowOpt)\r
-  {\r
-    AddCallback(a_sName, \r
-                ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX),\r
-                m_PostOprtDef, \r
-                ValidOprtChars() );\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize user defined functions. \r
-   \r
-    Calls the virtual functions InitFun(), InitConst() and InitOprt().\r
-  */\r
-  void ParserBase::Init()\r
-  {\r
-    InitCharSets();\r
-    InitFun();\r
-    InitConst();\r
-    InitOprt();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a user defined operator. \r
-      \post Will reset the Parser to string parsing mode.\r
-      \param [in] a_sName  operator Identifier \r
-      \param [in] a_pFun  Operator callback function\r
-      \param [in] a_iPrec  Operator Precedence (default=prSIGN)\r
-      \param [in] a_bAllowOpt  True if operator is volatile (default=false)\r
-      \sa EPrec\r
-  */\r
-  void ParserBase::DefineInfixOprt(const string_type &a_sName, \r
-                                  fun_type1 a_pFun, \r
-                                  int a_iPrec, \r
-                                  bool a_bAllowOpt)\r
-  {\r
-    AddCallback(a_sName, \r
-                ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), \r
-                m_InfixOprtDef, \r
-                ValidInfixOprtChars() );\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define a binary operator. \r
-      \param [in] a_sName The identifier of the operator.\r
-      \param [in] a_pFun Pointer to the callback function.\r
-      \param [in] a_iPrec Precedence of the operator.\r
-      \param [in] a_eAssociativity The associativity of the operator.\r
-      \param [in] a_bAllowOpt If this is true the operator may be optimized away.\r
-      \r
-      Adds a new Binary operator the the parser instance. \r
-  */\r
-  void ParserBase::DefineOprt( const string_type &a_sName, \r
-                               fun_type2 a_pFun, \r
-                               unsigned a_iPrec, \r
-                               EOprtAssociativity a_eAssociativity,\r
-                               bool a_bAllowOpt )\r
-  {\r
-    // Check for conflicts with built in operator names\r
-    for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i)\r
-      if (a_sName == string_type(c_DefaultOprt[i]))\r
-        Error(ecBUILTIN_OVERLOAD, -1, a_sName);\r
-\r
-    AddCallback(a_sName, \r
-                ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), \r
-                m_OprtDef, \r
-                ValidOprtChars() );\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Define a new string constant.\r
-      \param [in] a_strName The name of the constant.\r
-      \param [in] a_strVal the value of the constant. \r
-  */\r
-  void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)\r
-  {\r
-    // Test if a constant with that names already exists\r
-    if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())\r
-      Error(ecNAME_CONFLICT);\r
-\r
-    CheckName(a_strName, ValidNameChars());\r
-    \r
-    m_vStringVarBuf.push_back(a_strVal);                // Store variable string in internal buffer\r
-    m_StrVarDef[a_strName] = m_vStringVarBuf.size()-1;  // bind buffer index to variable name\r
-\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a user defined variable. \r
-      \param [in] a_sName the variable name\r
-      \param [in] a_pVar A pointer to the variable vaule.\r
-      \post Will reset the Parser to string parsing mode.\r
-      \throw ParserException in case the name contains invalid signs or a_pVar is NULL.\r
-  */\r
-  void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar)\r
-  {\r
-    if (a_pVar==0)\r
-      Error(ecINVALID_VAR_PTR);\r
-\r
-    // Test if a constant with that names already exists\r
-    if (m_ConstDef.find(a_sName)!=m_ConstDef.end())\r
-      Error(ecNAME_CONFLICT);\r
-\r
-    CheckName(a_sName, ValidNameChars());\r
-    m_VarDef[a_sName] = a_pVar;\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a user defined constant. \r
-      \param [in] a_sName The name of the constant.\r
-      \param [in] a_fVal the value of the constant.\r
-      \post Will reset the Parser to string parsing mode.\r
-      \throw ParserException in case the name contains invalid signs.\r
-  */\r
-  void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal)\r
-  {\r
-    CheckName(a_sName, ValidNameChars());\r
-    m_ConstDef[a_sName] = a_fVal;\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Get operator priority.\r
-      \throw ParserException if a_Oprt is no operator code\r
-  */\r
-  int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const\r
-  {\r
-    switch (a_Tok.GetCode())\r
-    {\r
-    // built in operators\r
-    case cmEND:      return -5;\r
-    case cmARG_SEP:  return -4;\r
-    case cmASSIGN:   return -1;               \r
-    case cmELSE:\r
-    case cmIF:       return  0;\r
-    case cmLAND:     return  prLAND;\r
-    case cmLOR:      return  prLOR;\r
-    case cmLT:\r
-    case cmGT:\r
-    case cmLE:\r
-    case cmGE:\r
-    case cmNEQ:\r
-    case cmEQ:       return  prCMP; \r
-    case cmADD:\r
-    case cmSUB:      return  prADD_SUB;\r
-    case cmMUL:\r
-    case cmDIV:      return  prMUL_DIV;\r
-    case cmPOW:      return  prPOW;\r
-\r
-    // user defined binary operators\r
-    case cmOPRT_INFIX: \r
-    case cmOPRT_BIN: return a_Tok.GetPri();\r
-    default:  Error(ecINTERNAL_ERROR, 5);\r
-              return 999;\r
-    }  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Get operator priority.\r
-      \throw ParserException if a_Oprt is no operator code\r
-  */\r
-  EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const\r
-  {\r
-    switch (a_Tok.GetCode())\r
-    {\r
-    case cmASSIGN:\r
-    case cmLAND:\r
-    case cmLOR:\r
-    case cmLT:\r
-    case cmGT:\r
-    case cmLE:\r
-    case cmGE:\r
-    case cmNEQ:\r
-    case cmEQ: \r
-    case cmADD:\r
-    case cmSUB:\r
-    case cmMUL:\r
-    case cmDIV:      return oaLEFT;\r
-    case cmPOW:      return oaRIGHT;\r
-    case cmOPRT_BIN: return a_Tok.GetAssociativity();\r
-    default:         return oaNONE;\r
-    }  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return a map containing the used variables only. */\r
-  const varmap_type& ParserBase::GetUsedVar() const\r
-  {\r
-    try\r
-    {\r
-      m_pTokenReader->IgnoreUndefVar(true);\r
-      CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it\r
-                   // may contain references to nonexisting variables.\r
-      m_pParseFormula = &ParserBase::ParseString;\r
-      m_pTokenReader->IgnoreUndefVar(false);\r
-    }\r
-    catch(exception_type & /*e*/)\r
-    {\r
-      // Make sure to stay in string parse mode, dont call ReInit()\r
-      // because it deletes the array with the used variables\r
-      m_pParseFormula = &ParserBase::ParseString;\r
-      m_pTokenReader->IgnoreUndefVar(false);\r
-      throw;\r
-    }\r
-    \r
-    return m_pTokenReader->GetUsedVar();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return a map containing the used variables only. */\r
-  const varmap_type& ParserBase::GetVar() const\r
-  {\r
-    return m_VarDef;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return a map containing all parser constants. */\r
-  const valmap_type& ParserBase::GetConst() const\r
-  {\r
-    return m_ConstDef;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return prototypes of all parser functions.\r
-      \return #m_FunDef\r
-      \sa FunProt\r
-      \throw nothrow\r
-      \r
-      The return type is a map of the public type #funmap_type containing the prototype\r
-      definitions for all numerical parser functions. String functions are not part of \r
-      this map. The Prototype definition is encapsulated in objects of the class FunProt\r
-      one per parser function each associated with function names via a map construct.\r
-  */\r
-  const funmap_type& ParserBase::GetFunDef() const\r
-  {\r
-    return m_FunDef;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Retrieve the formula. */\r
-  const string_type& ParserBase::GetExpr() const\r
-  {\r
-    return m_pTokenReader->GetExpr();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Execute a function that takes a single string argument.\r
-      \param a_FunTok Function token.\r
-      \throw exception_type If the function token is not a string function\r
-  */\r
-  ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok,\r
-                                                  const std::vector<token_type> &a_vArg) const\r
-  {\r
-    if (a_vArg.back().GetCode()!=cmSTRING)\r
-      Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
-\r
-    token_type  valTok;\r
-    generic_fun_type pFunc = a_FunTok.GetFuncAddr();\r
-    assert(pFunc);\r
-\r
-    try\r
-    {\r
-      // Check function arguments; write dummy value into valtok to represent the result\r
-      switch(a_FunTok.GetArgCount())\r
-      {\r
-      case 0: valTok.SetVal(1); a_vArg[0].GetAsString();  break;\r
-      case 1: valTok.SetVal(1); a_vArg[1].GetAsString();  a_vArg[0].GetVal();  break;\r
-      case 2: valTok.SetVal(1); a_vArg[2].GetAsString();  a_vArg[1].GetVal();  a_vArg[0].GetVal();  break;\r
-      default: Error(ecINTERNAL_ERROR);\r
-      }\r
-    }\r
-    catch(ParserError& )\r
-    {\r
-      Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
-    }\r
-\r
-    // string functions won't be optimized\r
-    m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());\r
-    \r
-    // Push dummy value representing the function result to the stack\r
-    return valTok;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Apply a function token. \r
-      \param iArgCount Number of Arguments actually gathered used only for multiarg functions.\r
-      \post The result is pushed to the value stack\r
-      \post The function token is removed from the stack\r
-      \throw exception_type if Argument count does not mach function requirements.\r
-  */\r
-  void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,\r
-                              ParserStack<token_type> &a_stVal, \r
-                              int a_iArgCount) const\r
-  { \r
-    assert(m_pTokenReader.get());\r
-\r
-    // Operator stack empty or does not contain tokens with callback functions\r
-    if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )\r
-      return;\r
-\r
-    token_type funTok = a_stOpt.pop();\r
-    assert(funTok.GetFuncAddr());\r
-\r
-    // Binary operators must rely on their internal operator number\r
-    // since counting of operators relies on commas for function arguments\r
-    // binary operators do not have commas in their expression\r
-    int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;\r
-\r
-    // determine how many parameters the function needs. To remember iArgCount includes the \r
-    // string parameter whilst GetArgCount() counts only numeric parameters.\r
-    int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0);\r
-\r
-    // Thats the number of numerical parameters\r
-    int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0);\r
-\r
-    if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1)\r
-      Error(ecINTERNAL_ERROR);\r
-\r
-    if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) \r
-      Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
-\r
-    if (funTok.GetCode()!=cmOPRT_BIN && iArgCount<iArgRequired )\r
-      Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
-\r
-    if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired )\r
-      Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
-\r
-    // Collect the numeric function arguments from the value stack and store them\r
-    // in a vector\r
-    std::vector<token_type> stArg;  \r
-    for (int i=0; i<iArgNumerical; ++i)\r
-    {\r
-      stArg.push_back( a_stVal.pop() );\r
-      if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
-        Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
-    }\r
-\r
-    switch(funTok.GetCode())\r
-    {\r
-    case  cmFUNC_STR:  \r
-          stArg.push_back(a_stVal.pop());\r
-          \r
-          if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
-            Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
-\r
-          ApplyStrFunc(funTok, stArg); \r
-          break;\r
-\r
-    case  cmFUNC_BULK: \r
-          m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); \r
-          break;\r
-\r
-    case  cmOPRT_BIN:\r
-    case  cmOPRT_POSTFIX:\r
-    case  cmOPRT_INFIX:\r
-    case  cmFUNC:\r
-          if (funTok.GetArgCount()==-1 && iArgCount==0)\r
-            Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());\r
-\r
-          m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical);\r
-          break;\r
-    default:\r
-          break;\r
-    }\r
-\r
-    // Push dummy value representing the function result to the stack\r
-    token_type token;\r
-    token.SetVal(1);  \r
-    a_stVal.push(token);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
-                               ParserStack<token_type> &a_stVal) const\r
-  {\r
-    // Check if there is an if Else clause to be calculated\r
-    while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE)\r
-    {\r
-      token_type opElse = a_stOpt.pop();\r
-      MUP_ASSERT(a_stOpt.size()>0);\r
-\r
-      // Take the value associated with the else branch from the value stack\r
-      token_type vVal2 = a_stVal.pop();\r
-\r
-      MUP_ASSERT(a_stOpt.size()>0);\r
-      MUP_ASSERT(a_stVal.size()>=2);\r
-\r
-      // it then else is a ternary operator Pop all three values from the value s\r
-      // tack and just return the right value\r
-      token_type vVal1 = a_stVal.pop();\r
-      token_type vExpr = a_stVal.pop();\r
-\r
-      a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2);\r
-\r
-      token_type opIf = a_stOpt.pop();\r
-      MUP_ASSERT(opElse.GetCode()==cmELSE);\r
-      MUP_ASSERT(opIf.GetCode()==cmIF);\r
-\r
-      m_vRPN.AddIfElse(cmENDIF);\r
-    } // while pending if-else-clause found\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Performs the necessary steps to write code for\r
-             the execution of binary operators into the bytecode. \r
-  */\r
-  void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
-                                ParserStack<token_type> &a_stVal) const\r
-  {\r
-    // is it a user defined binary operator?\r
-    if (a_stOpt.top().GetCode()==cmOPRT_BIN)\r
-    {\r
-      ApplyFunc(a_stOpt, a_stVal, 2);\r
-    }\r
-    else\r
-    {\r
-      MUP_ASSERT(a_stVal.size()>=2);\r
-      token_type valTok1 = a_stVal.pop(),\r
-                 valTok2 = a_stVal.pop(),\r
-                 optTok  = a_stOpt.pop(),\r
-                 resTok; \r
-\r
-      if ( valTok1.GetType()!=valTok2.GetType() || \r
-          (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) )\r
-        Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());\r
-\r
-      if (optTok.GetCode()==cmASSIGN)\r
-      {\r
-        if (valTok2.GetCode()!=cmVAR)\r
-          Error(ecUNEXPECTED_OPERATOR, -1, _T("="));\r
-                      \r
-        m_vRPN.AddAssignOp(valTok2.GetVar());\r
-      }\r
-      else\r
-        m_vRPN.AddOp(optTok.GetCode());\r
-\r
-      resTok.SetVal(1);\r
-      a_stVal.push(resTok);\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Apply a binary operator. \r
-      \param a_stOpt The operator stack\r
-      \param a_stVal The value stack\r
-  */\r
-  void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,\r
-                                      ParserStack<token_type> &stVal) const\r
-  {\r
-    while (stOpt.size() && \r
-           stOpt.top().GetCode() != cmBO &&\r
-           stOpt.top().GetCode() != cmIF)\r
-    {\r
-      token_type tok = stOpt.top();\r
-      switch (tok.GetCode())\r
-      {\r
-      case cmOPRT_INFIX:\r
-      case cmOPRT_BIN:\r
-      case cmLE:\r
-      case cmGE:\r
-      case cmNEQ:\r
-      case cmEQ:\r
-      case cmLT:\r
-      case cmGT:\r
-      case cmADD:\r
-      case cmSUB:\r
-      case cmMUL:\r
-      case cmDIV:\r
-      case cmPOW:\r
-      case cmLAND:\r
-      case cmLOR:\r
-      case cmASSIGN:\r
-          if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
-            ApplyFunc(stOpt, stVal, 1);\r
-          else\r
-            ApplyBinOprt(stOpt, stVal);\r
-          break;\r
-\r
-      case cmELSE:\r
-          ApplyIfElse(stOpt, stVal);\r
-          break;\r
-\r
-      default:\r
-          Error(ecINTERNAL_ERROR);\r
-      }\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Parse the command code.\r
-      \sa ParseString(...)\r
-\r
-      Command code contains precalculated stack positions of the values and the\r
-      associated operators. The Stack is filled beginning from index one the \r
-      value at index zero is not used at all.\r
-  */\r
-  value_type ParserBase::ParseCmdCode() const\r
-  {\r
-    return ParseCmdCodeBulk(0, 0);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Evaluate the RPN. \r
-      \param nOffset The offset added to variable addresses (for bulk mode)\r
-      \param nThreadID OpenMP Thread id of the calling thread\r
-  */\r
-  value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const\r
-  {\r
-    assert(nThreadID<=s_MaxNumOpenMPThreads);\r
-\r
-    // Note: The check for nOffset==0 and nThreadID here is not necessary but \r
-    //       brings a minor performance gain when not in bulk mode.\r
-    value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];\r
-    value_type buf;\r
-    int sidx(0);\r
-    for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok)\r
-    {\r
-      switch (pTok->Cmd)\r
-      {\r
-      // built in binary operators\r
-      case  cmLE:   --sidx; Stack[sidx]  = Stack[sidx] <= Stack[sidx+1]; continue;\r
-      case  cmGE:   --sidx; Stack[sidx]  = Stack[sidx] >= Stack[sidx+1]; continue;\r
-      case  cmNEQ:  --sidx; Stack[sidx]  = Stack[sidx] != Stack[sidx+1]; continue;\r
-      case  cmEQ:   --sidx; Stack[sidx]  = Stack[sidx] == Stack[sidx+1]; continue;\r
-      case  cmLT:   --sidx; Stack[sidx]  = Stack[sidx] < Stack[sidx+1];  continue;\r
-      case  cmGT:   --sidx; Stack[sidx]  = Stack[sidx] > Stack[sidx+1];  continue;\r
-      case  cmADD:  --sidx; Stack[sidx] += Stack[1+sidx]; continue;\r
-      case  cmSUB:  --sidx; Stack[sidx] -= Stack[1+sidx]; continue;\r
-      case  cmMUL:  --sidx; Stack[sidx] *= Stack[1+sidx]; continue;\r
-      case  cmDIV:  --sidx;\r
-\r
-  #if defined(MUP_MATH_EXCEPTIONS)\r
-                  if (Stack[1+sidx]==0)\r
-                    Error(ecDIV_BY_ZERO);\r
-  #endif\r
-                  Stack[sidx] /= Stack[1+sidx]; \r
-                  continue;\r
-\r
-      case  cmPOW: \r
-              --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]);\r
-              continue;\r
-\r
-      case  cmLAND: --sidx; Stack[sidx]  = (Stack[sidx] != 0.) && (Stack[sidx+1] != 0.); continue;\r
-      case  cmLOR:  --sidx; Stack[sidx]  = (Stack[sidx] != 0.) || (Stack[sidx+1] != 0.); continue;\r
-\r
-      case  cmASSIGN: \r
-          // Bugfix for Bulkmode:\r
-          // for details see:\r
-          //    https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws\r
-          --sidx; Stack[sidx] = *(pTok->u.Oprt.ptr + nOffset) = Stack[sidx + 1]; continue;\r
-          // original code:\r
-          //--sidx; Stack[sidx] = *pTok->u.Oprt.ptr = Stack[sidx+1]; continue;\r
-\r
-      //case  cmBO:  // unused, listed for compiler optimization purposes\r
-      //case  cmBC:\r
-      //      MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
-      //      continue;\r
-\r
-      case  cmIF:\r
-            if (Stack[sidx--]==0)\r
-              pTok += pTok->u.Oprt.offset;\r
-            continue;\r
-\r
-      case  cmELSE:\r
-            pTok += pTok->u.Oprt.offset;\r
-            continue;\r
-\r
-      case  cmENDIF:\r
-            continue;\r
-\r
-      //case  cmARG_SEP:\r
-      //      MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
-      //      continue;\r
-\r
-      // value and variable tokens\r
-      case  cmVAR:    Stack[++sidx] = *(pTok->u.Val.ptr + nOffset);  continue;\r
-      case  cmVAL:    Stack[++sidx] =  pTok->u.Val.data2;  continue;\r
-      \r
-      case  cmVARPOW2: buf = *(pTok->u.Val.ptr + nOffset);\r
-                       Stack[++sidx] = buf*buf;\r
-                       continue;\r
-\r
-      case  cmVARPOW3: buf = *(pTok->u.Val.ptr + nOffset);\r
-                       Stack[++sidx] = buf*buf*buf;\r
-                       continue;\r
-\r
-      case  cmVARPOW4: buf = *(pTok->u.Val.ptr + nOffset);\r
-                       Stack[++sidx] = buf*buf*buf*buf;\r
-                       continue;\r
-      \r
-      case  cmVARMUL:  Stack[++sidx] = *(pTok->u.Val.ptr + nOffset) * pTok->u.Val.data + pTok->u.Val.data2;\r
-                       continue;\r
-\r
-      // Next is treatment of numeric functions\r
-      case  cmFUNC:\r
-            {\r
-              int iArgCount = pTok->u.Fun.argc;\r
-\r
-              // switch according to argument count\r
-              switch(iArgCount)  \r
-              {\r
-              case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->u.Fun.ptr)(); continue;\r
-              case 1:            Stack[sidx] = (*(fun_type1)pTok->u.Fun.ptr)(Stack[sidx]);   continue;\r
-              case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue;\r
-              case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
-              case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
-              case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
-              case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
-              case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
-              case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
-              case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
-              case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
-              default:\r
-                if (iArgCount>0) // function with variable arguments store the number as a negative value\r
-                  Error(ecINTERNAL_ERROR, 1);\r
-\r
-                sidx -= -iArgCount - 1;\r
-                Stack[sidx] =(*(multfun_type)pTok->u.Fun.ptr)(&Stack[sidx], -iArgCount);\r
-                continue;\r
-              }\r
-            }\r
-\r
-      // Next is treatment of string functions\r
-      case  cmFUNC_STR:\r
-            {\r
-              sidx -= pTok->u.Fun.argc -1;\r
-\r
-              // The index of the string argument in the string table\r
-              int iIdxStack = pTok->u.Fun.idx;  \r
-              MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() );\r
-\r
-              switch(pTok->u.Fun.argc)  // switch according to argument count\r
-              {\r
-              case 0: Stack[sidx] = (*(strfun_type1)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;\r
-              case 1: Stack[sidx] = (*(strfun_type2)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;\r
-              case 2: Stack[sidx] = (*(strfun_type3)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue;\r
-              }\r
-\r
-              continue;\r
-            }\r
-\r
-        case  cmFUNC_BULK:\r
-              {\r
-                int iArgCount = pTok->u.Fun.argc;\r
-\r
-                // switch according to argument count\r
-                switch(iArgCount)  \r
-                {\r
-                case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->u.Fun.ptr)(nOffset, nThreadID); continue;\r
-                case 1:            Stack[sidx] = (*(bulkfun_type1 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue;\r
-                case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue;\r
-                case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
-                case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
-                case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
-                case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
-                case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
-                case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
-                case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
-                case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
-                default:\r
-                  Error(ecINTERNAL_ERROR, 2);\r
-                  continue;\r
-                }\r
-              }\r
-\r
-        default:\r
-              Error(ecINTERNAL_ERROR, 3);\r
-              return 0;\r
-      } // switch CmdCode\r
-    } // for all bytecode tokens\r
-\r
-    return Stack[m_nFinalResultIdx];  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserBase::CreateRPN() const\r
-  {\r
-    if (!m_pTokenReader->GetExpr().length())\r
-      Error(ecUNEXPECTED_EOF, 0);\r
-\r
-    ParserStack<token_type> stOpt, stVal;\r
-    ParserStack<int> stArgCount;\r
-    token_type opta, opt;  // for storing operators\r
-    token_type val, tval;  // for storing value\r
-\r
-    ReInit();\r
-    \r
-    // The outermost counter counts the number of seperated items\r
-    // such as in "a=10,b=20,c=c+a"\r
-    stArgCount.push(1);\r
-    \r
-    for(;;)\r
-    {\r
-      opt = m_pTokenReader->ReadNextToken();\r
-\r
-      switch (opt.GetCode())\r
-      {\r
-        //\r
-        // Next three are different kind of value entries\r
-        //\r
-        case cmSTRING:\r
-                opt.SetIdx((int)m_vStringBuf.size());      // Assign buffer index to token \r
-                stVal.push(opt);\r
-                           m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer\r
-                break;\r
-   \r
-        case cmVAR:\r
-                stVal.push(opt);\r
-                m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) );\r
-                break;\r
-\r
-        case cmVAL:\r
-                       stVal.push(opt);\r
-                m_vRPN.AddVal( opt.GetVal() );\r
-                break;\r
-\r
-        case cmELSE:\r
-                m_nIfElseCounter--;\r
-                if (m_nIfElseCounter<0)\r
-                  Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());\r
-\r
-                ApplyRemainingOprt(stOpt, stVal);\r
-                m_vRPN.AddIfElse(cmELSE);\r
-                stOpt.push(opt);\r
-                break;\r
-\r
-\r
-        case cmARG_SEP:\r
-                if (stArgCount.empty())\r
-                  Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());\r
-\r
-                ++stArgCount.top();\r
-                // fallthrough intentional (no break!)\r
-\r
-        case cmEND:\r
-                ApplyRemainingOprt(stOpt, stVal);\r
-                break;\r
-\r
-       case cmBC:\r
-                {\r
-                  // The argument count for parameterless functions is zero\r
-                  // by default an opening bracket sets parameter count to 1\r
-                  // in preparation of arguments to come. If the last token\r
-                  // was an opening bracket we know better...\r
-                  if (opta.GetCode()==cmBO)\r
-                    --stArgCount.top();\r
-                  \r
-                  ApplyRemainingOprt(stOpt, stVal);\r
-\r
-                  // Check if the bracket content has been evaluated completely\r
-                  if (stOpt.size() && stOpt.top().GetCode()==cmBO)\r
-                  {\r
-                    // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check\r
-                    // if there is either a function or a sign pending\r
-                    // neither the opening nor the closing bracket will be pushed back to\r
-                    // the operator stack\r
-                    // Check if a function is standing in front of the opening bracket, \r
-                    // if yes evaluate it afterwards check for infix operators\r
-                    assert(stArgCount.size());\r
-                    int iArgCount = stArgCount.pop();\r
-                    \r
-                    stOpt.pop(); // Take opening bracket from stack\r
-\r
-                    if (iArgCount>1 && ( stOpt.size()==0 || \r
-                                        (stOpt.top().GetCode()!=cmFUNC && \r
-                                         stOpt.top().GetCode()!=cmFUNC_BULK && \r
-                                         stOpt.top().GetCode()!=cmFUNC_STR) ) )\r
-                      Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());\r
-                    \r
-                    // The opening bracket was popped from the stack now check if there\r
-                    // was a function before this bracket\r
-                    if (stOpt.size() && \r
-                        stOpt.top().GetCode()!=cmOPRT_INFIX && \r
-                        stOpt.top().GetCode()!=cmOPRT_BIN && \r
-                        stOpt.top().GetFuncAddr()!=0)\r
-                    {\r
-                      ApplyFunc(stOpt, stVal, iArgCount);\r
-                    }\r
-                  }\r
-                } // if bracket content is evaluated\r
-                break;\r
-\r
-        //\r
-        // Next are the binary operator entries\r
-        //\r
-        //case cmAND:   // built in binary operators\r
-        //case cmOR:\r
-        //case cmXOR:\r
-        case cmIF:\r
-                m_nIfElseCounter++;\r
-                // fallthrough intentional (no break!)\r
-\r
-        case cmLAND:\r
-        case cmLOR:\r
-        case cmLT:\r
-        case cmGT:\r
-        case cmLE:\r
-        case cmGE:\r
-        case cmNEQ:\r
-        case cmEQ:\r
-        case cmADD:\r
-        case cmSUB:\r
-        case cmMUL:\r
-        case cmDIV:\r
-        case cmPOW:\r
-        case cmASSIGN:\r
-        case cmOPRT_BIN:\r
-\r
-                // A binary operator (user defined or built in) has been found. \r
-                while ( stOpt.size() && \r
-                        stOpt.top().GetCode() != cmBO &&\r
-                        stOpt.top().GetCode() != cmELSE &&\r
-                        stOpt.top().GetCode() != cmIF)\r
-                {\r
-                  int nPrec1 = GetOprtPrecedence(stOpt.top()),\r
-                      nPrec2 = GetOprtPrecedence(opt);\r
-\r
-                  if (stOpt.top().GetCode()==opt.GetCode())\r
-                  {\r
-\r
-                    // Deal with operator associativity\r
-                    EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);\r
-                    if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || \r
-                         (eOprtAsct==oaLEFT  && (nPrec1 <  nPrec2)) )\r
-                    {\r
-                      break;\r
-                    }\r
-                  }\r
-                  else if (nPrec1 < nPrec2)\r
-                  {\r
-                    // In case the operators are not equal the precedence decides alone...\r
-                    break;\r
-                  }\r
-                  \r
-                  if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
-                    ApplyFunc(stOpt, stVal, 1);\r
-                  else\r
-                    ApplyBinOprt(stOpt, stVal);\r
-                } // while ( ... )\r
-\r
-                if (opt.GetCode()==cmIF)\r
-                  m_vRPN.AddIfElse(opt.GetCode());\r
-\r
-                             // The operator can't be evaluated right now, push back to the operator stack\r
-                stOpt.push(opt);\r
-                break;\r
-\r
-        //\r
-        // Last section contains functions and operators implicitely mapped to functions\r
-        //\r
-        case cmBO:\r
-                stArgCount.push(1);\r
-                stOpt.push(opt);\r
-                break;\r
-\r
-        case cmOPRT_INFIX:\r
-        case cmFUNC:\r
-        case cmFUNC_BULK:\r
-        case cmFUNC_STR:  \r
-                stOpt.push(opt);\r
-                break;\r
-\r
-        case cmOPRT_POSTFIX:\r
-                stOpt.push(opt);\r
-                ApplyFunc(stOpt, stVal, 1);  // this is the postfix operator\r
-                break;\r
-\r
-        default:  Error(ecINTERNAL_ERROR, 3);\r
-      } // end of switch operator-token\r
-\r
-      opta = opt;\r
-\r
-      if ( opt.GetCode() == cmEND )\r
-      {\r
-        m_vRPN.Finalize();\r
-        break;\r
-      }\r
-\r
-      if (ParserBase::g_DbgDumpStack)\r
-      {\r
-        StackDump(stVal, stOpt);\r
-        m_vRPN.AsciiDump();\r
-      }\r
-    } // while (true)\r
-\r
-    if (ParserBase::g_DbgDumpCmdCode)\r
-      m_vRPN.AsciiDump();\r
-\r
-    if (m_nIfElseCounter>0)\r
-      Error(ecMISSING_ELSE_CLAUSE);\r
-\r
-    // get the last value (= final result) from the stack\r
-    MUP_ASSERT(stArgCount.size()==1);\r
-    m_nFinalResultIdx = stArgCount.top();\r
-    if (m_nFinalResultIdx==0)\r
-      Error(ecINTERNAL_ERROR, 9);\r
-\r
-    if (stVal.size()==0)\r
-      Error(ecEMPTY_EXPRESSION);\r
-\r
-    if (stVal.top().GetType()!=tpDBL)\r
-      Error(ecSTR_RESULT);\r
-\r
-    m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief One of the two main parse functions.\r
-      \sa ParseCmdCode(...)\r
-\r
-    Parse expression from input string. Perform syntax checking and create \r
-    bytecode. After parsing the string and creating the bytecode the function \r
-    pointer #m_pParseFormula will be changed to the second parse routine the \r
-    uses bytecode instead of string parsing.\r
-  */\r
-  value_type ParserBase::ParseString() const\r
-  {\r
-    try\r
-    {\r
-      CreateRPN();\r
-      m_pParseFormula = &ParserBase::ParseCmdCode;\r
-      return (this->*m_pParseFormula)(); \r
-    }\r
-    catch(ParserError &exc)\r
-    {\r
-      exc.SetFormula(m_pTokenReader->GetExpr());\r
-      throw;\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Create an error containing the parse error position.\r
-\r
-    This function will create an Parser Exception object containing the error text and\r
-    its position.\r
-\r
-    \param a_iErrc [in] The error code of type #EErrorCodes.\r
-    \param a_iPos [in] The position where the error was detected.\r
-    \param a_strTok [in] The token string representation associated with the error.\r
-    \throw ParserException always throws thats the only purpose of this function.\r
-  */\r
-  void  ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const\r
-  {\r
-    throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear all user defined variables.\r
-      \throw nothrow\r
-\r
-      Resets the parser to string parsing mode by calling #ReInit.\r
-  */\r
-  void ParserBase::ClearVar()\r
-  {\r
-    m_VarDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Remove a variable from internal storage.\r
-      \throw nothrow\r
-\r
-      Removes a variable if it exists. If the Variable does not exist nothing will be done.\r
-  */\r
-  void ParserBase::RemoveVar(const string_type &a_strVarName)\r
-  {\r
-    varmap_type::iterator item = m_VarDef.find(a_strVarName);\r
-    if (item!=m_VarDef.end())\r
-    {\r
-      m_VarDef.erase(item);\r
-      ReInit();\r
-    }\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear all functions.\r
-      \post Resets the parser to string parsing mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ClearFun()\r
-  {\r
-    m_FunDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear all user defined constants.\r
-\r
-      Both numeric and string constants will be removed from the internal storage.\r
-      \post Resets the parser to string parsing mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ClearConst()\r
-  {\r
-    m_ConstDef.clear();\r
-    m_StrVarDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear all user defined postfix operators.\r
-      \post Resets the parser to string parsing mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ClearPostfixOprt()\r
-  {\r
-    m_PostOprtDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear all user defined binary operators.\r
-      \post Resets the parser to string parsing mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ClearOprt()\r
-  {\r
-    m_OprtDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Clear the user defined Prefix operators. \r
-      \post Resets the parser to string parser mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::ClearInfixOprt()\r
-  {\r
-    m_InfixOprtDef.clear();\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Enable or disable the formula optimization feature. \r
-      \post Resets the parser to string parser mode.\r
-      \throw nothrow\r
-  */\r
-  void ParserBase::EnableOptimizer(bool a_bIsOn)\r
-  {\r
-    m_vRPN.EnableOptimizer(a_bIsOn);\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Enable the dumping of bytecode amd stack content on the console. \r
-      \param bDumpCmd Flag to enable dumping of the current bytecode to the console.\r
-      \param bDumpStack Flag to enable dumping of the stack content is written to the console.\r
-\r
-     This function is for debug purposes only!\r
-  */\r
-  void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)\r
-  {\r
-    ParserBase::g_DbgDumpCmdCode = bDumpCmd;\r
-    ParserBase::g_DbgDumpStack   = bDumpStack;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Enable or disable the built in binary operators.\r
-      \throw nothrow\r
-      \sa m_bBuiltInOp, ReInit()\r
-\r
-    If you disable the built in binary operators there will be no binary operators\r
-    defined. Thus you must add them manually one by one. It is not possible to\r
-    disable built in operators selectively. This function will Reinitialize the\r
-    parser by calling ReInit().\r
-  */\r
-  void ParserBase::EnableBuiltInOprt(bool a_bIsOn)\r
-  {\r
-    m_bBuiltInOp = a_bIsOn;\r
-    ReInit();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Query status of built in variables.\r
-      \return #m_bBuiltInOp; true if built in operators are enabled.\r
-      \throw nothrow\r
-  */\r
-  bool ParserBase::HasBuiltInOprt() const\r
-  {\r
-    return m_bBuiltInOp;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Get the argument separator character. \r
-  */\r
-  char_type ParserBase::GetArgSep() const\r
-  {\r
-    return m_pTokenReader->GetArgSep();\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Set argument separator. \r
-      \param cArgSep the argument separator character.\r
-  */\r
-  void ParserBase::SetArgSep(char_type cArgSep)\r
-  {\r
-    m_pTokenReader->SetArgSep(cArgSep);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Dump stack content. \r
-\r
-      This function is used for debugging only.\r
-  */\r
-  void ParserBase::StackDump(const ParserStack<token_type> &a_stVal, \r
-                             const ParserStack<token_type> &a_stOprt) const\r
-  {\r
-    ParserStack<token_type> stOprt(a_stOprt), \r
-                            stVal(a_stVal);\r
-\r
-    mu::console() << _T("\nValue stack:\n");\r
-    while ( !stVal.empty() ) \r
-    {\r
-      token_type val = stVal.pop();\r
-      if (val.GetType()==tpSTR)\r
-        mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");\r
-      else\r
-        mu::console() << _T(" ") << val.GetVal() << _T(" ");\r
-    }\r
-    mu::console() << "\nOperator stack:\n";\r
-\r
-    while ( !stOprt.empty() )\r
-    {\r
-      if (stOprt.top().GetCode()<=cmASSIGN) \r
-      {\r
-        mu::console() << _T("OPRT_INTRNL \"")\r
-                      << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] \r
-                      << _T("\" \n");\r
-      }\r
-      else\r
-      {\r
-        switch(stOprt.top().GetCode())\r
-        {\r
-        case cmVAR:   mu::console() << _T("VAR\n");  break;\r
-        case cmVAL:   mu::console() << _T("VAL\n");  break;\r
-        case cmFUNC:  mu::console() << _T("FUNC \"") \r
-                                    << stOprt.top().GetAsString() \r
-                                    << _T("\"\n");   break;\r
-        case cmFUNC_BULK:  mu::console() << _T("FUNC_BULK \"") \r
-                                         << stOprt.top().GetAsString() \r
-                                         << _T("\"\n");   break;\r
-        case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"")\r
-                                         << stOprt.top().GetAsString() \r
-                                         << _T("\"\n");      break;\r
-        case cmOPRT_BIN:   mu::console() << _T("OPRT_BIN \"") \r
-                                         << stOprt.top().GetAsString() \r
-                                         << _T("\"\n");           break;\r
-        case cmFUNC_STR: mu::console() << _T("FUNC_STR\n");       break;\r
-        case cmEND:      mu::console() << _T("END\n");            break;\r
-        case cmUNKNOWN:  mu::console() << _T("UNKNOWN\n");        break;\r
-        case cmBO:       mu::console() << _T("BRACKET \"(\"\n");  break;\r
-        case cmBC:       mu::console() << _T("BRACKET \")\"\n");  break;\r
-        case cmIF:       mu::console() << _T("IF\n");  break;\r
-        case cmELSE:     mu::console() << _T("ELSE\n");  break;\r
-        case cmENDIF:    mu::console() << _T("ENDIF\n");  break;\r
-        default:         mu::console() << stOprt.top().GetCode() << _T(" ");  break;\r
-        }\r
-      }        \r
-      stOprt.pop();\r
-    }\r
-\r
-    mu::console() << dec << endl;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Evaluate an expression containing comma seperated subexpressions \r
-      \param [out] nStackSize The total number of results available\r
-      \return Pointer to the array containing all expression results\r
-\r
-      This member function can be used to retriev all results of an expression\r
-      made up of multiple comma seperated subexpressions (i.e. "x+y,sin(x),cos(y)")\r
-  */\r
-  value_type* ParserBase::Eval(int &nStackSize) const\r
-  {\r
-    (this->*m_pParseFormula)(); \r
-    nStackSize = m_nFinalResultIdx;\r
-\r
-    // (for historic reasons the stack starts at position 1)\r
-    return &m_vStackBuffer[1];\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return the number of results on the calculation stack. \r
-  \r
-    If the expression contains comma seperated subexpressions (i.e. "sin(y), x+y"). \r
-    There mey be more than one return value. This function returns the number of \r
-    available results.\r
-  */\r
-  int ParserBase::GetNumResults() const\r
-  {\r
-    return m_nFinalResultIdx;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Calculate the result.\r
-\r
-    A note on const correctness: \r
-    I consider it important that Calc is a const function.\r
-    Due to caching operations Calc changes only the state of internal variables with one exception\r
-    m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making\r
-    Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update. \r
-\r
-    \pre A formula must be set.\r
-    \pre Variables must have been set (if needed)\r
-\r
-    \sa #m_pParseFormula\r
-    \return The evaluation result\r
-    \throw ParseException if no Formula is set or in case of any other error related to the formula.\r
-  */\r
-  value_type ParserBase::Eval() const\r
-  {\r
-    return (this->*m_pParseFormula)(); \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserBase::Eval(value_type *results, int nBulkSize)\r
-  {\r
-/* <ibg 2014-09-24/> Commented because it is making a unit test impossible\r
-\r
-    // Parallelization does not make sense for fewer than 10000 computations \r
-    // due to thread creation overhead. If the bulk size is below 2000\r
-    // computation is refused. \r
-    if (nBulkSize<2000)\r
-    {\r
-      throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS);\r
-    }\r
-*/\r
-    CreateRPN();\r
-\r
-    int i = 0;\r
-\r
-#ifdef MUP_USE_OPENMP\r
-//#define DEBUG_OMP_STUFF\r
-    #ifdef DEBUG_OMP_STUFF\r
-    int *pThread = new int[nBulkSize];\r
-    int *pIdx = new int[nBulkSize];\r
-    #endif\r
-\r
-    int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);\r
-       int nThreadID = 0, ct = 0;\r
-    omp_set_num_threads(nMaxThreads);\r
-\r
-    #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)\r
-    for (i=0; i<nBulkSize; ++i)\r
-    {\r
-      nThreadID = omp_get_thread_num();\r
-      results[i] = ParseCmdCodeBulk(i, nThreadID);\r
-\r
-      #ifdef DEBUG_OMP_STUFF\r
-      #pragma omp critical\r
-      {\r
-        pThread[ct] = nThreadID;  \r
-        pIdx[ct] = i; \r
-        ct++;\r
-      }\r
-      #endif\r
-    }\r
-\r
-#ifdef DEBUG_OMP_STUFF\r
-    FILE *pFile = fopen("bulk_dbg.txt", "w");\r
-    for (i=0; i<nBulkSize; ++i)\r
-    {\r
-      fprintf(pFile, "idx: %d  thread: %d \n", pIdx[i], pThread[i]);\r
-    }\r
-    \r
-    delete [] pIdx;\r
-    delete [] pThread;\r
-\r
-    fclose(pFile);\r
-#endif\r
-\r
-#else\r
-    for (i=0; i<nBulkSize; ++i)\r
-    {\r
-      results[i] = ParseCmdCodeBulk(i, 0);\r
-    }\r
-#endif\r
-\r
-  }\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserBytecode.cpp b/bundled/muparser_v2_2_4/src/muParserBytecode.cpp
deleted file mode 100644 (file)
index 42c6ad0..0000000
+++ /dev/null
@@ -1,589 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#include "muParserBytecode.h"\r
-\r
-#include <algorithm>\r
-#include <cassert>\r
-#include <string>\r
-#include <stack>\r
-#include <vector>\r
-#include <iostream>\r
-\r
-#include "muParserDef.h"\r
-#include "muParserError.h"\r
-#include "muParserToken.h"\r
-#include "muParserStack.h"\r
-#include "muParserTemplateMagic.h"\r
-\r
-\r
-namespace mu\r
-{\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Bytecode default constructor. */\r
-  ParserByteCode::ParserByteCode()\r
-    :m_iStackPos(0)\r
-    ,m_iMaxStackSize(0)\r
-    ,m_vRPN()\r
-    ,m_bEnableOptimizer(true)\r
-  {\r
-    m_vRPN.reserve(50);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy constructor. \r
-    \r
-      Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
-  */\r
-  ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)\r
-  {\r
-    Assign(a_ByteCode);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Assignment operator.\r
-    \r
-      Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
-  */\r
-  ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)\r
-  {\r
-    Assign(a_ByteCode);\r
-    return *this;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserByteCode::EnableOptimizer(bool bStat)\r
-  {\r
-    m_bEnableOptimizer = bStat;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy state of another object to this. \r
-    \r
-      \throw nowthrow\r
-  */\r
-  void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)\r
-  {\r
-    if (this==&a_ByteCode)    \r
-      return;\r
-\r
-    m_iStackPos = a_ByteCode.m_iStackPos;\r
-    m_vRPN = a_ByteCode.m_vRPN;\r
-    m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;\r
-       m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a Variable pointer to bytecode. \r
-      \param a_pVar Pointer to be added.\r
-      \throw nothrow\r
-  */\r
-  void ParserByteCode::AddVar(value_type *a_pVar)\r
-  {\r
-    ++m_iStackPos;\r
-    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
-\r
-    // optimization does not apply\r
-    SToken tok;\r
-    tok.Cmd       = cmVAR;\r
-    tok.u.Val.ptr   = a_pVar;\r
-    tok.u.Val.data  = 1;\r
-    tok.u.Val.data2 = 0;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a Variable pointer to bytecode. \r
-\r
-      Value entries in byte code consist of:\r
-      <ul>\r
-        <li>value array position of the value</li>\r
-        <li>the operator code according to ParserToken::cmVAL</li>\r
-        <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>\r
-      </ul>\r
-\r
-      \param a_pVal Value to be added.\r
-      \throw nothrow\r
-  */\r
-  void ParserByteCode::AddVal(value_type a_fVal)\r
-  {\r
-    ++m_iStackPos;\r
-    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
-\r
-    // If optimization does not apply\r
-    SToken tok;\r
-    tok.Cmd = cmVAL;\r
-    tok.u.Val.ptr   = NULL;\r
-    tok.u.Val.data  = 0;\r
-    tok.u.Val.data2 = a_fVal;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)\r
-  {\r
-    std::size_t sz = m_vRPN.size();\r
-    value_type &x = m_vRPN[sz-2].u.Val.data2,\r
-               &y = m_vRPN[sz-1].u.Val.data2;\r
-    switch (a_Oprt)\r
-    {\r
-    case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;\r
-    case cmLOR:  x = (int)x || (int)y; m_vRPN.pop_back(); break;\r
-    case cmLT:   x = x < y;  m_vRPN.pop_back();  break;\r
-    case cmGT:   x = x > y;  m_vRPN.pop_back();  break;\r
-    case cmLE:   x = x <= y; m_vRPN.pop_back();  break;\r
-    case cmGE:   x = x >= y; m_vRPN.pop_back();  break;\r
-    case cmNEQ:  x = x != y; m_vRPN.pop_back();  break;\r
-    case cmEQ:   x = x == y; m_vRPN.pop_back();  break;\r
-    case cmADD:  x = x + y;  m_vRPN.pop_back();  break;\r
-    case cmSUB:  x = x - y;  m_vRPN.pop_back();  break;\r
-    case cmMUL:  x = x * y;  m_vRPN.pop_back();  break;\r
-    case cmDIV: \r
-\r
-#if defined(MUP_MATH_EXCEPTIONS)\r
-        if (y==0)\r
-          throw ParserError(ecDIV_BY_ZERO, _T("0"));\r
-#endif\r
-\r
-        x = x / y;   \r
-        m_vRPN.pop_back();\r
-        break;\r
-\r
-    case cmPOW: x = MathImpl<value_type>::Pow(x, y); \r
-                m_vRPN.pop_back();\r
-                break;\r
-\r
-    default:\r
-        break;\r
-    } // switch opcode\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add an operator identifier to bytecode. \r
-    \r
-      Operator entries in byte code consist of:\r
-      <ul>\r
-        <li>value array position of the result</li>\r
-        <li>the operator code according to ParserToken::ECmdCode</li>\r
-      </ul>\r
-\r
-      \sa  ParserToken::ECmdCode\r
-  */\r
-  void ParserByteCode::AddOp(ECmdCode a_Oprt)\r
-  {\r
-    bool bOptimized = false;\r
-\r
-    if (m_bEnableOptimizer)\r
-    {\r
-      std::size_t sz = m_vRPN.size();\r
-\r
-      // Check for foldable constants like:\r
-      //   cmVAL cmVAL cmADD \r
-      // where cmADD can stand fopr any binary operator applied to\r
-      // two constant values.\r
-      if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)\r
-      {\r
-        ConstantFolding(a_Oprt);\r
-        bOptimized = true;\r
-      }\r
-      else\r
-      {\r
-        switch(a_Oprt)\r
-        {\r
-        case  cmPOW:\r
-              // Optimization for ploynomials of low order\r
-              if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)\r
-              {\r
-                if (m_vRPN[sz-1].u.Val.data2==2)\r
-                  m_vRPN[sz-2].Cmd = cmVARPOW2;\r
-                else if (m_vRPN[sz-1].u.Val.data2==3)\r
-                  m_vRPN[sz-2].Cmd = cmVARPOW3;\r
-                else if (m_vRPN[sz-1].u.Val.data2==4)\r
-                  m_vRPN[sz-2].Cmd = cmVARPOW4;\r
-                else\r
-                  break;\r
-\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              }\r
-              break;\r
-\r
-        case  cmSUB:\r
-        case  cmADD:\r
-              // Simple optimization based on pattern recognition for a shitload of different\r
-              // bytecode combinations of addition/subtraction\r
-              if ( (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVAL)    ||\r
-                   (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVAR)    || \r
-                   (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
-                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL)    ||\r
-                   (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVAR    && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
-                   (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
-                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR    && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
-                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) )\r
-              {\r
-                assert( (m_vRPN[sz-2].u.Val.ptr==NULL && m_vRPN[sz-1].u.Val.ptr!=NULL) ||\r
-                        (m_vRPN[sz-2].u.Val.ptr!=NULL && m_vRPN[sz-1].u.Val.ptr==NULL) || \r
-                        (m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) );\r
-\r
-                m_vRPN[sz-2].Cmd = cmVARMUL;\r
-                m_vRPN[sz-2].u.Val.ptr    = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));    // variable\r
-                m_vRPN[sz-2].u.Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data2;  // offset\r
-                m_vRPN[sz-2].u.Val.data  += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data;   // multiplikatior\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              } \r
-              break;\r
-\r
-        case  cmMUL:\r
-              if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||\r
-                   (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) \r
-              {\r
-                m_vRPN[sz-2].Cmd        = cmVARMUL;\r
-                m_vRPN[sz-2].u.Val.ptr    = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
-                m_vRPN[sz-2].u.Val.data   = m_vRPN[sz-2].u.Val.data2 + m_vRPN[sz-1].u.Val.data2;\r
-                m_vRPN[sz-2].u.Val.data2  = 0;\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              } \r
-              else if ( (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
-                        (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )\r
-              {\r
-                // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2\r
-                m_vRPN[sz-2].Cmd     = cmVARMUL;\r
-                m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
-                if (m_vRPN[sz-1].Cmd == cmVAL)\r
-                {\r
-                  m_vRPN[sz-2].u.Val.data  *= m_vRPN[sz-1].u.Val.data2;\r
-                  m_vRPN[sz-2].u.Val.data2 *= m_vRPN[sz-1].u.Val.data2;\r
-                }\r
-                else\r
-                {\r
-                  m_vRPN[sz-2].u.Val.data  = m_vRPN[sz-1].u.Val.data  * m_vRPN[sz-2].u.Val.data2;\r
-                  m_vRPN[sz-2].u.Val.data2 = m_vRPN[sz-1].u.Val.data2 * m_vRPN[sz-2].u.Val.data2;\r
-                }\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              }\r
-              else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&\r
-                       m_vRPN[sz-1].u.Val.ptr == m_vRPN[sz-2].u.Val.ptr)\r
-              {\r
-                // Optimization: a*a -> a^2\r
-                m_vRPN[sz-2].Cmd = cmVARPOW2;\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              }\r
-              break;\r
-\r
-        case cmDIV:\r
-              if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].u.Val.data2!=0)\r
-              {\r
-                // Optimization: 4*a/2 -> 2*a\r
-                m_vRPN[sz-2].u.Val.data  /= m_vRPN[sz-1].u.Val.data2;\r
-                m_vRPN[sz-2].u.Val.data2 /= m_vRPN[sz-1].u.Val.data2;\r
-                m_vRPN.pop_back();\r
-                bOptimized = true;\r
-              }\r
-              break;\r
-        default:\r
-              break;\r
-        } // switch a_Oprt\r
-      }\r
-    }\r
-\r
-    // If optimization can't be applied just write the value\r
-    if (!bOptimized)\r
-    {\r
-      --m_iStackPos;\r
-      SToken tok;\r
-      tok.Cmd = a_Oprt;\r
-      m_vRPN.push_back(tok);\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserByteCode::AddIfElse(ECmdCode a_Oprt)\r
-  {\r
-    SToken tok;\r
-    tok.Cmd = a_Oprt;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add an assignement operator\r
-    \r
-      Operator entries in byte code consist of:\r
-      <ul>\r
-        <li>cmASSIGN code</li>\r
-        <li>the pointer of the destination variable</li>\r
-      </ul>\r
-\r
-      \sa  ParserToken::ECmdCode\r
-  */\r
-  void ParserByteCode::AddAssignOp(value_type *a_pVar)\r
-  {\r
-    --m_iStackPos;\r
-\r
-    SToken tok;\r
-    tok.Cmd = cmASSIGN;\r
-    tok.u.Oprt.ptr = a_pVar;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add function to bytecode. \r
-\r
-      \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
-      \param a_pFun Pointer to function callback.\r
-  */\r
-  void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)\r
-  {\r
-    if (a_iArgc>=0)\r
-    {\r
-      m_iStackPos = m_iStackPos - a_iArgc + 1; \r
-    }\r
-    else\r
-    {\r
-      // function with unlimited number of arguments\r
-      m_iStackPos = m_iStackPos + a_iArgc + 1; \r
-    }\r
-    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
-\r
-    SToken tok;\r
-    tok.Cmd = cmFUNC;\r
-    tok.u.Fun.argc = a_iArgc;\r
-    tok.u.Fun.ptr = a_pFun;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add a bulk function to bytecode. \r
-\r
-      \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
-      \param a_pFun Pointer to function callback.\r
-  */\r
-  void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)\r
-  {\r
-    m_iStackPos = m_iStackPos - a_iArgc + 1; \r
-    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
-\r
-    SToken tok;\r
-    tok.Cmd = cmFUNC_BULK;\r
-    tok.u.Fun.argc = a_iArgc;\r
-    tok.u.Fun.ptr = a_pFun;\r
-    m_vRPN.push_back(tok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add Strung function entry to the parser bytecode. \r
-      \throw nothrow\r
-\r
-      A string function entry consists of the stack position of the return value,\r
-      followed by a cmSTRFUNC code, the function pointer and an index into the \r
-      string buffer maintained by the parser.\r
-  */\r
-  void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)\r
-  {\r
-    m_iStackPos = m_iStackPos - a_iArgc + 1;\r
-\r
-    SToken tok;\r
-    tok.Cmd = cmFUNC_STR;\r
-    tok.u.Fun.argc = a_iArgc;\r
-    tok.u.Fun.idx = a_iIdx;\r
-    tok.u.Fun.ptr = a_pFun;\r
-    m_vRPN.push_back(tok);\r
-\r
-    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Add end marker to bytecode.\r
-      \r
-      \throw nothrow \r
-  */\r
-  void ParserByteCode::Finalize()\r
-  {\r
-    SToken tok;\r
-    tok.Cmd = cmEND;\r
-    m_vRPN.push_back(tok);\r
-    rpn_type(m_vRPN).swap(m_vRPN);     // shrink bytecode vector to fit\r
-\r
-    // Determine the if-then-else jump offsets\r
-    ParserStack<int> stIf, stElse;\r
-    int idx;\r
-    for (int i=0; i<(int)m_vRPN.size(); ++i)\r
-    {\r
-      switch(m_vRPN[i].Cmd)\r
-      {\r
-      case cmIF:\r
-            stIf.push(i);\r
-            break;\r
-\r
-      case  cmELSE:\r
-            stElse.push(i);\r
-            idx = stIf.pop();\r
-            m_vRPN[idx].u.Oprt.offset = i - idx;\r
-            break;\r
-      \r
-      case cmENDIF:\r
-            idx = stElse.pop();\r
-            m_vRPN[idx].u.Oprt.offset = i - idx;\r
-            break;\r
-\r
-      default:\r
-            break;\r
-      }\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  const SToken* ParserByteCode::GetBase() const\r
-  {\r
-    if (m_vRPN.size()==0)\r
-      throw ParserError(ecINTERNAL_ERROR);\r
-    else\r
-      return &m_vRPN[0];\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  std::size_t ParserByteCode::GetMaxStackSize() const\r
-  {\r
-    return m_iMaxStackSize+1;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Returns the number of entries in the bytecode. */\r
-  std::size_t ParserByteCode::GetSize() const\r
-  {\r
-    return m_vRPN.size();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Delete the bytecode. \r
-  \r
-      \throw nothrow\r
-\r
-      The name of this function is a violation of my own coding guidelines\r
-      but this way it's more in line with the STL functions thus more \r
-      intuitive.\r
-  */\r
-  void ParserByteCode::clear()\r
-  {\r
-    m_vRPN.clear();\r
-    m_iStackPos = 0;\r
-    m_iMaxStackSize = 0;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Dump bytecode (for debugging only!). */\r
-  void ParserByteCode::AsciiDump()\r
-  {\r
-    if (!m_vRPN.size()) \r
-    {\r
-      mu::console() << _T("No bytecode available\n");\r
-      return;\r
-    }\r
-\r
-    mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");\r
-    for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)\r
-    {\r
-      mu::console() << std::dec << i << _T(" : \t");\r
-      switch (m_vRPN[i].Cmd)\r
-      {\r
-      case cmVAL:   mu::console() << _T("VAL \t");\r
-                    mu::console() << _T("[") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
-                    break;\r
-\r
-      case cmVAR:   mu::console() << _T("VAR \t");\r
-                         mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
-                    break;\r
-\r
-      case cmVARPOW2: mu::console() << _T("VARPOW2 \t");\r
-                           mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
-                      break;\r
-\r
-      case cmVARPOW3: mu::console() << _T("VARPOW3 \t");\r
-                           mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
-                      break;\r
-\r
-      case cmVARPOW4: mu::console() << _T("VARPOW4 \t");\r
-                           mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
-                      break;\r
-\r
-      case cmVARMUL:  mu::console() << _T("VARMUL \t");\r
-                           mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]"); \r
-                      mu::console() << _T(" * [") << m_vRPN[i].u.Val.data << _T("]");\r
-                      mu::console() << _T(" + [") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
-                      break;\r
-\r
-      case cmFUNC:  mu::console() << _T("CALL\t");\r
-                    mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]"); \r
-                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Fun.ptr << _T("]"); \r
-                    mu::console() << _T("\n");\r
-                    break;\r
-\r
-      case cmFUNC_STR:\r
-                    mu::console() << _T("CALL STRFUNC\t");\r
-                    mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]");\r
-                    mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].u.Fun.idx << _T("]");\r
-                    mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Fun.ptr << _T("]\n"); \r
-                    break;\r
-\r
-      case cmLT:    mu::console() << _T("LT\n");  break;\r
-      case cmGT:    mu::console() << _T("GT\n");  break;\r
-      case cmLE:    mu::console() << _T("LE\n");  break;\r
-      case cmGE:    mu::console() << _T("GE\n");  break;\r
-      case cmEQ:    mu::console() << _T("EQ\n");  break;\r
-      case cmNEQ:   mu::console() << _T("NEQ\n"); break;\r
-      case cmADD:   mu::console() << _T("ADD\n"); break;\r
-      case cmLAND:  mu::console() << _T("&&\n"); break;\r
-      case cmLOR:   mu::console() << _T("||\n"); break;\r
-      case cmSUB:   mu::console() << _T("SUB\n"); break;\r
-      case cmMUL:   mu::console() << _T("MUL\n"); break;\r
-      case cmDIV:   mu::console() << _T("DIV\n"); break;\r
-      case cmPOW:   mu::console() << _T("POW\n"); break;\r
-\r
-      case cmIF:    mu::console() << _T("IF\t");\r
-                    mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
-                    break;\r
-\r
-      case cmELSE:  mu::console() << _T("ELSE\t");\r
-                    mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
-                    break;\r
-\r
-      case cmENDIF: mu::console() << _T("ENDIF\n"); break;\r
-\r
-      case cmASSIGN: \r
-                    mu::console() << _T("ASSIGN\t");\r
-                    mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Oprt.ptr << _T("]\n"); \r
-                    break; \r
-\r
-      default:      mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); \r
-                    break;\r
-      } // switch cmdCode\r
-    } // while bytecode\r
-\r
-    mu::console() << _T("END") << std::endl;\r
-  }\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserCallback.cpp b/bundled/muparser_v2_2_4/src/muParserCallback.cpp
deleted file mode 100644 (file)
index 9baa91d..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2004-2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#include "muParserCallback.h"\r
-\r
-/** \file\r
-    \brief Implementation of the parser callback class.\r
-*/\r
-\r
-\r
-namespace mu\r
-{\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(0)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(1)\r
-    ,m_iPri(a_iPrec)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(a_iCode)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
-      \throw nothrow\r
-  */\r
-  ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(2)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Constructor for constructing binary operator callbacks. \r
-      \param a_pFun Pointer to a static function taking two arguments\r
-      \param a_bAllowOpti A flag indicating this funcation can be optimized\r
-      \param a_iPrec The operator precedence\r
-      \param a_eOprtAsct The operators associativity\r
-      \throw nothrow\r
-  */\r
-  ParserCallback::ParserCallback(fun_type2 a_pFun, \r
-                                 bool a_bAllowOpti, \r
-                                 int a_iPrec, \r
-                                 EOprtAssociativity a_eOprtAsct)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(2)\r
-    ,m_iPri(a_iPrec)\r
-    ,m_eOprtAsct(a_eOprtAsct)\r
-    ,m_iCode(cmOPRT_BIN)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(3)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(4)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(5)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(6)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(7)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(8)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(9)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(10)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(0)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(1)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
-      \throw nothrow\r
-  */\r
-  ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(2)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(3)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(4)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(5)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(6)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(7)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(8)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(9)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(10)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_BULK)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(-1)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC)\r
-    ,m_iType(tpDBL)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(0)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_STR)\r
-    ,m_iType(tpSTR)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(1)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_STR)\r
-    ,m_iType(tpSTR)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)\r
-    :m_pFun((void*)a_pFun)\r
-    ,m_iArgc(2)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmFUNC_STR)\r
-    ,m_iType(tpSTR)\r
-    ,m_bAllowOpti(a_bAllowOpti)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Default constructor. \r
-      \throw nothrow\r
-  */\r
-  ParserCallback::ParserCallback()\r
-    :m_pFun(0)\r
-    ,m_iArgc(0)\r
-    ,m_iPri(-1)\r
-    ,m_eOprtAsct(oaNONE)\r
-    ,m_iCode(cmUNKNOWN)\r
-    ,m_iType(tpVOID)\r
-    ,m_bAllowOpti(0)\r
-  {}\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy constructor. \r
-      \throw nothrow\r
-  */\r
-  ParserCallback::ParserCallback(const ParserCallback &ref)\r
-  {\r
-    m_pFun       = ref.m_pFun;\r
-    m_iArgc      = ref.m_iArgc;\r
-    m_bAllowOpti = ref.m_bAllowOpti;\r
-    m_iCode      = ref.m_iCode;\r
-    m_iType      = ref.m_iType;\r
-    m_iPri       = ref.m_iPri;\r
-    m_eOprtAsct  = ref.m_eOprtAsct;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Clone this instance and return a pointer to the new instance. */\r
-  ParserCallback* ParserCallback::Clone() const\r
-  {\r
-    return new ParserCallback(*this);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return tru if the function is conservative.\r
-\r
-      Conservative functions return always the same result for the same argument.\r
-      \throw nothrow\r
-  */\r
-  bool ParserCallback::IsOptimizable() const  \r
-  { \r
-    return m_bAllowOpti; \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Get the callback address for the parser function. \r
-  \r
-      The type of the address is void. It needs to be recasted according to the\r
-      argument number to the right type.\r
-\r
-      \throw nothrow\r
-      \return #pFun\r
-  */\r
-  void* ParserCallback::GetAddr() const \r
-  { \r
-    return m_pFun;  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return the callback code. */\r
-  ECmdCode  ParserCallback::GetCode() const \r
-  { \r
-    return m_iCode; \r
-  }\r
-  \r
-  //---------------------------------------------------------------------------\r
-  ETypeCode ParserCallback::GetType() const \r
-  { \r
-    return m_iType; \r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return the operator precedence. \r
-      \throw nothrown\r
-\r
-     Only valid if the callback token is an operator token (binary or infix).\r
-  */\r
-  int ParserCallback::GetPri()  const \r
-  { \r
-    return m_iPri;  \r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return the operators associativity. \r
-      \throw nothrown\r
-\r
-     Only valid if the callback token is a binary operator token.\r
-  */\r
-  EOprtAssociativity ParserCallback::GetAssociativity() const\r
-  {\r
-    return m_eOprtAsct;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Returns the number of function Arguments. */\r
-  int ParserCallback::GetArgc() const \r
-  { \r
-    return m_iArgc; \r
-  }\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserError.cpp b/bundled/muparser_v2_2_4/src/muParserError.cpp
deleted file mode 100644 (file)
index e1ac721..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#include "muParserError.h"\r
-\r
-\r
-namespace mu\r
-{\r
-  const ParserErrorMsg ParserErrorMsg::m_Instance;\r
-\r
-  //------------------------------------------------------------------------------\r
-  const ParserErrorMsg& ParserErrorMsg::Instance()\r
-  {\r
-    return m_Instance;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  string_type ParserErrorMsg::operator[](unsigned a_iIdx) const\r
-  {\r
-    return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserErrorMsg::~ParserErrorMsg()\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Assignement operator is deactivated.\r
-  */\r
-  ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )\r
-  {\r
-    assert(false);\r
-    return *this;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)\r
-  {}\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserErrorMsg::ParserErrorMsg()\r
-    :m_vErrMsg(0)\r
-  {\r
-    m_vErrMsg.resize(ecCOUNT);\r
-\r
-    m_vErrMsg[ecUNASSIGNABLE_TOKEN]     = _T("Unexpected token \"$TOK$\" found at position $POS$.");\r
-    m_vErrMsg[ecINTERNAL_ERROR]         = _T("Internal error");\r
-    m_vErrMsg[ecINVALID_NAME]           = _T("Invalid function-, variable- or constant name: \"$TOK$\".");\r
-    m_vErrMsg[ecINVALID_BINOP_IDENT]    = _T("Invalid binary operator identifier: \"$TOK$\".");\r
-    m_vErrMsg[ecINVALID_INFIX_IDENT]    = _T("Invalid infix operator identifier: \"$TOK$\".");\r
-    m_vErrMsg[ecINVALID_POSTFIX_IDENT]  = _T("Invalid postfix operator identifier: \"$TOK$\".");\r
-    m_vErrMsg[ecINVALID_FUN_PTR]        = _T("Invalid pointer to callback function.");\r
-    m_vErrMsg[ecEMPTY_EXPRESSION]       = _T("Expression is empty.");\r
-    m_vErrMsg[ecINVALID_VAR_PTR]        = _T("Invalid pointer to variable.");\r
-    m_vErrMsg[ecUNEXPECTED_OPERATOR]    = _T("Unexpected operator \"$TOK$\" found at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_EOF]         = _T("Unexpected end of expression at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_ARG_SEP]     = _T("Unexpected argument separator at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_PARENS]      = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_FUN]         = _T("Unexpected function \"$TOK$\" at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_VAL]         = _T("Unexpected value \"$TOK$\" found at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_VAR]         = _T("Unexpected variable \"$TOK$\" found at position $POS$");\r
-    m_vErrMsg[ecUNEXPECTED_ARG]         = _T("Function arguments used without a function (position: $POS$)");\r
-    m_vErrMsg[ecMISSING_PARENS]         = _T("Missing parenthesis");\r
-    m_vErrMsg[ecTOO_MANY_PARAMS]        = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");\r
-    m_vErrMsg[ecTOO_FEW_PARAMS]         = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");\r
-    m_vErrMsg[ecDIV_BY_ZERO]            = _T("Divide by zero");\r
-    m_vErrMsg[ecDOMAIN_ERROR]           = _T("Domain error");\r
-    m_vErrMsg[ecNAME_CONFLICT]          = _T("Name conflict");\r
-    m_vErrMsg[ecOPT_PRI]                = _T("Invalid value for operator priority (must be greater or equal to zero).");\r
-    m_vErrMsg[ecBUILTIN_OVERLOAD]       = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");\r
-    m_vErrMsg[ecUNEXPECTED_STR]         = _T("Unexpected string token found at position $POS$.");\r
-    m_vErrMsg[ecUNTERMINATED_STRING]    = _T("Unterminated string starting at position $POS$.");\r
-    m_vErrMsg[ecSTRING_EXPECTED]        = _T("String function called with a non string type of argument.");\r
-    m_vErrMsg[ecVAL_EXPECTED]           = _T("String value used where a numerical argument is expected.");\r
-    m_vErrMsg[ecOPRT_TYPE_CONFLICT]     = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");\r
-    m_vErrMsg[ecSTR_RESULT]             = _T("Function result is a string.");\r
-    m_vErrMsg[ecGENERIC]                = _T("Parser error.");\r
-    m_vErrMsg[ecLOCALE]                 = _T("Decimal separator is identic to function argument separator.");\r
-    m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket.");\r
-    m_vErrMsg[ecMISSING_ELSE_CLAUSE]    = _T("If-then-else operator is missing an else clause");\r
-    m_vErrMsg[ecMISPLACED_COLON]        = _T("Misplaced colon at position $POS$");\r
-    m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)");\r
-    \r
-    #if defined(_DEBUG)\r
-      for (int i=0; i<ecCOUNT; ++i)\r
-        if (!m_vErrMsg[i].length())\r
-          assert(false);\r
-    #endif\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  //\r
-  //  ParserError class\r
-  //\r
-  //---------------------------------------------------------------------------\r
-\r
-  /** \brief Default constructor. */\r
-  ParserError::ParserError()\r
-    :m_strMsg()\r
-    ,m_strFormula()\r
-    ,m_strTok()\r
-    ,m_iPos(-1)\r
-    ,m_iErrc(ecUNDEFINED)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief This Constructor is used for internal exceptions only. \r
-      \r
-    It does not contain any information but the error code.\r
-  */\r
-  ParserError::ParserError(EErrorCodes a_iErrc) \r
-    :m_strMsg()\r
-    ,m_strFormula()\r
-    ,m_strTok()\r
-    ,m_iPos(-1)\r
-    ,m_iErrc(a_iErrc)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-    m_strMsg = m_ErrMsg[m_iErrc];\r
-    stringstream_type stream;\r
-    stream << (int)m_iPos;\r
-    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
-    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Construct an error from a message text. */\r
-  ParserError::ParserError(const string_type &sMsg) \r
-    :m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-    Reset();\r
-    m_strMsg = sMsg;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Construct an error object. \r
-      \param [in] a_iErrc the error code.\r
-      \param [in] sTok The token string related to this error.\r
-      \param [in] sExpr The expression related to the error.\r
-      \param [in] a_iPos the position in the expression where the error occured. \r
-  */\r
-  ParserError::ParserError( EErrorCodes iErrc,\r
-                            const string_type &sTok,\r
-                            const string_type &sExpr,\r
-                            int iPos )\r
-    :m_strMsg()\r
-    ,m_strFormula(sExpr)\r
-    ,m_strTok(sTok)\r
-    ,m_iPos(iPos)\r
-    ,m_iErrc(iErrc)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-    m_strMsg = m_ErrMsg[m_iErrc];\r
-    stringstream_type stream;\r
-    stream << (int)m_iPos;\r
-    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
-    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Construct an error object. \r
-      \param [in] iErrc the error code.\r
-      \param [in] iPos the position in the expression where the error occured. \r
-      \param [in] sTok The token string related to this error.\r
-  */\r
-  ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) \r
-    :m_strMsg()\r
-    ,m_strFormula()\r
-    ,m_strTok(sTok)\r
-    ,m_iPos(iPos)\r
-    ,m_iErrc(iErrc)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-    m_strMsg = m_ErrMsg[m_iErrc];\r
-    stringstream_type stream;\r
-    stream << (int)m_iPos;\r
-    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
-    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Construct an error object. \r
-      \param [in] szMsg The error message text.\r
-      \param [in] iPos the position related to the error.\r
-      \param [in] sTok The token string related to this error.\r
-  */\r
-  ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) \r
-    :m_strMsg(szMsg)\r
-    ,m_strFormula()\r
-    ,m_strTok(sTok)\r
-    ,m_iPos(iPos)\r
-    ,m_iErrc(ecGENERIC)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-    stringstream_type stream;\r
-    stream << (int)m_iPos;\r
-    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
-    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Copy constructor. */\r
-  ParserError::ParserError(const ParserError &a_Obj)\r
-    :m_strMsg(a_Obj.m_strMsg)\r
-    ,m_strFormula(a_Obj.m_strFormula)\r
-    ,m_strTok(a_Obj.m_strTok)\r
-    ,m_iPos(a_Obj.m_iPos)\r
-    ,m_iErrc(a_Obj.m_iErrc)\r
-    ,m_ErrMsg(ParserErrorMsg::Instance())\r
-  {\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Assignment operator. */\r
-  ParserError& ParserError::operator=(const ParserError &a_Obj)\r
-  {\r
-    if (this==&a_Obj)\r
-      return *this;\r
-\r
-    m_strMsg = a_Obj.m_strMsg;\r
-    m_strFormula = a_Obj.m_strFormula;\r
-    m_strTok = a_Obj.m_strTok;\r
-    m_iPos = a_Obj.m_iPos;\r
-    m_iErrc = a_Obj.m_iErrc;\r
-    return *this;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  ParserError::~ParserError()\r
-  {}\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Replace all ocuurences of a substring with another string. \r
-      \param strFind The string that shall be replaced.\r
-      \param strReplaceWith The string that should be inserted instead of strFind\r
-  */\r
-  void ParserError::ReplaceSubString( string_type &strSource,\r
-                                      const string_type &strFind,\r
-                                      const string_type &strReplaceWith)\r
-  {\r
-    string_type strResult;\r
-    string_type::size_type iPos(0), iNext(0);\r
-\r
-    for(;;)\r
-    {\r
-      iNext = strSource.find(strFind, iPos);\r
-      strResult.append(strSource, iPos, iNext-iPos);\r
-\r
-      if( iNext==string_type::npos )\r
-        break;\r
-\r
-      strResult.append(strReplaceWith);\r
-      iPos = iNext + strFind.length();\r
-    } \r
-\r
-    strSource.swap(strResult);\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Reset the erro object. */\r
-  void ParserError::Reset()\r
-  {\r
-    m_strMsg = _T("");\r
-    m_strFormula = _T("");\r
-    m_strTok = _T("");\r
-    m_iPos = -1;\r
-    m_iErrc = ecUNDEFINED;\r
-  }\r
-      \r
-  //------------------------------------------------------------------------------\r
-  /** \brief Set the expression related to this error. */\r
-  void ParserError::SetFormula(const string_type &a_strFormula)\r
-  {\r
-    m_strFormula = a_strFormula;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief gets the expression related tp this error.*/\r
-  const string_type& ParserError::GetExpr() const \r
-  {\r
-    return m_strFormula;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Returns the message string for this error. */\r
-  const string_type& ParserError::GetMsg() const\r
-  {\r
-    return m_strMsg;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Return the formula position related to the error. \r
-\r
-    If the error is not related to a distinct position this will return -1\r
-  */\r
-  int ParserError::GetPos() const\r
-  {\r
-    return m_iPos;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Return string related with this token (if available). */\r
-  const string_type& ParserError::GetToken() const\r
-  {\r
-    return m_strTok;\r
-  }\r
-\r
-  //------------------------------------------------------------------------------\r
-  /** \brief Return the error code. */\r
-  EErrorCodes ParserError::GetCode() const\r
-  {\r
-    return m_iErrc;\r
-  }\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserInt.cpp b/bundled/muparser_v2_2_4/src/muParserInt.cpp
deleted file mode 100644 (file)
index fd377a8..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2011 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#include "muParserInt.h"\r
-\r
-#include <cmath>\r
-#include <algorithm>\r
-#include <numeric>\r
-\r
-using namespace std;\r
-\r
-/** \file\r
-    \brief Implementation of a parser using integer value.\r
-*/\r
-\r
-/** \brief Namespace for mathematical applications. */\r
-namespace mu\r
-{\r
-value_type ParserInt::Abs(value_type v)  { return (value_type)Round(fabs((double)v)); }\r
-value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }\r
-value_type ParserInt::Ite(value_type v1, \r
-                          value_type v2, \r
-                          value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }\r
-value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1)  + Round(v2); }\r
-value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1)  - Round(v2); }\r
-value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1)  * Round(v2); }\r
-value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1)  / Round(v2); }\r
-value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1)  % Round(v2); }\r
-value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }\r
-value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }\r
-value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }\r
-value_type ParserInt::LogOr(value_type v1, value_type v2)  { return Round(v1) | Round(v2); }\r
-value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }\r
-value_type ParserInt::Or(value_type v1, value_type v2)  { return Round(v1) || Round(v2); }\r
-value_type ParserInt::Less(value_type v1, value_type v2)      { return Round(v1)  < Round(v2); }\r
-value_type ParserInt::Greater(value_type v1, value_type v2)   { return Round(v1)  > Round(v2); }\r
-value_type ParserInt::LessEq(value_type v1, value_type v2)    { return Round(v1) <= Round(v2); }\r
-value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }\r
-value_type ParserInt::Equal(value_type v1, value_type v2)     { return Round(v1) == Round(v2); }\r
-value_type ParserInt::NotEqual(value_type v1, value_type v2)  { return Round(v1) != Round(v2); }\r
-value_type ParserInt::Not(value_type v) { return !Round(v); }\r
-\r
-value_type ParserInt::Pow(value_type v1, value_type v2) \r
-{ \r
-  return std::pow((double)Round(v1), (double)Round(v2)); \r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-// Unary operator Callbacks: Infix operators\r
-value_type ParserInt::UnaryMinus(value_type v) \r
-{ \r
-  return -Round(v); \r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)\r
-{ \r
-  if (!a_iArgc)        \r
-    throw ParserError(_T("too few arguments for function sum."));\r
-\r
-  value_type fRes=0;\r
-  for (int i=0; i<a_iArgc; ++i) \r
-    fRes += a_afArg[i];\r
-\r
-  return fRes;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)\r
-{ \r
-  if (!a_iArgc)        \r
-    throw ParserError( _T("too few arguments for function min.") );\r
-\r
-  value_type fRes=a_afArg[0];\r
-  for (int i=0; i<a_iArgc; ++i) \r
-    fRes = std::min(fRes, a_afArg[i]);\r
-\r
-  return fRes;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)\r
-{ \r
-  if (!a_iArgc)        \r
-    throw ParserError(_T("too few arguments for function min."));\r
-\r
-  value_type fRes=a_afArg[0];\r
-  for (int i=0; i<a_iArgc; ++i) \r
-    fRes = std::max(fRes, a_afArg[i]);\r
-\r
-  return fRes;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-// Default value recognition callback\r
-int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
-{\r
-  string_type buf(a_szExpr);\r
-  std::size_t pos = buf.find_first_not_of(_T("0123456789"));\r
-\r
-  if (pos==std::string::npos)\r
-    return 0;\r
-\r
-  stringstream_type stream( buf.substr(0, pos ) );\r
-  int iVal(0);\r
-\r
-  stream >> iVal;\r
-  if (stream.fail())\r
-    return 0;\r
-      \r
-  stringstream_type::pos_type iEnd = stream.tellg();   // Position after reading\r
-  if (stream.fail())\r
-    iEnd = stream.str().length();  \r
-\r
-  if (iEnd==(stringstream_type::pos_type)-1)\r
-    return 0;\r
-\r
-  *a_iPos += (int)iEnd;\r
-  *a_fVal = (value_type)iVal;\r
-  return 1;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief Check a given position in the expression for the presence of \r
-           a hex value. \r
-    \param a_szExpr Pointer to the expression string\r
-    \param [in/out] a_iPos Pointer to an interger value holding the current parsing \r
-           position in the expression.\r
-    \param [out] a_fVal Pointer to the position where the detected value shall be stored.\r
-\r
-  Hey values must be prefixed with "0x" in order to be detected properly.\r
-*/\r
-int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
-{\r
-  if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
-    return 0;\r
-\r
-  unsigned iVal(0);\r
-\r
-  // New code based on streams for UNICODE compliance:\r
-  stringstream_type::pos_type nPos(0);\r
-  stringstream_type ss(a_szExpr + 2);\r
-  ss >> std::hex >> iVal;\r
-  nPos = ss.tellg();\r
-\r
-  if (nPos==(stringstream_type::pos_type)0)\r
-    return 1;\r
-\r
-  *a_iPos += (int)(2 + nPos);\r
-  *a_fVal = (value_type)iVal;\r
-  return 1;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
-{\r
-  if (a_szExpr[0]!='#') \r
-    return 0;\r
-\r
-  unsigned iVal(0), \r
-           iBits(sizeof(iVal)*8),\r
-           i(0);\r
-\r
-  for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)\r
-    iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);\r
-\r
-  if (i==0) \r
-    return 0;\r
-\r
-  if (i==iBits)\r
-    throw exception_type(_T("Binary to integer conversion error (overflow)."));\r
-\r
-  *a_fVal = (unsigned)(iVal >> (iBits-i) );\r
-  *a_iPos += i+1;\r
-\r
-  return 1;\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief Constructor. \r
-\r
-  Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
-*/\r
-ParserInt::ParserInt()\r
-  :ParserBase()\r
-{\r
-  AddValIdent(IsVal);    // lowest priority\r
-  AddValIdent(IsBinVal);\r
-  AddValIdent(IsHexVal); // highest priority\r
-\r
-  InitCharSets();\r
-  InitFun();\r
-  InitOprt();\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-void ParserInt::InitConst()\r
-{\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-void ParserInt::InitCharSets()\r
-{\r
-  DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
-  DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );\r
-  DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief Initialize the default functions. */\r
-void ParserInt::InitFun()\r
-{\r
-  DefineFun( _T("sign"), Sign);\r
-  DefineFun( _T("abs"), Abs);\r
-  DefineFun( _T("if"), Ite);\r
-  DefineFun( _T("sum"), Sum);\r
-  DefineFun( _T("min"), Min);\r
-  DefineFun( _T("max"), Max);\r
-}\r
-\r
-//---------------------------------------------------------------------------\r
-/** \brief Initialize operators. */\r
-void ParserInt::InitOprt()\r
-{\r
-  // disable all built in operators, not all of them usefull for integer numbers\r
-  // (they don't do rounding of values)\r
-  EnableBuiltInOprt(false);\r
-\r
-  // Disable all built in operators, they wont work with integer numbers\r
-  // since they are designed for floating point numbers\r
-  DefineInfixOprt( _T("-"), UnaryMinus);\r
-  DefineInfixOprt( _T("!"), Not);\r
-\r
-  DefineOprt( _T("&"), LogAnd, prLOGIC);\r
-  DefineOprt( _T("|"), LogOr, prLOGIC);\r
-  DefineOprt( _T("&&"), And, prLOGIC);\r
-  DefineOprt( _T("||"), Or, prLOGIC);\r
-\r
-  DefineOprt( _T("<"), Less, prCMP);\r
-  DefineOprt( _T(">"), Greater, prCMP);\r
-  DefineOprt( _T("<="), LessEq, prCMP);\r
-  DefineOprt( _T(">="), GreaterEq, prCMP);\r
-  DefineOprt( _T("=="), Equal, prCMP);\r
-  DefineOprt( _T("!="), NotEqual, prCMP);\r
-\r
-  DefineOprt( _T("+"), Add, prADD_SUB);\r
-  DefineOprt( _T("-"), Sub, prADD_SUB);\r
-\r
-  DefineOprt( _T("*"), Mul, prMUL_DIV);\r
-  DefineOprt( _T("/"), Div, prMUL_DIV);\r
-  DefineOprt( _T("%"), Mod, prMUL_DIV);\r
-\r
-  DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);\r
-  DefineOprt( _T(">>"), Shr, prMUL_DIV+1);\r
-  DefineOprt( _T("<<"), Shl, prMUL_DIV+1);\r
-}\r
-\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserTest.cpp b/bundled/muparser_v2_2_4/src/muParserTest.cpp
deleted file mode 100644 (file)
index af2aa86..0000000
+++ /dev/null
@@ -1,1552 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-\r
-#include "muParserTest.h"\r
-\r
-#include <cstdio>\r
-#include <cmath>\r
-#include <iostream>\r
-#include <limits>\r
-\r
-#define PARSER_CONST_PI  3.141592653589793238462643\r
-#define PARSER_CONST_E   2.718281828459045235360287\r
-\r
-using namespace std;\r
-\r
-/** \file\r
-    \brief This file contains the implementation of parser test cases.\r
-*/\r
-\r
-namespace mu\r
-{\r
-  namespace Test\r
-  {\r
-    int ParserTester::c_iCount = 0;\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    ParserTester::ParserTester()\r
-      :m_vTestFun()\r
-    {\r
-      AddTest(&ParserTester::TestNames);\r
-      AddTest(&ParserTester::TestSyntax);\r
-      AddTest(&ParserTester::TestPostFix);\r
-      AddTest(&ParserTester::TestInfixOprt);\r
-      AddTest(&ParserTester::TestVarConst);\r
-      AddTest(&ParserTester::TestMultiArg);\r
-      AddTest(&ParserTester::TestExpression);\r
-      AddTest(&ParserTester::TestIfThenElse);\r
-      AddTest(&ParserTester::TestInterface);\r
-      AddTest(&ParserTester::TestBinOprt);\r
-      AddTest(&ParserTester::TestException);\r
-      AddTest(&ParserTester::TestStrArg);\r
-      AddTest(&ParserTester::TestBulkMode);\r
-\r
-      ParserTester::c_iCount = 0;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
-    {\r
-      if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
-        return 0;\r
-\r
-      unsigned iVal(0);\r
-\r
-      // New code based on streams for UNICODE compliance:\r
-      stringstream_type::pos_type nPos(0);\r
-      stringstream_type ss(a_szExpr + 2);\r
-      ss >> std::hex >> iVal;\r
-      nPos = ss.tellg();\r
-\r
-      if (nPos==(stringstream_type::pos_type)0)\r
-        return 1;\r
-\r
-      *a_iPos += (int)(2 + nPos);\r
-      *a_fVal = (value_type)iVal;\r
-      return 1;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    int ParserTester::TestInterface()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing member functions...");\r
-   \r
-      // Test RemoveVar\r
-      value_type afVal[3] = {1,2,3};\r
-      Parser p;\r
-  \r
-      try\r
-      {\r
-        p.DefineVar( _T("a"), &afVal[0]);\r
-        p.DefineVar( _T("b"), &afVal[1]);\r
-        p.DefineVar( _T("c"), &afVal[2]);\r
-        p.SetExpr( _T("a+b+c") );\r
-        p.Eval();\r
-      }\r
-      catch(...)\r
-      {\r
-        iStat += 1;  // this is not supposed to happen \r
-      }\r
-\r
-      try\r
-      {\r
-        p.RemoveVar( _T("c") );\r
-        p.Eval();\r
-        iStat += 1;  // not supposed to reach this, nonexisting variable "c" deleted...\r
-      }\r
-      catch(...)\r
-      {\r
-        // failure is expected...\r
-      }\r
-\r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    int ParserTester::TestStrArg()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing string arguments...");\r
\r
-      iStat += EqnTest(_T("valueof(\"\")"), 123, true);   // empty string arguments caused a crash\r
-      iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\")  "), 246, true);\r
-      iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);\r
-      // use in expressions with variables\r
-      iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);\r
-      iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);\r
-      // string + numeric arguments\r
-      iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);\r
-      iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);\r
-      iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);\r
-      // string constants\r
-      iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true);\r
-\r
-      if (iStat==0)\r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    int ParserTester::TestBulkMode()\r
-    {\r
-        int iStat = 0;\r
-        mu::console() << _T("testing bulkmode...");\r
-\r
-#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \\r
-        { \\r
-          double res[] = { R1, R2, R3, R4 }; \\r
-          iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \\r
-        }\r
-\r
-        // Bulk Variables for the test:\r
-        // a: 1,2,3,4\r
-        // b: 2,2,2,2\r
-        // c: 3,3,3,3\r
-        // d: 5,4,3,2\r
-        EQN_TEST_BULK("a",   1, 1, 1, 1, false)\r
-        EQN_TEST_BULK("a",   1, 2, 3, 4, true)\r
-        EQN_TEST_BULK("b=a", 1, 2, 3, 4, true)\r
-        EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true)\r
-        EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true)\r
-        EQN_TEST_BULK("a+b", 3, 4, 5, 6, true)\r
-        EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true)\r
-#undef EQN_TEST_BULK\r
-\r
-        if (iStat == 0)\r
-            mu::console() << _T("passed") << endl;\r
-        else\r
-            mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-        return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    int ParserTester::TestBinOprt()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing binary operators...");\r
-   \r
-      // built in operators\r
-      // xor operator\r
-\r
-      iStat += EqnTest(_T("a++b"), 3, true);\r
-      iStat += EqnTest(_T("a ++ b"), 3, true);\r
-      iStat += EqnTest(_T("1++2"), 3, true);\r
-      iStat += EqnTest(_T("1 ++ 2"), 3, true);\r
-      iStat += EqnTest(_T("a add b"), 3, true);\r
-      iStat += EqnTest(_T("1 add 2"), 3, true);\r
-      iStat += EqnTest(_T("a<b"), 1, true);\r
-      iStat += EqnTest(_T("b>a"), 1, true);\r
-      iStat += EqnTest(_T("a>a"), 0, true);\r
-      iStat += EqnTest(_T("a<a"), 0, true);\r
-      iStat += EqnTest(_T("a>a"), 0, true);\r
-      iStat += EqnTest(_T("a<=a"), 1, true);\r
-      iStat += EqnTest(_T("a<=b"), 1, true);\r
-      iStat += EqnTest(_T("b<=a"), 0, true);\r
-      iStat += EqnTest(_T("a>=a"), 1, true);\r
-      iStat += EqnTest(_T("b>=a"), 1, true);\r
-      iStat += EqnTest(_T("a>=b"), 0, true);\r
-\r
-      // Test logical operators, expecially if user defined "&" and the internal "&&" collide\r
-      iStat += EqnTest(_T("1 && 1"), 1, true); \r
-      iStat += EqnTest(_T("1 && 0"), 0, true); \r
-      iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true); \r
-      iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true); \r
-      //iStat += EqnTest(_T("12 and 255"), 12, true); \r
-      //iStat += EqnTest(_T("12 and 0"), 0, true); \r
-      iStat += EqnTest(_T("12 & 255"), 12, true); \r
-      iStat += EqnTest(_T("12 & 0"), 0, true); \r
-      iStat += EqnTest(_T("12&255"), 12, true); \r
-      iStat += EqnTest(_T("12&0"), 0, true); \r
-\r
-      // Assignement operator\r
-      iStat += EqnTest(_T("a = b"), 2, true); \r
-      iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); \r
-      iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);\r
-      iStat += EqnTest(_T("(a=b)*2"), 4, true);\r
-      iStat += EqnTest(_T("2*(a=b)"), 4, true);\r
-      iStat += EqnTest(_T("2*(a=b+1)"), 6, true);\r
-      iStat += EqnTest(_T("(a=b+1)*2"), 6, true);\r
-      iStat += EqnTest(_T("a=c, a*10"), 30, true);\r
-\r
-      iStat += EqnTest(_T("2^2^3"), 256, true); \r
-      iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); \r
-\r
-      // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3\r
-      iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); \r
-\r
-      // Test user defined binary operators\r
-      iStat += EqnTestInt(_T("1 | 2"), 3, true);          \r
-      iStat += EqnTestInt(_T("1 || 2"), 1, true);          \r
-      iStat += EqnTestInt(_T("123 & 456"), 72, true);          \r
-      iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);\r
-      iStat += EqnTestInt(_T("1 && 0"), 0, true);          \r
-      iStat += EqnTestInt(_T("123 && 456"), 1, true);          \r
-      iStat += EqnTestInt(_T("1 << 3"), 8, true);          \r
-      iStat += EqnTestInt(_T("8 >> 3"), 1, true);          \r
-      iStat += EqnTestInt(_T("9 / 4"), 2, true);  \r
-      iStat += EqnTestInt(_T("9 % 4"), 1, true);  \r
-      iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);\r
-      iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);\r
-      iStat += EqnTestInt(_T("-10+1"), -9, true);\r
-      iStat += EqnTestInt(_T("1+2*3"), 7, true);\r
-      iStat += EqnTestInt(_T("const1 != const2"), 1, true);\r
-      iStat += EqnTestInt(_T("const1 != const2"), 0, false);\r
-      iStat += EqnTestInt(_T("const1 == const2"), 0, true);\r
-      iStat += EqnTestInt(_T("const1 == 1"), 1, true);\r
-      iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);\r
-      iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);\r
-      iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);\r
-      iStat += EqnTestInt(_T("const1 < const2"), 1, true);\r
-      iStat += EqnTestInt(_T("const2 > const1"), 1, true);\r
-      iStat += EqnTestInt(_T("const1 <= 1"), 1, true);\r
-      iStat += EqnTestInt(_T("const2 >= 2"), 1, true);\r
-      iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);\r
-      iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);\r
-      iStat += EqnTestInt(_T("a != b"), 1, true);\r
-      iStat += EqnTestInt(_T("a != b"), 0, false);\r
-      iStat += EqnTestInt(_T("a == b"), 0, true);\r
-      iStat += EqnTestInt(_T("a == 1"), 1, true);\r
-      iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);\r
-      iStat += EqnTestInt(_T("2*(a | b)"), 6, true);\r
-      iStat += EqnTestInt(_T("2*(a | b)"), 7, false);\r
-      iStat += EqnTestInt(_T("a < b"), 1, true);\r
-      iStat += EqnTestInt(_T("b > a"), 1, true);\r
-      iStat += EqnTestInt(_T("a <= 1"), 1, true);\r
-      iStat += EqnTestInt(_T("b >= 2"), 1, true);\r
-      iStat += EqnTestInt(_T("2*(a + b)"), 6, true);\r
-      iStat += EqnTestInt(_T("2*(a - b)"), -2, true);\r
-      iStat += EqnTestInt(_T("a + (a << b)"), 5, true);\r
-      iStat += EqnTestInt(_T("-2^2"), -4, true);\r
-      iStat += EqnTestInt(_T("3--a"), 4, true);\r
-      iStat += EqnTestInt(_T("3+-3^2"), -6, true);\r
-\r
-      // Test reading of hex values:\r
-      iStat += EqnTestInt(_T("0xff"), 255, true);\r
-      iStat += EqnTestInt(_T("10+0xff"), 265, true);\r
-      iStat += EqnTestInt(_T("0xff+10"), 265, true);\r
-      iStat += EqnTestInt(_T("10*0xff"), 2550, true);\r
-      iStat += EqnTestInt(_T("0xff*10"), 2550, true);\r
-      iStat += EqnTestInt(_T("10+0xff+1"), 266, true);\r
-      iStat += EqnTestInt(_T("1+0xff+10"), 266, true);\r
-\r
-// incorrect: '^' is yor here, not power\r
-//    iStat += EqnTestInt("-(1+2)^2", -9, true);\r
-//    iStat += EqnTestInt("-1^3", -1, true);          \r
-\r
-      // Test precedence\r
-      // a=1, b=2, c=3\r
-      iStat += EqnTestInt(_T("a + b * c"), 7, true);\r
-      iStat += EqnTestInt(_T("a * b + c"), 5, true);\r
-      iStat += EqnTestInt(_T("a<b && b>10"), 0, true);\r
-      iStat += EqnTestInt(_T("a<b && b<10"), 1, true);\r
-\r
-      iStat += EqnTestInt(_T("a + b << c"), 17, true);\r
-      iStat += EqnTestInt(_T("a << b + c"), 7, true);\r
-      iStat += EqnTestInt(_T("c * b < a"), 0, true);\r
-      iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);\r
-      iStat += EqnTestInt(_T("2^2^3"), 256, true); \r
-\r
-\r
-      if (iStat==0)\r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------------------------\r
-    /** \brief Check muParser name restriction enforcement. */\r
-    int ParserTester::TestNames()\r
-    {\r
-      int  iStat= 0,\r
-           iErr = 0;\r
-\r
-      mu::console() << "testing name restriction enforcement...";\r
-    \r
-      Parser p;\r
-\r
-  #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \\r
-      iErr = 0;                                      \\r
-      ParserTester::c_iCount++;                      \\r
-      try                                            \\r
-      {                                              \\r
-        p.Define##DOMAIN(EXPR, ARG);                 \\r
-      }                                              \\r
-      catch(Parser::exception_type&)                 \\r
-      {                                              \\r
-        iErr = (FAIL==false) ? 0 : 1;                \\r
-      }                                              \\r
-      iStat += iErr;      \r
-      \r
-      // constant names\r
-      PARSER_THROWCHECK(Const, false, _T("0a"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("9a"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("+a"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("-a"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("a-"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("a*"), 1)\r
-      PARSER_THROWCHECK(Const, false, _T("a?"), 1)\r
-      PARSER_THROWCHECK(Const, true, _T("a"), 1)\r
-      PARSER_THROWCHECK(Const, true, _T("a_min"), 1)\r
-      PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)\r
-      PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)\r
-      // variable names\r
-      value_type a;\r
-      p.ClearConst();\r
-      PARSER_THROWCHECK(Var, false, _T("123abc"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("9a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("0a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("+a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("-a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("?a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("!a"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("a+"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("a-"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("a*"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("a?"), &a)\r
-      PARSER_THROWCHECK(Var, true, _T("a"), &a)\r
-      PARSER_THROWCHECK(Var, true, _T("a_min"), &a)\r
-      PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)\r
-      PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)\r
-      PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)\r
-      // Postfix operators\r
-      // fail\r
-      PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)\r
-      // pass\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("-a"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("?a"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("_"),   f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("#"),   f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("&&"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("||"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("&"),   f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("|"),   f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("++"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("--"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("?>"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("?<"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("**"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("or"),  f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)\r
-      PARSER_THROWCHECK(PostfixOprt, true, _T("!"),   f1of1)\r
-      // Binary operator\r
-      // The following must fail with builtin operators activated\r
-      // p.EnableBuiltInOp(true); -> this is the default\r
-      p.ClearPostfixOprt();\r
-      PARSER_THROWCHECK(Oprt, false, _T("+"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("-"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("*"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("/"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("^"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("&&"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, false, _T("||"),  f1of2)\r
-      // without activated built in operators it should work\r
-      p.EnableBuiltInOprt(false);\r
-      PARSER_THROWCHECK(Oprt, true, _T("+"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("-"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("*"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("/"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("^"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("&&"),  f1of2)\r
-      PARSER_THROWCHECK(Oprt, true, _T("||"),  f1of2)\r
-  #undef PARSER_THROWCHECK\r
-\r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestSyntax()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing syntax engine...");\r
-\r
-      iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF);  // incomplete hex definition\r
-      iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF);  // incomplete hex definition\r
-      iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF);  // incomplete hex definition\r
-      iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF);  // incomplete hex definition\r
-      iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF);  // incomplete hex definition\r
-\r
-      iStat += EqnTest(_T("(1+ 2*a)"), 3, true);   // Spaces within formula\r
-      iStat += EqnTest(_T("sqrt((4))"), 2, true);  // Multiple brackets\r
-      iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets\r
-      iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets\r
-      iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets\r
-      iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets\r
-      iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or"\r
-      iStat += EqnTest(_T("(2+"), 0, false);       // missing closing bracket \r
-      iStat += EqnTest(_T("2++4"), 0, false);      // unexpected operator\r
-      iStat += EqnTest(_T("2+-4"), 0, false);      // unexpected operator\r
-      iStat += EqnTest(_T("(2+)"), 0, false);      // unexpected closing bracket\r
-      iStat += EqnTest(_T("--2"), 0, false);       // double sign\r
-      iStat += EqnTest(_T("ksdfj"), 0, false);     // unknown token\r
-      iStat += EqnTest(_T("()"), 0, false);        // empty bracket without a function\r
-      iStat += EqnTest(_T("5+()"), 0, false);      // empty bracket without a function\r
-      iStat += EqnTest(_T("sin(cos)"), 0, false);  // unexpected function\r
-      iStat += EqnTest(_T("5t6"), 0, false);       // unknown token\r
-      iStat += EqnTest(_T("5 t 6"), 0, false);     // unknown token\r
-      iStat += EqnTest(_T("8*"), 0, false);        // unexpected end of formula\r
-      iStat += EqnTest(_T(",3"), 0, false);        // unexpected comma\r
-      iStat += EqnTest(_T("3,5"), 0, false);       // unexpected comma\r
-      iStat += EqnTest(_T("sin(8,8)"), 0, false);  // too many function args\r
-      iStat += EqnTest(_T("(7,8)"), 0, false);     // too many function args\r
-      iStat += EqnTest(_T("sin)"), 0, false);      // unexpected closing bracket\r
-      iStat += EqnTest(_T("a)"), 0, false);        // unexpected closing bracket\r
-      iStat += EqnTest(_T("pi)"), 0, false);       // unexpected closing bracket\r
-      iStat += EqnTest(_T("sin(())"), 0, false);   // unexpected closing bracket\r
-      iStat += EqnTest(_T("sin()"), 0, false);     // unexpected closing bracket\r
-\r
-      if (iStat==0)\r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestVarConst()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing variable/constant detection...");\r
-\r
-      // Test if the result changes when a variable changes\r
-      iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 );\r
-      iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 );\r
-\r
-      // distinguish constants with same basename\r
-      iStat += EqnTest( _T("const"), 1, true);\r
-      iStat += EqnTest( _T("const1"), 2, true);\r
-      iStat += EqnTest( _T("const2"), 3, true);\r
-      iStat += EqnTest( _T("2*const"), 2, true);\r
-      iStat += EqnTest( _T("2*const1"), 4, true);\r
-      iStat += EqnTest( _T("2*const2"), 6, true);\r
-      iStat += EqnTest( _T("2*const+1"), 3, true);\r
-      iStat += EqnTest( _T("2*const1+1"), 5, true);\r
-      iStat += EqnTest( _T("2*const2+1"), 7, true);\r
-      iStat += EqnTest( _T("const"), 0, false);\r
-      iStat += EqnTest( _T("const1"), 0, false);\r
-      iStat += EqnTest( _T("const2"), 0, false);\r
-\r
-      // distinguish variables with same basename\r
-      iStat += EqnTest( _T("a"), 1, true);\r
-      iStat += EqnTest( _T("aa"), 2, true);\r
-      iStat += EqnTest( _T("2*a"), 2, true);\r
-      iStat += EqnTest( _T("2*aa"), 4, true);\r
-      iStat += EqnTest( _T("2*a-1"), 1, true);\r
-      iStat += EqnTest( _T("2*aa-1"), 3, true);\r
-\r
-      // custom value recognition\r
-      iStat += EqnTest( _T("0xff"), 255, true);\r
-      iStat += EqnTest( _T("0x97 + 0xff"), 406, true);\r
-\r
-      // Finally test querying of used variables\r
-      try\r
-      {\r
-        int idx;\r
-        mu::Parser p;\r
-        mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};\r
-        p.DefineVar( _T("a"), &vVarVal[0]);\r
-        p.DefineVar( _T("b"), &vVarVal[1]);\r
-        p.DefineVar( _T("c"), &vVarVal[2]);\r
-        p.DefineVar( _T("d"), &vVarVal[3]);\r
-        p.DefineVar( _T("e"), &vVarVal[4]);\r
-\r
-        // Test lookup of defined variables\r
-        // 4 used variables\r
-        p.SetExpr( _T("a+b+c+d") );\r
-        mu::varmap_type UsedVar = p.GetUsedVar();\r
-        int iCount = (int)UsedVar.size();\r
-        if (iCount!=4) \r
-          throw false;\r
-        \r
-        // the next check will fail if the parser \r
-        // erroneousely creates new variables internally\r
-        if (p.GetVar().size()!=5)\r
-          throw false;\r
-\r
-        mu::varmap_type::const_iterator item = UsedVar.begin();\r
-        for (idx=0; item!=UsedVar.end(); ++item)\r
-        {\r
-          if (&vVarVal[idx++]!=item->second) \r
-            throw false;\r
-        }\r
-\r
-        // Test lookup of undefined variables\r
-        p.SetExpr( _T("undef1+undef2+undef3") );\r
-        UsedVar = p.GetUsedVar();\r
-        iCount = (int)UsedVar.size();\r
-        if (iCount!=3) \r
-          throw false;\r
-\r
-        // the next check will fail if the parser \r
-        // erroneousely creates new variables internally\r
-        if (p.GetVar().size()!=5)\r
-          throw false;\r
-\r
-        for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)\r
-        {\r
-          if (item->second!=0) \r
-            throw false; // all pointers to undefined variables must be null\r
-        }\r
-\r
-        // 1 used variables\r
-        p.SetExpr( _T("a+b") );\r
-        UsedVar = p.GetUsedVar();\r
-        iCount = (int)UsedVar.size();\r
-        if (iCount!=2) throw false;\r
-        item = UsedVar.begin();\r
-        for (idx=0; item!=UsedVar.end(); ++item)\r
-          if (&vVarVal[idx++]!=item->second) throw false;\r
-\r
-      }\r
-      catch(...)\r
-      {\r
-        iStat += 1;\r
-      }\r
-\r
-      if (iStat==0)  \r
-        mu::console() << _T("passed") << endl;\r
-      else\r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestMultiArg()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing multiarg functions...");\r
-    \r
-      // Compound expressions\r
-      iStat += EqnTest( _T("1,2,3"), 3, true);\r
-      iStat += EqnTest( _T("a,b,c"), 3, true);\r
-      iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true);\r
-      iStat += EqnTest( _T("1,\n2,\n3"), 3, true);\r
-      iStat += EqnTest( _T("a,\nb,\nc"), 3, true);\r
-      iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true);\r
-      iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true);\r
-      iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true);\r
-      iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true);\r
-\r
-      // picking the right argument\r
-      iStat += EqnTest( _T("f1of1(1)"), 1, true);\r
-      iStat += EqnTest( _T("f1of2(1, 2)"), 1, true);\r
-      iStat += EqnTest( _T("f2of2(1, 2)"), 2, true);\r
-      iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true);\r
-      iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true);\r
-      iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true);\r
-      iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true);\r
-      iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true);\r
-      iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true);\r
-      iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true);\r
-      iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true);\r
-      iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true);\r
-      iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true);\r
-      iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true);\r
-      iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true);\r
-      // Too few arguments / Too many arguments\r
-      iStat += EqnTest( _T("1+ping()"), 11, true);\r
-      iStat += EqnTest( _T("ping()+1"), 11, true);\r
-      iStat += EqnTest( _T("2*ping()"), 20, true);\r
-      iStat += EqnTest( _T("ping()*2"), 20, true);\r
-      iStat += EqnTest( _T("ping(1,2)"), 0, false);\r
-      iStat += EqnTest( _T("1+ping(1,2)"), 0, false);\r
-      iStat += EqnTest( _T("f1of1(1,2)"), 0, false);\r
-      iStat += EqnTest( _T("f1of1()"), 0, false);\r
-      iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false);\r
-      iStat += EqnTest( _T("f1of2(1)"), 0, false);\r
-      iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false);\r
-      iStat += EqnTest( _T("f1of3(1)"), 0, false);\r
-      iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false);\r
-      iStat += EqnTest( _T("f1of4(1)"), 0, false);\r
-      iStat += EqnTest( _T("(1,2,3)"), 0, false);\r
-      iStat += EqnTest( _T("1,2,3"), 0, false);\r
-      iStat += EqnTest( _T("(1*a,2,3)"), 0, false);\r
-      iStat += EqnTest( _T("1,2*a,3"), 0, false);\r
-     \r
-      // correct calculation of arguments\r
-      iStat += EqnTest( _T("min(a, 1)"),  1, true);\r
-      iStat += EqnTest( _T("min(3*2, 1)"),  1, true);\r
-      iStat += EqnTest( _T("min(3*2, 1)"),  6, false);\r
-      iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true);\r
-      iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true);\r
-      iStat += EqnTest( _T("min(3*a+1, 1)"),  1, true);\r
-      iStat += EqnTest( _T("max(3*a+1, 1)"),  4, true);\r
-      iStat += EqnTest( _T("max(3*a+1, 1)*2"),  8, true);\r
-      iStat += EqnTest( _T("2*max(3*a+1, 1)+2"),  10, true);\r
-\r
-      // functions with Variable argument count\r
-      iStat += EqnTest( _T("sum(a)"), 1, true);\r
-      iStat += EqnTest( _T("sum(1,2,3)"),  6, true);\r
-      iStat += EqnTest( _T("sum(a,b,c)"),  6, true);\r
-      iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"),  4, true);\r
-      iStat += EqnTest( _T("2*sum(1,2,3)"),  12, true);\r
-      iStat += EqnTest( _T("2*sum(1,2,3)+2"),  14, true);\r
-      iStat += EqnTest( _T("2*sum(-1,2,3)+2"),  10, true);\r
-      iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"),  6, true);\r
-      iStat += EqnTest( _T("2*sum(-1,10,-a)+2"),  18, true);\r
-      iStat += EqnTest( _T("2*sum(1,2,3)*2"),  24, true);\r
-      iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"),  4, true);\r
-      iStat += EqnTest( _T("sum(1*3, 4, a+2)"),  10, true);\r
-      iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"),  16, true);\r
-      iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);\r
-\r
-      // some failures\r
-      iStat += EqnTest( _T("sum()"),  0, false);\r
-      iStat += EqnTest( _T("sum(,)"),  0, false);\r
-      iStat += EqnTest( _T("sum(1,2,)"),  0, false);\r
-      iStat += EqnTest( _T("sum(,1,2)"),  0, false);\r
-\r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;\r
-      else\r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-  \r
-      return iStat;\r
-    }\r
-\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestInfixOprt()\r
-    {\r
-      int iStat(0);\r
-      mu::console() << "testing infix operators...";\r
-\r
-      iStat += EqnTest( _T("+1"),    +1, true);\r
-      iStat += EqnTest( _T("-(+1)"), -1, true);\r
-      iStat += EqnTest( _T("-(+1)*2"),  -2, true);\r
-      iStat += EqnTest( _T("-(+2)*sqrt(4)"),  -4, true);\r
-      iStat += EqnTest( _T("3-+a"), 2, true);\r
-      iStat += EqnTest( _T("+1*3"),  3, true);\r
-\r
-      iStat += EqnTest( _T("-1"),    -1, true);\r
-      iStat += EqnTest( _T("-(-1)"),  1, true);\r
-      iStat += EqnTest( _T("-(-1)*2"),  2, true);\r
-      iStat += EqnTest( _T("-(-2)*sqrt(4)"),  4, true);\r
-      iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true);\r
-      iStat += EqnTest( _T("-a"),  -1, true);\r
-      iStat += EqnTest( _T("-(a)"),  -1, true);\r
-      iStat += EqnTest( _T("-(-a)"),  1, true);\r
-      iStat += EqnTest( _T("-(-a)*2"),  2, true);\r
-      iStat += EqnTest( _T("-(8)"), -8, true);\r
-      iStat += EqnTest( _T("-8"), -8, true);\r
-      iStat += EqnTest( _T("-(2+1)"), -3, true);\r
-      iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true);\r
-      iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true);\r
-      iStat += EqnTest( _T("-sin(8)"), -0.989358, true);\r
-      iStat += EqnTest( _T("3-(-a)"), 4, true);\r
-      iStat += EqnTest( _T("3--a"), 4, true);\r
-      iStat += EqnTest( _T("-1*3"),  -3, true);\r
-\r
-      // Postfix / infix priorities\r
-      iStat += EqnTest( _T("~2#"), 8, true);\r
-      iStat += EqnTest( _T("~f1of1(2)#"), 8, true);\r
-      iStat += EqnTest( _T("~(b)#"), 8, true);\r
-      iStat += EqnTest( _T("(~b)#"), 12, true);\r
-      iStat += EqnTest( _T("~(2#)"), 8, true);\r
-      iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true);\r
-      //\r
-      iStat += EqnTest( _T("-2^2"),-4, true);\r
-      iStat += EqnTest( _T("-(a+b)^2"),-9, true);\r
-      iStat += EqnTest( _T("(-3)^2"),9, true);\r
-      iStat += EqnTest( _T("-(-2^2)"),4, true);\r
-      iStat += EqnTest( _T("3+-3^2"),-6, true);\r
-      // The following assumes use of sqr as postfix operator ("§") together\r
-      // with a sign operator of low priority:\r
-      iStat += EqnTest( _T("-2'"), -4, true);\r
-      iStat += EqnTest( _T("-(1+1)'"),-4, true);\r
-      iStat += EqnTest( _T("2+-(1+1)'"),-2, true);\r
-      iStat += EqnTest( _T("2+-2'"), -2, true);\r
-      // This is the classic behaviour of the infix sign operator (here: "$") which is\r
-      // now deprecated:\r
-      iStat += EqnTest( _T("$2^2"),4, true);\r
-      iStat += EqnTest( _T("$(a+b)^2"),9, true);\r
-      iStat += EqnTest( _T("($3)^2"),9, true);\r
-      iStat += EqnTest( _T("$($2^2)"),-4, true);\r
-      iStat += EqnTest( _T("3+$3^2"),12, true);\r
-\r
-      // infix operators sharing the first few characters\r
-      iStat += EqnTest( _T("~ 123"),  123+2, true);\r
-      iStat += EqnTest( _T("~~ 123"),  123+2, true);\r
-\r
-      if (iStat==0)\r
-        mu::console() << _T("passed") << endl;\r
-      else\r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestPostFix()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing postfix operators...");\r
-\r
-      // application\r
-      iStat += EqnTest( _T("3{m}+5"), 5.003, true);\r
-      iStat += EqnTest( _T("1000{m}"), 1, true);\r
-      iStat += EqnTest( _T("1000 {m}"), 1, true);\r
-      iStat += EqnTest( _T("(a){m}"), 1e-3, true);\r
-      iStat += EqnTest( _T("a{m}"), 1e-3, true);\r
-      iStat += EqnTest( _T("a {m}"), 1e-3, true);\r
-      iStat += EqnTest( _T("-(a){m}"), -1e-3, true);\r
-      iStat += EqnTest( _T("-2{m}"), -2e-3, true);\r
-      iStat += EqnTest( _T("-2 {m}"), -2e-3, true);\r
-      iStat += EqnTest( _T("f1of1(1000){m}"), 1, true);\r
-      iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true);\r
-      iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true);\r
-      iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true);\r
-      iStat += EqnTest( _T("2+(a*1000){m}"), 3, true);\r
-\r
-      // can postfix operators "m" und "meg" be told apart properly?\r
-      iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true);   \r
-\r
-      // some incorrect results\r
-      iStat += EqnTest( _T("1000{m}"), 0.1, false);\r
-      iStat += EqnTest( _T("(a){m}"), 2, false);\r
-      // failure due to syntax checking\r
-      iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN);  // incomplete hex definition\r
-      iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);\r
-      iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS);\r
-      iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS);\r
\r
-      iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN);\r
-\r
-      if (iStat==0)\r
-        mu::console() << _T("passed") << endl;\r
-      else\r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestExpression()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing expression samples...");\r
-\r
-      value_type b = 2;\r
-\r
-      // Optimization\r
-      iStat += EqnTest( _T("2*b*5"), 20, true);\r
-      iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true);\r
-      iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true);\r
-\r
-      // Addition auf cmVARMUL \r
-      iStat += EqnTest( _T("3+b"), b+3, true);\r
-      iStat += EqnTest( _T("b+3"), b+3, true);\r
-      iStat += EqnTest( _T("b*3+2"), b*3+2, true);\r
-      iStat += EqnTest( _T("3*b+2"), b*3+2, true);\r
-      iStat += EqnTest( _T("2+b*3"), b*3+2, true);\r
-      iStat += EqnTest( _T("2+3*b"), b*3+2, true);\r
-      iStat += EqnTest( _T("b+3*b"), b+3*b, true);\r
-      iStat += EqnTest( _T("3*b+b"), b+3*b, true);\r
-\r
-      iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true);\r
-      iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true);\r
-\r
-      iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true);\r
-      iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true);\r
-\r
-      // operator precedencs\r
-      iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true);\r
-      iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true);\r
-      iStat += EqnTest( _T("1+2*3"), 7, true);\r
-      iStat += EqnTest( _T("1+2*3"), 7, true);\r
-      iStat += EqnTest( _T("(1+2)*3"), 9, true);\r
-      iStat += EqnTest( _T("(1+2)*(-3)"), -9, true);\r
-      iStat += EqnTest( _T("2/4"), 0.5, true);\r
-\r
-      iStat += EqnTest( _T("exp(ln(7))"), 7, true);\r
-      iStat += EqnTest( _T("e^ln(7)"), 7, true);\r
-      iStat += EqnTest( _T("e^(ln(7))"), 7, true);\r
-      iStat += EqnTest( _T("(e^(ln(7)))"), 7, true);\r
-      iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true);\r
-      iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true);\r
-      iStat += EqnTest( _T("10^log(5)"), pow(10.0, log(5.0)), true);\r
-      iStat += EqnTest( _T("10^log10(5)"), 5, true);\r
-      iStat += EqnTest( _T("2^log2(4)"), 4, true);\r
-      iStat += EqnTest( _T("-(sin(0)+1)"), -1, true);\r
-      iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true);\r
-\r
-      iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true);\r
-      iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true);\r
-      iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true);\r
-      iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true);\r
-\r
-      // long formula (Reference: Matlab)\r
-      iStat += EqnTest(\r
-        _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")\r
-        _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")\r
-        _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")\r
-        _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")\r
-        _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")\r
-        _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true);\r
-\r
-      // long formula (Reference: Matlab)\r
-      iStat += EqnTest(\r
-          _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e")\r
-          _T(")+a)))*2.77)"), -2.16995656, true);\r
-\r
-      // long formula (Reference: Matlab)\r
-      iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);\r
-         \r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;  \r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestIfThenElse()\r
-    {\r
-      int iStat = 0;\r
-      mu::console() << _T("testing if-then-else operator...");\r
-\r
-      // Test error detection\r
-      iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); \r
-      iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); \r
-      iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE); \r
-      iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE); \r
-      iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE); \r
-      iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE); \r
-      iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON); \r
-      iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON); \r
-      iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON); \r
-      iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN); \r
-\r
-      iStat += EqnTest(_T("1 ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true);\r
-      iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true);\r
-      iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true);\r
-      iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true);\r
-      iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true);\r
-      iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true);\r
-      iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);\r
-      iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);\r
-      iStat += EqnTest(_T("(a<b) ? c : d"), 3, true);\r
-      iStat += EqnTest(_T("(a>b) ? c : d"), -2, true);\r
-\r
-      iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true);\r
-      iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true);\r
-      iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);\r
-      iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);\r
-\r
-      iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);\r
-      iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true);\r
-      iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);\r
-      iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true);\r
-      iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);\r
-      iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);\r
-      iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);\r
-      iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);\r
-      iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);\r
-      iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
-      iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);\r
-      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);\r
-      iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);\r
-      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);\r
-      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
-\r
-      // todo: auch für muParserX hinzufügen!\r
-      iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);\r
-      iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);\r
-      iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);\r
-      iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);\r
-      iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);\r
-\r
-      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);\r
-      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);\r
-      iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);\r
-      iStat += EqnTest(_T("1>0 ? 50 :  1>0 ? 128 : 255"), 50, true);\r
-      iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);\r
-      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);\r
-      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :  1>0 ? 32 :1>2 ? 64 : 16"), 255, true);\r
-      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);\r
-      iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true);\r
-\r
-      // assignment operators\r
-      iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true);\r
-      iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);\r
-      iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);\r
-      iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true);\r
-      iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true);\r
-      iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true);\r
-      iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true);  // a should not change its value due to lazy calculation\r
-      \r
-      iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true);\r
-      iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true);\r
-      iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true);\r
-      iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true);\r
-\r
-      iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true);\r
-      iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true);\r
-      iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true);\r
-      iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true);\r
-\r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;  \r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::TestException()\r
-    {\r
-      int  iStat = 0;\r
-      mu::console() << _T("testing error codes...");\r
-\r
-      iStat += ThrowTest(_T("3+"),           ecUNEXPECTED_EOF);\r
-      iStat += ThrowTest(_T("3+)"),          ecUNEXPECTED_PARENS);\r
-      iStat += ThrowTest(_T("()"),           ecUNEXPECTED_PARENS);\r
-      iStat += ThrowTest(_T("3+()"),         ecUNEXPECTED_PARENS);\r
-      iStat += ThrowTest(_T("sin(3,4)"),     ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest(_T("sin()"),        ecTOO_FEW_PARAMS);\r
-      iStat += ThrowTest(_T("(1+2"),         ecMISSING_PARENS);\r
-      iStat += ThrowTest(_T("sin(3)3"),      ecUNEXPECTED_VAL);\r
-      iStat += ThrowTest(_T("sin(3)xyz"),    ecUNASSIGNABLE_TOKEN);\r
-      iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);\r
-      iStat += ThrowTest(_T("a+b+c=10"),     ecUNEXPECTED_OPERATOR);\r
-      iStat += ThrowTest(_T("a=b=3"),        ecUNEXPECTED_OPERATOR);\r
-      \r
-#if defined(MUP_MATH_EXCEPTIONS)\r
-      // divide by zero whilst constant folding\r
-      iStat += ThrowTest(_T("1/0"),          ecDIV_BY_ZERO);\r
-      // square root of a negative number\r
-      iStat += ThrowTest(_T("sqrt(-1)"),     ecDOMAIN_ERROR);\r
-      // logarithms of zero\r
-      iStat += ThrowTest(_T("ln(0)"),        ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log2(0)"),      ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log10(0)"),     ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log(0)"),       ecDOMAIN_ERROR);\r
-      // logarithms of negative values\r
-      iStat += ThrowTest(_T("ln(-1)"),       ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log2(-1)"),     ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log10(-1)"),    ecDOMAIN_ERROR);\r
-      iStat += ThrowTest(_T("log(-1)"),      ecDOMAIN_ERROR);\r
-#endif\r
-\r
-      // functions without parameter\r
-      iStat += ThrowTest( _T("3+ping(2)"),    ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("3+ping(a+2)"),  ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("3+ping(sin(a)+2)"),  ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("3+ping(1+sin(a))"),  ecTOO_MANY_PARAMS);\r
-\r
-      // String function related\r
-      iStat += ThrowTest( _T("valueof(\"xxx\")"),  999, false);\r
-      iStat += ThrowTest( _T("valueof()"),          ecUNEXPECTED_PARENS);\r
-      iStat += ThrowTest( _T("1+valueof(\"abc\""),  ecMISSING_PARENS);\r
-      iStat += ThrowTest( _T("valueof(\"abc\""),    ecMISSING_PARENS);\r
-      iStat += ThrowTest( _T("valueof(\"abc"),      ecUNTERMINATED_STRING);\r
-      iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("valueof(3)"),         ecSTRING_EXPECTED);\r
-      iStat += ThrowTest( _T("sin(\"abc\")"),       ecVAL_EXPECTED);\r
-      iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"),  999, false);\r
-      iStat += ThrowTest( _T("\"hello world\""),    ecSTR_RESULT);\r
-      iStat += ThrowTest( _T("(\"hello world\")"),  ecSTR_RESULT);\r
-      iStat += ThrowTest( _T("\"abcd\"+100"),       ecOPRT_TYPE_CONFLICT);\r
-      iStat += ThrowTest( _T("\"a\"+\"b\""),        ecOPRT_TYPE_CONFLICT);\r
-      iStat += ThrowTest( _T("strfun1(\"100\",3)"),     ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("strfun2(\"100\",3,5)"),   ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("strfun2(\"100\")"),       ecTOO_FEW_PARAMS);\r
-      iStat += ThrowTest( _T("strfun3(\"100\",6)"),   ecTOO_FEW_PARAMS);\r
-      iStat += ThrowTest( _T("strfun2(1,1)"),         ecSTRING_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun2(a,1)"),         ecSTRING_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun2(1,1,1)"),       ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("strfun2(a,1,1)"),       ecTOO_MANY_PARAMS);\r
-      iStat += ThrowTest( _T("strfun3(1,2,3)"),         ecSTRING_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun3(1, \"100\",3)"),  ecSTRING_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"),  ecVAL_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"),  ecVAL_EXPECTED);\r
-      iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"),  ecTOO_MANY_PARAMS);\r
-\r
-      // assignement operator\r
-      iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR);\r
-      iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR);\r
-      iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR);\r
-\r
-      // <ibg 20090529>\r
-      // this is now legal, for reference see:\r
-      // https://sourceforge.net/forum/message.php?msg_id=7411373\r
-      //      iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR);    \r
-      // </ibg>\r
-\r
-      iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR);\r
-      iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR);\r
-      iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);\r
-\r
-      if (iStat==0) \r
-        mu::console() << _T("passed") << endl;\r
-      else \r
-        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;\r
-\r
-      return iStat;\r
-    }\r
-\r
-\r
-    //---------------------------------------------------------------------------\r
-    void ParserTester::AddTest(testfun_type a_pFun)\r
-    {\r
-      m_vTestFun.push_back(a_pFun);\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    void ParserTester::Run()\r
-    {\r
-      int iStat = 0;\r
-      try\r
-      {\r
-        for (int i=0; i<(int)m_vTestFun.size(); ++i)\r
-          iStat += (this->*m_vTestFun[i])();\r
-      }\r
-      catch(Parser::exception_type &e)\r
-      {\r
-        mu::console() << "\n" << e.GetMsg() << endl;\r
-        mu::console() << e.GetToken() << endl;\r
-        Abort();\r
-      }\r
-      catch(std::exception &e)\r
-      {\r
-        mu::console() << e.what() << endl;\r
-        Abort();\r
-      }\r
-      catch(...)\r
-      {\r
-        mu::console() << "Internal error";\r
-        Abort();\r
-      }\r
-\r
-      if (iStat==0) \r
-      {\r
-        mu::console() << "Test passed (" <<  ParserTester::c_iCount << " expressions)" << endl;\r
-      }\r
-      else \r
-      {\r
-        mu::console() << "Test failed with " << iStat \r
-                  << " errors (" <<  ParserTester::c_iCount \r
-                  << " expressions)" << endl;\r
-      }\r
-      ParserTester::c_iCount = 0;\r
-    }\r
-\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)\r
-    {\r
-      ParserTester::c_iCount++;\r
-\r
-      try\r
-      {\r
-        value_type fVal[] = {1,1,1};\r
-        Parser p;\r
-\r
-        p.DefineVar( _T("a"), &fVal[0]);\r
-        p.DefineVar( _T("b"), &fVal[1]);\r
-        p.DefineVar( _T("c"), &fVal[2]);\r
-        p.DefinePostfixOprt( _T("{m}"), Milli);\r
-        p.DefinePostfixOprt( _T("m"), Milli);\r
-        p.DefineFun( _T("ping"), Ping);\r
-        p.DefineFun( _T("valueof"), ValueOf);\r
-        p.DefineFun( _T("strfun1"), StrFun1);\r
-        p.DefineFun( _T("strfun2"), StrFun2);\r
-        p.DefineFun( _T("strfun3"), StrFun3);\r
-        p.SetExpr(a_str);\r
-        p.Eval();\r
-      }\r
-      catch(ParserError &e)\r
-      {\r
-        // output the formula in case of an failed test\r
-        if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )\r
-        {\r
-          mu::console() << _T("\n  ") \r
-                        << _T("Expression: ") << a_str \r
-                        << _T("  Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")")\r
-                        << _T("  Expected:") << a_iErrc;\r
-        }\r
-\r
-        return (a_iErrc==e.GetCode()) ? 0 : 1;\r
-      }\r
-\r
-      // if a_bFail==false no exception is expected\r
-      bool bRet((a_bFail==false) ? 0 : 1);\r
-      if (bRet==1)\r
-      {\r
-        mu::console() << _T("\n  ") \r
-                      << _T("Expression: ") << a_str \r
-                      << _T("  did evaluate; Expected error:") << a_iErrc;\r
-      }\r
-\r
-      return bRet; \r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    /** \brief Evaluate a tet expression. \r
-\r
-        \return 1 in case of a failure, 0 otherwise.\r
-    */\r
-    int ParserTester::EqnTestWithVarChange(const string_type &a_str, \r
-                                           double a_fVar1, \r
-                                           double a_fRes1, \r
-                                           double a_fVar2, \r
-                                           double a_fRes2)\r
-    {\r
-      ParserTester::c_iCount++;\r
-\r
-      try\r
-      {\r
-        value_type fVal[2] = {-999, -999 }; // should be equalinitially\r
-         \r
-        Parser  p;\r
-        value_type var = 0;\r
-\r
-        // variable\r
-        p.DefineVar( _T("a"), &var);\r
-        p.SetExpr(a_str);\r
-\r
-        var = a_fVar1;\r
-        fVal[0] = p.Eval();\r
-\r
-        var = a_fVar2;\r
-        fVal[1] = p.Eval();\r
-        \r
-        if ( fabs(a_fRes1-fVal[0]) > 0.0000000001)\r
-          throw std::runtime_error("incorrect result (first pass)");\r
-\r
-        if ( fabs(a_fRes2-fVal[1]) > 0.0000000001)\r
-          throw std::runtime_error("incorrect result (second pass)");\r
-      }\r
-      catch(Parser::exception_type &e)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
-        return 1;\r
-      }\r
-      catch(std::exception &e)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
-        return 1;  // always return a failure since this exception is not expected\r
-      }\r
-      catch(...)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");\r
-        return 1;  // exceptions other than ParserException are not allowed\r
-      }\r
-\r
-      return 0;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    /** \brief Evaluate a tet expression. \r
-\r
-        \return 1 in case of a failure, 0 otherwise.\r
-    */\r
-    int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)\r
-    {\r
-      ParserTester::c_iCount++;\r
-      int iRet(0);\r
-      value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different\r
-\r
-      try\r
-      {\r
-        std::unique_ptr<Parser> p1;\r
-        Parser  p2, p3;   // three parser objects\r
-                          // they will be used for testing copy and assihnment operators\r
-        // p1 is a pointer since i'm going to delete it in order to test if\r
-        // parsers after copy construction still refer to members of it.\r
-        // !! If this is the case this function will crash !!\r
-      \r
-        p1.reset(new mu::Parser()); \r
-        // Add constants\r
-        p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI);\r
-        p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E);\r
-        p1->DefineConst( _T("const"), 1);\r
-        p1->DefineConst( _T("const1"), 2);\r
-        p1->DefineConst( _T("const2"), 3);\r
-        // string constants\r
-        p1->DefineStrConst( _T("str1"), _T("1.11"));\r
-        p1->DefineStrConst( _T("str2"), _T("2.22"));\r
-        // variables\r
-        value_type vVarVal[] = { 1, 2, 3, -2};\r
-        p1->DefineVar( _T("a"), &vVarVal[0]);\r
-        p1->DefineVar( _T("aa"), &vVarVal[1]);\r
-        p1->DefineVar( _T("b"), &vVarVal[1]);\r
-        p1->DefineVar( _T("c"), &vVarVal[2]);\r
-        p1->DefineVar( _T("d"), &vVarVal[3]);\r
-        \r
-        // custom value ident functions\r
-        p1->AddValIdent(&ParserTester::IsHexVal);        \r
-\r
-        // functions\r
-        p1->DefineFun( _T("ping"), Ping);\r
-        p1->DefineFun( _T("f1of1"), f1of1);  // one parameter\r
-        p1->DefineFun( _T("f1of2"), f1of2);  // two parameter\r
-        p1->DefineFun( _T("f2of2"), f2of2);\r
-        p1->DefineFun( _T("f1of3"), f1of3);  // three parameter\r
-        p1->DefineFun( _T("f2of3"), f2of3);\r
-        p1->DefineFun( _T("f3of3"), f3of3);\r
-        p1->DefineFun( _T("f1of4"), f1of4);  // four parameter\r
-        p1->DefineFun( _T("f2of4"), f2of4);\r
-        p1->DefineFun( _T("f3of4"), f3of4);\r
-        p1->DefineFun( _T("f4of4"), f4of4);\r
-        p1->DefineFun( _T("f1of5"), f1of5);  // five parameter\r
-        p1->DefineFun( _T("f2of5"), f2of5);\r
-        p1->DefineFun( _T("f3of5"), f3of5);\r
-        p1->DefineFun( _T("f4of5"), f4of5);\r
-        p1->DefineFun( _T("f5of5"), f5of5);\r
-\r
-        // binary operators\r
-        p1->DefineOprt( _T("add"), add, 0);\r
-        p1->DefineOprt( _T("++"), add, 0);\r
-        p1->DefineOprt( _T("&"), land, prLAND);\r
-\r
-        // sample functions\r
-        p1->DefineFun( _T("min"), Min);\r
-        p1->DefineFun( _T("max"), Max);\r
-        p1->DefineFun( _T("sum"), Sum);\r
-        p1->DefineFun( _T("valueof"), ValueOf);\r
-        p1->DefineFun( _T("atof"), StrToFloat);\r
-        p1->DefineFun( _T("strfun1"), StrFun1);\r
-        p1->DefineFun( _T("strfun2"), StrFun2);\r
-        p1->DefineFun( _T("strfun3"), StrFun3);\r
-        p1->DefineFun( _T("lastArg"), LastArg);\r
-        p1->DefineFun( _T("firstArg"), FirstArg);\r
-        p1->DefineFun( _T("order"), FirstArg);\r
-\r
-        // infix / postfix operator\r
-        // Note: Identifiers used here do not have any meaning \r
-        //       they are mere placeholders to test certain features.\r
-        p1->DefineInfixOprt( _T("$"), sign, prPOW+1);  // sign with high priority\r
-        p1->DefineInfixOprt( _T("~"), plus2);          // high priority\r
-        p1->DefineInfixOprt( _T("~~"), plus2);\r
-        p1->DefinePostfixOprt( _T("{m}"), Milli);\r
-        p1->DefinePostfixOprt( _T("{M}"), Mega);\r
-        p1->DefinePostfixOprt( _T("m"), Milli);\r
-        p1->DefinePostfixOprt( _T("meg"), Mega);\r
-        p1->DefinePostfixOprt( _T("#"), times3);\r
-        p1->DefinePostfixOprt( _T("'"), sqr); \r
-        p1->SetExpr(a_str);\r
-\r
-        // Test bytecode integrity\r
-        // String parsing and bytecode parsing must yield the same result\r
-        fVal[0] = p1->Eval(); // result from stringparsing\r
-        fVal[1] = p1->Eval(); // result from bytecode\r
-        if (fVal[0]!=fVal[1])\r
-          throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") );\r
-\r
-        // Test copy and assignement operators\r
-        try\r
-        {\r
-          // Test copy constructor\r
-          std::vector<mu::Parser> vParser;\r
-          vParser.push_back(*(p1.get()));\r
-          mu::Parser p2 = vParser[0];   // take parser from vector\r
-        \r
-          // destroy the originals from p2\r
-          vParser.clear();              // delete the vector\r
-          p1.reset(0);\r
-\r
-          fVal[2] = p2.Eval();\r
-\r
-          // Test assignement operator\r
-          // additionally  disable Optimizer this time\r
-          mu::Parser p3;\r
-          p3 = p2;\r
-          p3.EnableOptimizer(false);\r
-          fVal[3] = p3.Eval();\r
-\r
-          // Test Eval function for multiple return values\r
-          // use p2 since it has the optimizer enabled!\r
-          int nNum;\r
-          value_type *v = p2.Eval(nNum);\r
-          fVal[4] = v[nNum-1];\r
-        }\r
-        catch(std::exception &e)\r
-        {\r
-          mu::console() << _T("\n  ") << e.what() << _T("\n");\r
-        }\r
-\r
-        // limited floating point accuracy requires the following test\r
-        bool bCloseEnough(true);\r
-        for (unsigned i=0; i<sizeof(fVal)/sizeof(value_type); ++i)\r
-        {\r
-          bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.00001));\r
-\r
-          // The tests equations never result in infinity, if they do thats a bug.\r
-          // reference:\r
-          // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825\r
-          #pragma warning(push)\r
-          #pragma warning(disable:4127)\r
-                 if (std::numeric_limits<value_type>::has_infinity)\r
-          #pragma warning(pop)\r
-                 {\r
-            bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity());\r
-                 }\r
-               }\r
-\r
-        iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;\r
-        \r
-        \r
-        if (iRet==1)\r
-        {\r
-          mu::console() << _T("\n  fail: ") << a_str.c_str() \r
-                        << _T(" (incorrect result; expected: ") << a_fRes\r
-                        << _T(" ;calculated: ") << fVal[0] << _T(",") \r
-                                                << fVal[1] << _T(",")\r
-                                                << fVal[2] << _T(",")\r
-                                                << fVal[3] << _T(",")\r
-                                                << fVal[4] << _T(").");\r
-        }\r
-      }\r
-      catch(Parser::exception_type &e)\r
-      {\r
-        if (a_fPass)\r
-        {\r
-          if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)\r
-            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (copy construction)");\r
-          else\r
-            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
-          return 1;\r
-        }\r
-      }\r
-      catch(std::exception &e)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
-        return 1;  // always return a failure since this exception is not expected\r
-      }\r
-      catch(...)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");\r
-        return 1;  // exceptions other than ParserException are not allowed\r
-      }\r
-\r
-      return iRet;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)\r
-    {\r
-      ParserTester::c_iCount++;\r
-\r
-      value_type vVarVal[] = {1, 2, 3};   // variable values\r
-      int iRet(0);\r
-\r
-      try\r
-      {\r
-        value_type fVal[2] = {-99, -999};   // results: initially should be different\r
-        ParserInt p;\r
-        p.DefineConst( _T("const1"), 1);\r
-        p.DefineConst( _T("const2"), 2);\r
-        p.DefineVar( _T("a"), &vVarVal[0]);\r
-        p.DefineVar( _T("b"), &vVarVal[1]);\r
-        p.DefineVar( _T("c"), &vVarVal[2]);\r
-\r
-        p.SetExpr(a_str);\r
-        fVal[0] = p.Eval(); // result from stringparsing\r
-        fVal[1] = p.Eval(); // result from bytecode\r
-\r
-        if (fVal[0]!=fVal[1])\r
-          throw Parser::exception_type( _T("Bytecode corrupt.") );\r
-\r
-        iRet =  ( (a_fRes==fVal[0] &&  a_fPass) || \r
-                  (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;\r
-        if (iRet==1)\r
-        {\r
-          mu::console() << _T("\n  fail: ") << a_str.c_str() \r
-                        << _T(" (incorrect result; expected: ") << a_fRes \r
-                        << _T(" ;calculated: ") << fVal[0]<< _T(").");\r
-        }\r
-      }\r
-      catch(Parser::exception_type &e)\r
-      {\r
-        if (a_fPass)\r
-        {\r
-          mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();\r
-          iRet = 1;\r
-        }\r
-      }\r
-      catch(...)\r
-      {\r
-        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");\r
-        iRet = 1;  // exceptions other than ParserException are not allowed\r
-      }\r
-\r
-      return iRet;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    /** \brief Test an expression in Bulk Mode. */\r
-    int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass)\r
-    {\r
-        ParserTester::c_iCount++;\r
-\r
-        // Define Bulk Variables\r
-        int nBulkSize = 4;\r
-        value_type vVariableA[] = { 1, 2, 3, 4 };   // variable values\r
-        value_type vVariableB[] = { 2, 2, 2, 2 };   // variable values\r
-        value_type vVariableC[] = { 3, 3, 3, 3 };   // variable values\r
-        value_type vResults[] = { 0, 0, 0, 0 };   // variable values\r
-        int iRet(0);\r
-\r
-        try\r
-        {\r
-            Parser p;\r
-            p.DefineConst(_T("const1"), 1);\r
-            p.DefineConst(_T("const2"), 2);\r
-            p.DefineVar(_T("a"), vVariableA);\r
-            p.DefineVar(_T("b"), vVariableB);\r
-            p.DefineVar(_T("c"), vVariableC);\r
-\r
-            p.SetExpr(a_str);\r
-            p.Eval(vResults, nBulkSize);\r
-\r
-            bool bCloseEnough(true);\r
-            for (int i = 0; i < nBulkSize; ++i)\r
-            {\r
-                bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001));\r
-            }\r
-\r
-            iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;\r
-            if (iRet == 1)\r
-            {\r
-                mu::console() << _T("\n  fail: ") << a_str.c_str()\r
-                    << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}")\r
-                    << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}");\r
-            }\r
-        }\r
-        catch (Parser::exception_type &e)\r
-        {\r
-            if (a_fPass)\r
-            {\r
-                mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();\r
-                iRet = 1;\r
-            }\r
-        }\r
-        catch (...)\r
-        {\r
-            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
-            iRet = 1;  // exceptions other than ParserException are not allowed\r
-        }\r
-\r
-        return iRet;\r
-    }\r
-\r
-    //---------------------------------------------------------------------------\r
-    /** \brief Internal error in test class Test is going to be aborted. */\r
-    void ParserTester::Abort() const\r
-    {\r
-      mu::console() << _T("Test failed (internal error in test class)") << endl;\r
-      while (!getchar());\r
-      exit(-1);\r
-    }\r
-  } // namespace test\r
-} // namespace mu\r
diff --git a/bundled/muparser_v2_2_4/src/muParserTokenReader.cpp b/bundled/muparser_v2_2_4/src/muParserTokenReader.cpp
deleted file mode 100644 (file)
index 55daf8e..0000000
+++ /dev/null
@@ -1,958 +0,0 @@
-/*\r
-                 __________                                      \r
-    _____   __ __\______   \_____  _______  ______  ____ _______ \r
-   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \\r
-  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/\r
-  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   \r
-        \/                       \/            \/      \/        \r
-  Copyright (C) 2013 Ingo Berg\r
-\r
-  Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
-  software and associated documentation files (the "Software"), to deal in the Software\r
-  without restriction, including without limitation the rights to use, copy, modify, \r
-  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
-  permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
-\r
-  The above copyright notice and this permission notice shall be included in all copies or \r
-  substantial portions of the Software.\r
-\r
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
-  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
-  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
-*/\r
-#include <cassert>\r
-#include <cstdio>\r
-#include <cstring>\r
-#include <map>\r
-#include <stack>\r
-#include <string>\r
-\r
-#include "muParserTokenReader.h"\r
-#include "muParserBase.h"\r
-\r
-/** \file\r
-    \brief This file contains the parser token reader implementation.\r
-*/\r
-\r
-\r
-namespace mu\r
-{\r
-\r
-  // Forward declaration\r
-  class ParserBase;\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Copy constructor.\r
-\r
-      \sa Assign\r
-      \throw nothrow\r
-  */\r
-  ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) \r
-  { \r
-    Assign(a_Reader);\r
-  }\r
-    \r
-  //---------------------------------------------------------------------------\r
-  /** \brief Assignement operator.\r
-\r
-      Self assignement will be suppressed otherwise #Assign is called.\r
-\r
-      \param a_Reader Object to copy to this token reader.\r
-      \throw nothrow\r
-  */\r
-  ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) \r
-  {\r
-    if (&a_Reader!=this)\r
-      Assign(a_Reader);\r
-\r
-    return *this;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Assign state of a token reader to this token reader. \r
-      \r
-      \param a_Reader Object from which the state should be copied.\r
-      \throw nothrow\r
-  */\r
-  void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)\r
-  {\r
-    m_pParser = a_Reader.m_pParser;\r
-    m_strFormula = a_Reader.m_strFormula;\r
-    m_iPos = a_Reader.m_iPos;\r
-    m_iSynFlags = a_Reader.m_iSynFlags;\r
-    \r
-    m_UsedVar         = a_Reader.m_UsedVar;\r
-    m_pFunDef         = a_Reader.m_pFunDef;\r
-    m_pConstDef       = a_Reader.m_pConstDef;\r
-    m_pVarDef         = a_Reader.m_pVarDef;\r
-    m_pStrVarDef      = a_Reader.m_pStrVarDef;\r
-    m_pPostOprtDef    = a_Reader.m_pPostOprtDef;\r
-    m_pInfixOprtDef   = a_Reader.m_pInfixOprtDef;\r
-    m_pOprtDef        = a_Reader.m_pOprtDef;\r
-    m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;\r
-    m_vIdentFun       = a_Reader.m_vIdentFun;\r
-    m_pFactory        = a_Reader.m_pFactory;\r
-    m_pFactoryData    = a_Reader.m_pFactoryData;\r
-    m_iBrackets       = a_Reader.m_iBrackets;\r
-    m_cArgSep         = a_Reader.m_cArgSep;\r
-       m_fZero           = a_Reader.m_fZero;\r
-       m_lastTok         = a_Reader.m_lastTok;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Constructor. \r
-      \r
-      Create a Token reader and bind it to a parser object. \r
-\r
-      \pre [assert] a_pParser may not be NULL\r
-      \post #m_pParser==a_pParser\r
-      \param a_pParent Parent parser object of the token reader.\r
-  */\r
-  ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)\r
-    :m_pParser(a_pParent)\r
-    ,m_strFormula()\r
-    ,m_iPos(0)\r
-    ,m_iSynFlags(0)\r
-    ,m_bIgnoreUndefVar(false)\r
-    ,m_pFunDef(NULL)\r
-    ,m_pPostOprtDef(NULL)\r
-    ,m_pInfixOprtDef(NULL)\r
-    ,m_pOprtDef(NULL)\r
-    ,m_pConstDef(NULL)\r
-    ,m_pStrVarDef(NULL)\r
-    ,m_pVarDef(NULL)\r
-    ,m_pFactory(NULL)\r
-    ,m_pFactoryData(NULL)\r
-    ,m_vIdentFun()\r
-    ,m_UsedVar()\r
-    ,m_fZero(0)\r
-    ,m_iBrackets(0)\r
-    ,m_lastTok()\r
-    ,m_cArgSep(',')\r
-  {\r
-    assert(m_pParser);\r
-    SetParent(m_pParser);\r
-  }\r
-    \r
-  //---------------------------------------------------------------------------\r
-  /** \brief Create instance of a ParserTokenReader identical with this \r
-              and return its pointer. \r
-\r
-      This is a factory method the calling function must take care of the object destruction.\r
-\r
-      \return A new ParserTokenReader object.\r
-      \throw nothrow\r
-  */\r
-  ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const\r
-  {\r
-    std::unique_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));\r
-    ptr->SetParent(a_pParent);\r
-    return ptr.release();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok)\r
-  {\r
-    m_lastTok = tok;\r
-    return m_lastTok;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserTokenReader::AddValIdent(identfun_type a_pCallback)\r
-  {\r
-    // Use push_front is used to give user defined callbacks a higher priority than\r
-    // the built in ones. Otherwise reading hex numbers would not work\r
-    // since the "0" in "0xff" would always be read first making parsing of \r
-    // the rest impossible.\r
-    // reference:\r
-    // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956\r
-    m_vIdentFun.push_front(a_pCallback);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)\r
-  {\r
-    m_pFactory = a_pFactory;\r
-    m_pFactoryData = pUserData;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return the current position of the token reader in the formula string. \r
-\r
-      \return #m_iPos\r
-      \throw nothrow\r
-  */\r
-  int ParserTokenReader::GetPos() const\r
-  {\r
-    return m_iPos;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return a reference to the formula. \r
-\r
-      \return #m_strFormula\r
-      \throw nothrow\r
-  */\r
-  const string_type& ParserTokenReader::GetExpr() const\r
-  {\r
-    return m_strFormula;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Return a map containing the used variables only. */\r
-  varmap_type& ParserTokenReader::GetUsedVar() \r
-  {\r
-    return m_UsedVar;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Initialize the token Reader. \r
-  \r
-      Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.\r
-      \pre [assert] triggered if a_szFormula==0\r
-  */\r
-  void ParserTokenReader::SetFormula(const string_type &a_strFormula)\r
-  {\r
-    m_strFormula = a_strFormula;\r
-    ReInit();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found. \r
-  \r
-    If true, the parser does not throw an exception if an undefined variable is found. \r
-    otherwise it does. This variable is used internally only!\r
-    It supresses a "undefined variable" exception in GetUsedVar().  \r
-    Those function should return a complete list of variables including \r
-    those the are not defined by the time of it's call.\r
-  */\r
-  void ParserTokenReader::IgnoreUndefVar(bool bIgnore)\r
-  {\r
-    m_bIgnoreUndefVar = bIgnore;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Reset the token reader to the start of the formula. \r
-\r
-      The syntax flags will be reset to a value appropriate for the \r
-      start of a formula.\r
-      \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR\r
-      \throw nothrow\r
-      \sa ESynCodes\r
-  */\r
-  void ParserTokenReader::ReInit()\r
-  {\r
-    m_iPos = 0;\r
-    m_iSynFlags = sfSTART_OF_LINE;\r
-    m_iBrackets = 0;\r
-    m_UsedVar.clear();\r
-    m_lastTok = token_type();\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Read the next token from the string. */ \r
-  ParserTokenReader::token_type ParserTokenReader::ReadNextToken()\r
-  {\r
-    assert(m_pParser);\r
-\r
-    const char_type *szFormula = m_strFormula.c_str();\r
-    token_type tok;\r
-\r
-    // Ignore all non printable characters when reading the expression\r
-    while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) \r
-      ++m_iPos;\r
-\r
-    if ( IsEOF(tok) )        return SaveBeforeReturn(tok); // Check for end of formula\r
-    if ( IsOprt(tok) )       return SaveBeforeReturn(tok); // Check for user defined binary operator\r
-    if ( IsFunTok(tok) )     return SaveBeforeReturn(tok); // Check for function token\r
-    if ( IsBuiltIn(tok) )    return SaveBeforeReturn(tok); // Check built in operators / tokens\r
-    if ( IsArgSep(tok) )     return SaveBeforeReturn(tok); // Check for function argument separators\r
-    if ( IsValTok(tok) )     return SaveBeforeReturn(tok); // Check for values / constant tokens\r
-    if ( IsVarTok(tok) )     return SaveBeforeReturn(tok); // Check for variable tokens\r
-    if ( IsStrVarTok(tok) )  return SaveBeforeReturn(tok); // Check for string variables\r
-    if ( IsString(tok) )     return SaveBeforeReturn(tok); // Check for String tokens\r
-    if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators\r
-    if ( IsPostOpTok(tok) )  return SaveBeforeReturn(tok); // Check for unary operators\r
-\r
-    // Check String for undefined variable token. Done only if a \r
-    // flag is set indicating to ignore undefined variables.\r
-    // This is a way to conditionally avoid an error if \r
-    // undefined variables occur. \r
-    // (The GetUsedVar function must suppress the error for\r
-    // undefined variables in order to collect all variable \r
-    // names including the undefined ones.)\r
-    if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )  \r
-      return SaveBeforeReturn(tok);\r
-\r
-    // Check for unknown token\r
-    // \r
-    // !!! From this point on there is no exit without an exception possible...\r
-    // \r
-    string_type strTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
-    if (iEnd!=m_iPos)\r
-      Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);\r
-\r
-    Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));\r
-    return token_type(); // never reached\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserTokenReader::SetParent(ParserBase *a_pParent)\r
-  {\r
-    m_pParser       = a_pParent; \r
-    m_pFunDef       = &a_pParent->m_FunDef;\r
-    m_pOprtDef      = &a_pParent->m_OprtDef;\r
-    m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;\r
-    m_pPostOprtDef  = &a_pParent->m_PostOprtDef;\r
-    m_pVarDef       = &a_pParent->m_VarDef;\r
-    m_pStrVarDef    = &a_pParent->m_StrVarDef;\r
-    m_pConstDef     = &a_pParent->m_ConstDef;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Extract all characters that belong to a certain charset.\r
-\r
-    \param a_szCharSet [in] Const char array of the characters allowed in the token. \r
-    \param a_strTok [out]  The string that consists entirely of characters listed in a_szCharSet.\r
-    \param a_iPos [in] Position in the string from where to start reading.\r
-    \return The Position of the first character not listed in a_szCharSet.\r
-    \throw nothrow\r
-  */\r
-  int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, \r
-                                      string_type &a_sTok, \r
-                                      int a_iPos) const\r
-  {\r
-    int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);\r
-\r
-    if (iEnd==(int)string_type::npos)\r
-        iEnd = (int)m_strFormula.length();\r
-    \r
-    // Assign token string if there was something found\r
-    if (a_iPos!=iEnd)\r
-      a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);\r
-\r
-    return iEnd;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check Expression for the presence of a binary operator token.\r
-  \r
-    Userdefined binary operator "++" gives inconsistent parsing result for\r
-    the equations "a++b" and "a ++ b" if alphabetic characters are allowed\r
-    in operator tokens. To avoid this this function checks specifically\r
-    for operator tokens.\r
-  */\r
-  int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, \r
-                                              int a_iPos) const\r
-  {\r
-    // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6\r
-    int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos);\r
-    if (iEnd==(int)string_type::npos)\r
-      iEnd = (int)m_strFormula.length();\r
-\r
-    // Assign token string if there was something found\r
-    if (a_iPos!=iEnd)\r
-    {\r
-      a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);\r
-      return iEnd;\r
-    }\r
-    else\r
-    {\r
-      // There is still the chance of having to deal with an operator consisting exclusively\r
-      // of alphabetic characters.\r
-      return ExtractToken(MUP_CHARS, a_sTok, a_iPos);\r
-    }\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a built in operator or other token can be found\r
-      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
-      \return true if an operator token has been found.\r
-  */\r
-  bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)\r
-  {\r
-    const char_type **const pOprtDef = m_pParser->GetOprtDef(),\r
-                     *const szFormula = m_strFormula.c_str();\r
-\r
-    // Compare token with function and operator strings\r
-    // check string for operator/function\r
-    for (int i=0; pOprtDef[i]; i++)\r
-    {\r
-      std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );\r
-      if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )\r
-      {\r
-        switch(i)\r
-        {\r
-        //case cmAND:\r
-        //case cmOR:\r
-        //case cmXOR:\r
-        case cmLAND:\r
-        case cmLOR:\r
-        case cmLT:\r
-        case cmGT:\r
-        case cmLE:\r
-        case cmGE:\r
-        case cmNEQ:  \r
-        case cmEQ:\r
-        case cmADD:\r
-        case cmSUB:\r
-        case cmMUL:\r
-        case cmDIV:\r
-        case cmPOW:\r
-        case cmASSIGN:\r
-              //if (len!=sTok.length())\r
-              //  continue;\r
-\r
-              // The assignement operator need special treatment\r
-              if (i==cmASSIGN && m_iSynFlags & noASSIGN)\r
-                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
-\r
-              if (!m_pParser->HasBuiltInOprt()) continue;\r
-              if (m_iSynFlags & noOPT) \r
-              {\r
-                // Maybe its an infix operator not an operator\r
-                // Both operator types can share characters in \r
-                // their identifiers\r
-                if ( IsInfixOpTok(a_Tok) ) \r
-                  return true;\r
-\r
-                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
-              }\r
-\r
-              m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND;\r
-              break;\r
-\r
-                   case cmBO:\r
-              if (m_iSynFlags & noBO)\r
-                     Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
-              \r
-              if (m_lastTok.GetCode()==cmFUNC)\r
-                m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;\r
-              else\r
-                m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;\r
-\r
-              ++m_iBrackets;\r
-              break;\r
-\r
-                   case cmBC:\r
-              if (m_iSynFlags & noBC)\r
-                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
-\r
-              m_iSynFlags  = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;\r
-\r
-              if (--m_iBrackets<0)\r
-                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
-              break;\r
-\r
-        case cmELSE:\r
-              if (m_iSynFlags & noELSE)\r
-                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
-\r
-              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
-              break;\r
-\r
-        case cmIF:\r
-              if (m_iSynFlags & noIF)\r
-                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
-\r
-              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
-              break;\r
-\r
-                   default:      // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...\r
-              Error(ecINTERNAL_ERROR);\r
-        } // switch operator id\r
-\r
-        m_iPos += (int)len;\r
-        a_Tok.Set( (ECmdCode)i, pOprtDef[i] );\r
-        return true;\r
-           } // if operator string found\r
-    } // end of for all operator strings\r
-  \r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  bool ParserTokenReader::IsArgSep(token_type &a_Tok)\r
-  {\r
-    const char_type* szFormula = m_strFormula.c_str();\r
-\r
-    if (szFormula[m_iPos]==m_cArgSep)\r
-    {\r
-      // copy the separator into null terminated string\r
-      char_type szSep[2];\r
-      szSep[0] = m_cArgSep;\r
-      szSep[1] = 0;\r
-\r
-      if (m_iSynFlags & noARG_SEP)\r
-        Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);\r
-\r
-      m_iSynFlags  = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;\r
-      m_iPos++;\r
-      a_Tok.Set(cmARG_SEP, szSep);\r
-      return true;\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check for End of Formula.\r
-\r
-      \return true if an end of formula is found false otherwise.\r
-      \param a_Tok [out] If an eof is found the corresponding token will be stored there.\r
-      \throw nothrow\r
-      \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok\r
-  */\r
-  bool ParserTokenReader::IsEOF(token_type &a_Tok)\r
-  {\r
-    const char_type* szFormula = m_strFormula.c_str();\r
-\r
-    // check for EOF\r
-    if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)\r
-    {\r
-      if ( m_iSynFlags & noEND )\r
-        Error(ecUNEXPECTED_EOF, m_iPos);\r
-\r
-      if (m_iBrackets>0)\r
-        Error(ecMISSING_PARENS, m_iPos, _T(")"));\r
-\r
-      m_iSynFlags = 0;\r
-      a_Tok.Set(cmEND);\r
-      return true;\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a string position contains a unary infix operator. \r
-      \return true if a function token has been found false otherwise.\r
-  */\r
-  bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)\r
-  {\r
-    string_type sTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    // iteraterate over all postfix operator strings\r
-    funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();\r
-    for ( ; it!=m_pInfixOprtDef->rend(); ++it)\r
-    {\r
-      if (sTok.find(it->first)!=0)\r
-        continue;\r
-\r
-      a_Tok.Set(it->second, it->first);\r
-      m_iPos += (int)it->first.length();\r
-\r
-      if (m_iSynFlags & noINFIXOP) \r
-        Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
-\r
-      m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;\r
-      return true;\r
-    }\r
-\r
-    return false;\r
-\r
-/*\r
-    a_Tok.Set(item->second, sTok);\r
-    m_iPos = (int)iEnd;\r
-\r
-    if (m_iSynFlags & noINFIXOP) \r
-      Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
-\r
-    m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; \r
-    return true;\r
-*/\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check whether the token at a given position is a function token.\r
-      \param a_Tok [out] If a value token is found it will be placed here.\r
-      \throw ParserException if Syntaxflags do not allow a function at a_iPos\r
-      \return true if a function token has been found false otherwise.\r
-      \pre [assert] m_pParser!=0\r
-  */\r
-  bool ParserTokenReader::IsFunTok(token_type &a_Tok)\r
-  {\r
-    string_type strTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    funmap_type::const_iterator item = m_pFunDef->find(strTok);\r
-    if (item==m_pFunDef->end())\r
-      return false;\r
-\r
-    // Check if the next sign is an opening bracket\r
-    const char_type *szFormula = m_strFormula.c_str();\r
-    if (szFormula[iEnd]!='(')\r
-      return false;\r
-\r
-    a_Tok.Set(item->second, strTok);\r
-\r
-    m_iPos = (int)iEnd;\r
-    if (m_iSynFlags & noFUN)\r
-      Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());\r
-\r
-    m_iSynFlags = noANY ^ noBO;\r
-    return true;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a string position contains a binary operator.\r
-      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
-      \return true if an operator token has been found.\r
-  */\r
-  bool ParserTokenReader::IsOprt(token_type &a_Tok)\r
-  {\r
-    const char_type *const szExpr = m_strFormula.c_str();\r
-    string_type strTok;\r
-\r
-    int iEnd = ExtractOperatorToken(strTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    // Check if the operator is a built in operator, if so ignore it here\r
-    const char_type **const pOprtDef = m_pParser->GetOprtDef();\r
-    for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)\r
-    {\r
-      if (string_type(pOprtDef[i])==strTok)\r
-        return false;\r
-    }\r
-\r
-    // Note:\r
-    // All tokens in oprt_bin_maptype are have been sorted by their length\r
-    // Long operators must come first! Otherwise short names (like: "add") that\r
-    // are part of long token names (like: "add123") will be found instead \r
-    // of the long ones.\r
-    // Length sorting is done with ascending length so we use a reverse iterator here.\r
-    funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();\r
-    for ( ; it!=m_pOprtDef->rend(); ++it)\r
-    {\r
-      const string_type &sID = it->first;\r
-      if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )\r
-      {\r
-        a_Tok.Set(it->second, strTok);\r
-\r
-        // operator was found\r
-        if (m_iSynFlags & noOPT) \r
-        {\r
-          // An operator was found but is not expected to occur at\r
-          // this position of the formula, maybe it is an infix \r
-          // operator, not a binary operator. Both operator types\r
-          // can share characters in their identifiers.\r
-          if ( IsInfixOpTok(a_Tok) ) \r
-            return true;\r
-          else\r
-          {\r
-            // nope, no infix operator\r
-            return false;\r
-            //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); \r
-          }\r
-\r
-        }\r
-\r
-        m_iPos += (int)sID.length();\r
-        m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN;\r
-        return true;\r
-      }\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check if a string position contains a unary post value operator. */\r
-  bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)\r
-  {\r
-    // <ibg 20110629> Do not check for postfix operators if they are not allowed at\r
-    //                the current expression index.\r
-    //\r
-    //  This will fix the bug reported here:  \r
-    //\r
-    //  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979\r
-    //\r
-    if (m_iSynFlags & noPOSTOP)\r
-      return false;\r
-    // </ibg>\r
-\r
-    // Tricky problem with equations like "3m+5":\r
-    //     m is a postfix operator, + is a valid sign for postfix operators and \r
-    //     for binary operators parser detects "m+" as operator string and \r
-    //     finds no matching postfix operator.\r
-    // \r
-    // This is a special case so this routine slightly differs from the other\r
-    // token readers.\r
-    \r
-    // Test if there could be a postfix operator\r
-    string_type sTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    // iteraterate over all postfix operator strings\r
-    funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();\r
-    for ( ; it!=m_pPostOprtDef->rend(); ++it)\r
-    {\r
-      if (sTok.find(it->first)!=0)\r
-        continue;\r
-\r
-      a_Tok.Set(it->second, sTok);\r
-         m_iPos += (int)it->first.length();\r
-\r
-      m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;\r
-      return true;\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check whether the token at a given position is a value token.\r
-\r
-    Value tokens are either values or constants.\r
-\r
-    \param a_Tok [out] If a value token is found it will be placed here.\r
-    \return true if a value token has been found.\r
-  */\r
-  bool ParserTokenReader::IsValTok(token_type &a_Tok)\r
-  {\r
-    assert(m_pConstDef);\r
-    assert(m_pParser);\r
-\r
-    string_type strTok;\r
-    value_type fVal(0);\r
-    int iEnd(0);\r
-    \r
-    // 2.) Check for user defined constant\r
-    // Read everything that could be a constant name\r
-    iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
-    if (iEnd!=m_iPos)\r
-    {\r
-      valmap_type::const_iterator item = m_pConstDef->find(strTok);\r
-      if (item!=m_pConstDef->end())\r
-      {\r
-        m_iPos = iEnd;\r
-        a_Tok.SetVal(item->second, strTok);\r
-\r
-        if (m_iSynFlags & noVAL)\r
-          Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
-\r
-        m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
-        return true;\r
-      }\r
-    }\r
-\r
-    // 3.call the value recognition functions provided by the user\r
-    // Call user defined value recognition functions\r
-    std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();\r
-    for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)\r
-    {\r
-      int iStart = m_iPos;\r
-      if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )\r
-      {\r
-        // 2013-11-27 Issue 2:  https://code.google.com/p/muparser/issues/detail?id=2\r
-        strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart);\r
-\r
-        if (m_iSynFlags & noVAL)\r
-          Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
-\r
-        a_Tok.SetVal(fVal, strTok);\r
-        m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;\r
-        return true;\r
-      }\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check wheter a token at a given position is a variable token. \r
-      \param a_Tok [out] If a variable token has been found it will be placed here.\r
-           \return true if a variable token has been found.\r
-  */\r
-  bool ParserTokenReader::IsVarTok(token_type &a_Tok)\r
-  {\r
-    if (m_pVarDef->empty())\r
-      return false;\r
-\r
-    string_type strTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    varmap_type::const_iterator item =  m_pVarDef->find(strTok);\r
-    if (item==m_pVarDef->end())\r
-      return false;\r
-\r
-    if (m_iSynFlags & noVAR)\r
-      Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
-\r
-    m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);\r
-\r
-    m_iPos = iEnd;\r
-    a_Tok.SetVar(item->second, strTok);\r
-    m_UsedVar[item->first] = item->second;  // Add variable to used-var-list\r
-\r
-    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;\r
-\r
-//  Zur Info hier die SynFlags von IsVal():\r
-//    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
-    return true;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)\r
-  {\r
-    if (!m_pStrVarDef || m_pStrVarDef->empty())\r
-      return false;\r
-\r
-    string_type strTok;\r
-    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
-    if (iEnd==m_iPos)\r
-      return false;\r
-\r
-    strmap_type::const_iterator item =  m_pStrVarDef->find(strTok);\r
-    if (item==m_pStrVarDef->end())\r
-      return false;\r
-\r
-    if (m_iSynFlags & noSTR)\r
-      Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
-\r
-    m_iPos = iEnd;\r
-    if (!m_pParser->m_vStringVarBuf.size())\r
-      Error(ecINTERNAL_ERROR);\r
-\r
-    a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );\r
-\r
-    m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP);\r
-    return true;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check wheter a token at a given position is an undefined variable. \r
-\r
-      \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.\r
-           \return true if a variable token has been found.\r
-      \throw nothrow\r
-  */\r
-  bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)\r
-  {\r
-    string_type strTok;\r
-    int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );\r
-    if ( iEnd==m_iPos )\r
-      return false;\r
-\r
-    if (m_iSynFlags & noVAR)\r
-    {\r
-      // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the \r
-      //                 token identifier. \r
-      // related bug report:\r
-      // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979\r
-      Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);\r
-    }\r
-\r
-    // If a factory is available implicitely create new variables\r
-    if (m_pFactory)\r
-    {\r
-      value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);\r
-      a_Tok.SetVar(fVar, strTok );\r
-\r
-      // Do not use m_pParser->DefineVar( strTok, fVar );\r
-      // in order to define the new variable, it will clear the\r
-      // m_UsedVar array which will kill previousely defined variables\r
-      // from the list\r
-      // This is safe because the new variable can never override an existing one\r
-      // because they are checked first!\r
-      (*m_pVarDef)[strTok] = fVar;\r
-      m_UsedVar[strTok] = fVar;  // Add variable to used-var-list\r
-    }\r
-    else\r
-    {\r
-      a_Tok.SetVar((value_type*)&m_fZero, strTok);\r
-      m_UsedVar[strTok] = 0;  // Add variable to used-var-list\r
-    }\r
-\r
-    m_iPos = iEnd;\r
-\r
-    // Call the variable factory in order to let it define a new parser variable\r
-    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;\r
-    return true;\r
-  }\r
-\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Check wheter a token at a given position is a string.\r
-      \param a_Tok [out] If a variable token has been found it will be placed here.\r
-         \return true if a string token has been found.\r
-      \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok\r
-      \throw nothrow\r
-  */\r
-  bool ParserTokenReader::IsString(token_type &a_Tok)\r
-  {\r
-    if (m_strFormula[m_iPos]!='"') \r
-      return false;\r
-\r
-    string_type strBuf(&m_strFormula[m_iPos+1]);\r
-    std::size_t iEnd(0), iSkip(0);\r
-\r
-    // parser over escaped '\"' end replace them with '"'\r
-    for(iEnd=(int)strBuf.find( _T('\"') ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T('\"'), iEnd))\r
-    {\r
-      if (strBuf[iEnd-1]!='\\') break;\r
-      strBuf.replace(iEnd-1, 2, _T("\"") );\r
-      iSkip++;\r
-    }\r
-\r
-    if (iEnd==string_type::npos)\r
-      Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );\r
-\r
-    string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);\r
-\r
-    if (m_iSynFlags & noSTR)\r
-      Error(ecUNEXPECTED_STR, m_iPos, strTok);\r
-\r
-               m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer\r
-    a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());\r
-\r
-    m_iPos += (int)strTok.length() + 2 + (int)iSkip;  // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen\r
-    m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );\r
-\r
-    return true;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  /** \brief Create an error containing the parse error position.\r
-\r
-    This function will create an Parser Exception object containing the error text and its position.\r
-\r
-    \param a_iErrc [in] The error code of type #EErrorCodes.\r
-    \param a_iPos [in] The position where the error was detected.\r
-    \param a_strTok [in] The token string representation associated with the error.\r
-    \throw ParserException always throws thats the only purpose of this function.\r
-  */\r
-  void  ParserTokenReader::Error( EErrorCodes a_iErrc, \r
-                                  int a_iPos, \r
-                                  const string_type &a_sTok) const\r
-  {\r
-    m_pParser->Error(a_iErrc, a_iPos, a_sTok);\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  void ParserTokenReader::SetArgSep(char_type cArgSep)\r
-  {\r
-    m_cArgSep = cArgSep;\r
-  }\r
-\r
-  //---------------------------------------------------------------------------\r
-  char_type ParserTokenReader::GetArgSep() const\r
-  {\r
-    return m_cArgSep;\r
-  }\r
-} // namespace mu\r
-\r
similarity index 82%
rename from bundled/muparser_v2_2_4/Changes.txt
rename to bundled/muparser_v2_3_3/CHANGELOG
index 08d4dc7b3b79915cacf7517fdf3cecfcfeb4140d..3ad1916840359569bd2bab068dd71467e213ff24 100644 (file)
-#######################################################################\r
-#                                                                     #\r
-#                                                                     #\r
-#                 __________                                          #\r
-#    _____   __ __\______   \_____  _______  ______  ____ _______     #\r
-#   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \    #\r
-#  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/    #\r
-#  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|       #\r
-#        \/                       \/            \/      \/            #\r
-#                                        Fast math parser Library    #\r
-#                                                                     #\r
-#  Copyright (C) 2014 Ingo Berg                                       #\r
-#                                                                     #\r
-#  Web:     muparser.beltoforion.de                                   #\r
-#  e-mail:  muparser@beltoforion.de                                   #\r
-#                                                                     #\r
-#                                                                     #\r
-#######################################################################\r
\r
-\r
-History:\r
---------\r
-\r
-Rev 2.2.4: 02.10.2014\r
----------------------\r
-  Changes:\r
-   * explicit positive sign allowed\r
-\r
-  Bugfixes:\r
-   * Fix for Issue 6 (https://code.google.com/p/muparser/issues/detail?id=6)\r
-   * String constants did not work properly. Using more than a single one \r
-     was impossible.\r
-   * Project Files for VS2008 and VS2010 removed from the repository \r
-   * Fix for Issue 4 (https://code.google.com/p/muparser/issues/detail?id=4)\r
-   * Fix for VS2013 64 bit build option\r
-   * return type of ParserError::GetPos changed to int\r
-   * OpenMP support enabled in the VS2013 project files and precompiled windows DLL's\r
-   * Bulkmode did not evaluate properly if "=" and "," operator was used in the expression\r
-       \r
-Rev 2.2.3: 22.12.2012\r
----------------------\r
-\r
-  Removed features:\r
-   * build files for msvc2005, borland and watcom compiler were removed\r
-\r
-  Bugfixes:\r
-   * Bugfix for Intel Compilers added: The power operator did not work properly \r
-     with Intel C++ composer XE 2011.\r
-     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)\r
-   * Issue 3509860: Callbacks of functions with string parameters called twice\r
-     (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)\r
-   * Issue 3570423: example1 shows slot number in hexadecimal\r
-     (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)\r
-   * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:\r
-       - division by zero in constant expressions was reported with the code "ec_GENERIC" \r
-          instead of "ecDIV_BY_ZERO"\r
-        - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions\r
-\r
-\r
-Rev 2.2.2: 18.02.2012\r
----------------------\r
-  Bugfixes:\r
-   * Optimizer did'nt work properly for division:\r
-     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)\r
-\r
-Rev 2.2.1: 22.01.2012\r
----------------------\r
-  Bugfixes:\r
-   * Optimizer bug in 64 bit systems fixed\r
-     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)\r
-        \r
-Rev 2.2.0: 22.01.2012\r
----------------------\r
-  Improvements:\r
-   * Optimizer rewritten and improved. In general: more optimizations are \r
-     now applied to the bytecode. The downside is that callback Functions \r
-     can no longer be flagged as non-optimizable. (The flag is still present \r
-     but ignored) This is necessary since the optimizer had to call the \r
-     functions in order to precalculate the result (see Bugfixes). These calls \r
-     posed a problems for callback functions with side  effects and if-then-else \r
-     clauses in general since they undermined the shortcut evaluation prinziple.\r
-\r
-  Bugfixes:\r
-   * Infix operators where not properly detected in the presence of a constant \r
-     name starting with an underscore which is a valid character for infix \r
-     operators too (i.e. "-_pi").\r
-   * Issue 3463353: Callback functions are called twice during the first call to eval.\r
-   * Issue 3447007: GetUsedVar unnecessaryly executes callback functions.\r
-\r
-\r
-Rev 2.1.0: 19.11.2011\r
----------------------\r
-  New feature:\r
-   * Function atan2 added\r
-\r
-  Bugfixes:\r
-   * Issue 3438380:  Changed behaviour of tellg with GCC >4.6 led to failures  \r
-                     in value detection callbacks.\r
-   * Issue 3438715:  only "double" is a valid MUP_BASETYPE \r
-                     MUP_BASETYPE can now be any of:\r
-                       float, \r
-                       double, \r
-                       long double, \r
-                       short, \r
-                       unsigned short, \r
-                       unsigned int, \r
-                       long,\r
-                       unsigned long. \r
-                     Previousely only floating point types were allowed. \r
-                     Using "int" is still not allowed!\r
-   * Compiler issues with GCC 4.6 fixed\r
-   * Custom value recognition callbacks added with AddValIdent had lower\r
-     priority than built in functions. This was causing problems with \r
-     hex value recognition since detection of non hex values had priority\r
-     over the detection of hex values. The "0" in the hex prefix "0x" would \r
-     be read as a separate non-hex number leaving the rest of the expression\r
-     unparseable.\r
-\r
-Rev 2.0.0: 04.09.2011\r
----------------------\r
-This release introduces a new version numbering scheme in order to make\r
-future changes in the ABI apparent to users of the library. The number is\r
-now based on the SONAME property as used by GNU/Linux. \r
-\r
-  Changes:\r
-   * Beginning with this version all version numbers will be SONAME compliant\r
-   * Project files for MSVC2010 added\r
-   * Project files for MSVC2003 removed\r
-   * Bytecode parsing engine cleaned up and rewritten\r
-   * Retrieving all results of expressions made up of comma separate \r
-     subexpressions is now possible with a new Eval overload.\r
-   * Callback functions with fixed number of arguments can now have up to 10 \r
-     Parameters (previous limit was 5)\r
-\r
-  New features:\r
-   * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )\r
-   * new intrinsic binary operators: "&&", "||" (logical and, or)\r
-   * A new bulkmode allows submitting large arrays as variables to compute large \r
-     numbers of expressions with a single call. This can drastically improve \r
-     parsing performance when interfacing the library from managed languages like \r
-     C#. (It doesn't bring any performance benefit for C++ users though...)\r
-\r
-  Removed features:\r
-   * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let \r
-     users the freedom of defining them on their own versions (either as logical or bitwise \r
-     operators).\r
-   * Implementation for complex numbers removed. This was merely a hack. If you \r
-     need complex numbers try muParserX which provides native support for them.\r
-     (see: http://beltoforion.de/muparserx/math_expression_parser_en.html)\r
-\r
-  Bugfixes:\r
-   * User defined operators could collide with built in operators that entirely \r
-     contained their identifier. i.e. user defined "&" would not work with the built \r
-     in "&&" operator since the user defined operator was detected with a higher \r
-     priority resulting in a syntax error.\r
-   * Detection of unknown variables did not work properly in case a postfix operator\r
-     was defined which was part of the undefined variable.\r
-     i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did\r
-     not detect "multi" as an undefined variable.\r
-     (Reference:  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)\r
-   * Postfix operators sharing the first few characters were causing bogus parsing exception.\r
-     (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)\r
-\r
-Rev 1.34: 04.09.2010\r
---------------------\r
-  Changes:\r
-   * The prefix needed for parsing hex values is now "0x" and no longer "$". \r
-   * AddValIdent reintroduced into the DLL interface\r
-\r
-  New features:\r
-   * The associativity of binary operators can now be changed. The pow operator \r
-     is now right associative. (This is what Mathematica is using) \r
-   * Seperator can now be used outside of functions. This allows compound \r
-     expressions like:\r
-     "a=10,b=20,c=a*b" The last "argument" will be taken as the return value\r
-\r
-  Bugfixes:    \r
-   * The copy constructor did not copy binary operator definitions. Those were lost\r
-     in the copied parser instance.\r
-   * Mixing special characters and alphabetic characters in binary operator names \r
-     led to inconsistent parsing behaviour when parsing expressions like "a ++ b" \r
-     and "a++b" when "++" is defined as a binary operator. Binary operators must \r
-     now consist entirely of special characters or of alphabetic ones.\r
-     (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)\r
-   * User defined operators were not exactly handled like built in operators. This \r
-     led to inconsistencies in expression evaluation when using them. The results \r
-     differed due to slightly different precedence rules.\r
-   * Using empty string arguments ("") would cause a crash of muParser\r
-\r
-\r
-Rev 1.32: 29.01.2010 \r
---------------------\r
-\r
-  Changes:\r
-   * "example3" renamed to "example2"\r
-   * Project/Makefiles files are now provided for:\r
-           - msvc2003 \r
-           - msvc2005 \r
-           - msvc2008\r
-           - watcom   (makefile)\r
-           - mingw    (makefile)\r
-           - bcc      (makefile)\r
-   * Project files for borland cpp builder were removed\r
-\r
-\r
-  New features:\r
-   * Added function returning muparsers version number\r
-   * Added function for resetting the locale\r
-\r
-\r
-  Bugfixes:    \r
-   * Changes example1 in order to fix issues with irritating memory leak reports. \r
-     Added conditional code for memory leak detection with MSVC in example1.\r
-     (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)\r
-   * Fixed some warnings for gcc\r
-\r
-\r
-\r
-Rev 1.31cp: 15.01.2010  (Maintainance release for CodeProject)\r
-----------------------\r
-\r
-  Changes:\r
-   * Archive structure changed\r
-   * C# wrapper added\r
-   * Fixed issued that prevented compiling with VS2010 Beta2\r
-    \r
-\r
-Rev 1.30: 09.06.2008\r
---------------------\r
-\r
-  Changes:\r
-   * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.\r
-\r
-  New features:\r
-   * Setting thousands separator and decimal separator is now possible\r
-\r
-  Bugfixes:\r
-   * The dll interface did not provide a callback for functions without any arguments.  \r
-       \r
-\r
-Rev 1.29: Januar 2008\r
----------------------\r
-\r
-  Unrelease Version available only via SVN.\r
-\r
-\r
-Rev 1.28: 02. July, 2007\r
----------------------------\r
\r
-  Library changes:\r
-  * Interface for the dynamic library changed and extended to create an interface \r
-    using pure C functions only. \r
-  * mupInit() removed\r
-\r
-  Build system:\r
-   * MSVC7 Project files removed in favor of MSVC8\r
-\r
-  Bugfixes:\r
-   * The dynamic library did not build on other systems than linux due to a misplaced \r
-     preprocessor definition. This is fixed now.\r
-\r
-\r
-Rev 1.27:\r
----------------------------\r
-\r
-  Build system:\r
-   * Modified build\ directory layout introducing some subfolders \r
-     for the various IDE supported\r
-   * Project files for BCB and MSVC7 added\r
-   * Switched to use bakefile 0.2.1 which now correctly creates the \r
-     "make uninstall" target for autoconf's Makefile.in\r
-   * Now the library debug builds are named "muparserd" instead of "muparser"\r
-     to allow multiple mixed release/debug builds to coexist; so e.g. on Windows\r
-     when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"\r
-\r
-  New Features:\r
-   * Factory functions can now take a user defined pointer\r
-   * String functions can now be used with up to two additional \r
-     double parameters\r
-   * Support for UNICODE character types added\r
-   * Infix operator priority can now be changed by the user\r
-\r
-  Bugfixes:\r
-   * An internal error was raised when evaluating an empty \r
-     expressions\r
-   * The error message raised in case of name collisions between \r
-     implicitely defined variables and postfix operators did contain\r
-     misleading data.\r
-\r
-\r
-Rev 1.26: (unofficial release)\r
-------------------------------\r
-\r
-  New Features:\r
-   * Unary operator precedence can now be changed by the user.\r
-\r
-\r
-Rev 1.25: 5. February, 2006\r
----------------------------\r
-\r
-  Build system: (special thanks to Francesco Montorsi for implementing it!)\r
-    * created a bakefile-based build system which adds support for the following win32 compilers:\r
-      -> MS visual C++ (6 and .NET)\r
-      -> BorlandC++ (5 or greater)\r
-      -> Mingw32 (tested with gcc 3.2)\r
-      -> Watcom (not tested)\r
-      and for GCC on Unix (using a standard autoconf's configure script).\r
-\r
-  Compatibility improvements:\r
-    * fixed some small warnings when using -Wall with GCC on Unix\r
-    * added inclusion guards for win32-specific portions of code\r
-    * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.\r
-\r
-\r
-Rev 1.24: 29. October, 2005\r
----------------------------\r
-\r
-Changes:\r
-\r
-  Compatibility improvements:\r
-    * parser now works on 64 bit compilers\r
-    * (bytecode base datatype can now be changed freely)\r
-\r
-\r
-Rev 1.23: 19. October, 2005\r
----------------------------\r
-\r
-Changes:\r
-\r
-  Bugfixes:\r
-    * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.\r
-\r
-  New features:\r
-    * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6\r
-\r
-\r
-Rev 1.22: October, 2005\r
------------------------\r
-\r
-Release notes:\r
-\r
-All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with\r
-gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. \r
-This should make the code cleaner. The Borland Project files were removed. If you want to use it \r
-with Borland either use the dll version or create your own project files. I can't support it since I don't \r
-have this compiler at hand.\r
-\r
-Changes:\r
-\r
-  Project Changes:\r
-    * Borland project files removed\r
-      (The code should still compile with BCB but I cant provide you with project files)\r
-\r
-  Internal Changes:\r
-    * unnecessary template files have been removed:\r
-        - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp\r
-        - removed Files: muIParserTypes.h\r
-\r
-\r
-Rev 1.2 / 1.21: April, 2005\r
----------------------------\r
-\r
-Release Notes:\r
-First of all the interface has changed so this version is not backwards compatible.\r
-After receiving a couple of questions about it, this version features support for\r
-user defined binary operators. Consequently the built in operators can now be \r
-turned off, thus you can deactivate them and write complete customized parser\r
-subclasses that only contain the functionality you want. Another new feature is \r
-the introduction of callback functions taking string arguments, implicit \r
-generation of variables and the Assignement operator.\r
-\r
-  Functionality\r
-    * New built in operator: xor; Logical xor.\r
-    * New built in operator: Assignement operator; Defining variables in terms of \r
-                             other variables/constants\r
-    * New feature: Strings as arguments for callback functions\r
-    * New feature: User defined binary operators\r
-    * New feature: ParserInt a class with a sample implementation for\r
-                     integer numbers.\r
-    * New feature: Callbacks to value regognition functions.\r
-\r
-    * Removed:  all predefined postfix operators have been removed.\r
-    * New project file:  Now comes with a ready to use windows DLL.\r
-    * New project file:  Makefile for cygwin now included.\r
-    * New example:  Example3 shows usage of the DLL.\r
-\r
-  Interface changes\r
-    * New member function: DefineOprt For adding user defined binary operators.\r
-    * New member function: EnableBuiltInOprt(bool) Enables/Disables built in \r
-                           binary operators.\r
-    * New member function: AddValIdent(...) to add callbacks for custom value \r
-                           recognition functions.\r
-    * Removed: SetVar(), SetConst().\r
-    * Renamed: Most interface functions have been renamed\r
-    * Changed: The type for multiargument callbacks multfun_type has changed. \r
-               It no longer takes a std::vector as input.\r
-\r
-  Internal changes\r
-    * new class muParserTokenReader.h encapsulates the token identification \r
-      and token assignement.\r
-    * Internal handling of function callbacks unified as a result the performance \r
-      of the bytecode evaluation increased.\r
-\r
-\r
-Rev 1.10 : December 30, 2004\r
-----------------------------\r
-\r
-Release Notes:\r
-This version does not contain major new feature compared to V1.07 but its internal structure has\r
-changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode\r
-parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you\r
-can change its value datatype. It should work on 64-bit systems. For this reason I supply both\r
-versions for download. If you use V1.07 and are happy with it there is no need for updating\r
-your version.\r
-\r
-    * New example program: Archive now contains two demo programs: One for standard C++ and one for\r
-                           managed C++.\r
-    * New member function: RemoveVar(...) can be used for removing a single variable from the internal \r
-                           storage.\r
-    * New member function: GetVar() can be used for querying the variable names and pointers of all\r
-                           variables defined in the parser.\r
-    * New member function: GetConst() can be used for querying all defined constants and their values.\r
-    * New member function: GetFunDef() can be used for querying all defined functions and the number of\r
-                           arguments they expect.\r
-    * Internal structure changed; hanging base datatype at compile time is now possible.\r
-    * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
-    * Bugfix: Variable names must will now be tested if they conflict with constant or function names.\r
-    * Internal change:  Removed most dependencies from the C-string libraries.\r
-    * Internal change:  Bytecode is now stored in a separate class: ParserByteCode.h\r
-    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.\r
-    * Internal change:  Error treatment changed. ParserException is no longer derived from\r
-                        std::runtime_error; Internal treatment of Error messages changed.\r
-    * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
-                        they are used for defining the charset allowed for variable-, operator- and\r
-                        function names.\r
-\r
-\r
-Rev 1.09 : November 20, 2004\r
-----------------------------\r
-\r
-    * New member function:  RemoveVar(...) can be used for removing a single variable from the internal \r
-                            storage.\r
-    * Internal structure changed; changing base datatype at compile time is now possible.\r
-    * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
-    * Internal change:  Removed most dependencies from the C-string libraries.\r
-    * Internal change:  Bytecode is now stored in a seperate class: ParserByteCode.h.\r
-    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.\r
-    * Internal change:  Error treatment changed. ParserException is no longer derived from \r
-                        std::runtime_error; Internal treatment of Error messages changed.\r
-    * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
-      they are used for defining the charset allowed for variable-, operator- and function names.\r
-\r
-\r
-Rev 1.08 : November, 2004 \r
--------------------------\r
-\r
-    * unpublished; experimental template version with respect to data type and underlying string\r
-      type (string <-> widestring). The idea was dropped...\r
-\r
-\r
-Rev 1.07 : September 4 2004\r
----------------------------\r
-\r
-    * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some\r
-      issues left.\r
-    * Improved portability; Changes in order to allow compiling on BCB.\r
-    * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with\r
-      respect to a certain variable; added in muParser.h.\r
-\r
-\r
-Rev 1.06 : August 20 2004\r
--------------------------\r
-\r
-    * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter\r
-      indicating that the function can not be optimized.\r
-    * Internal changes: muParserStack.h simplified; refactorings\r
-    * Parser is now distributed under the MIT License; all comments changed accordingly.\r
-\r
-\r
-Rev 1.05 : August 20 2004\r
--------------------------\r
-\r
-    * Variable/constant names will now be checked for invalid characters.\r
-    * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().\r
-    * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).\r
-    * Predefined functions with variable number of arguments added: sum, avg, min, max.\r
-    * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().\r
-    * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().\r
-    * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.\r
-    * Internal changes: static array removed in Command code calculation routine; misc. changes.\r
-\r
-\r
-Rev 1.04 : August 16 2004\r
--------------------------\r
-\r
-    * Support for functions with variable number of arguments added.\r
-    * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;\r
-      changed: Parser.h, Parser.cpp.\r
-    * Bug in the bytecode calculation function fixed (affected the unary minus operator).\r
-    * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).\r
-\r
-\r
-Rev 1.03 : August 10 2004\r
--------------------------\r
-\r
-    * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),\r
-      ClearPostOp().\r
-    * Minor changes to the bytecode parsing routine.\r
-    * User defined functions can now have up to four parameters.\r
-    * Performance optimized: simple formula optimization added; (precalculation of constant parts of the\r
-      expression).\r
-    * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.\r
-\r
-\r
-Rev 1.02 : July 30 2004\r
------------------------\r
-\r
-    * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),\r
-      ClearConst().\r
-    * Single variables can now be added using AddVar(); you have now the choice of adding them either\r
-      one by one or all at the same time using SetVar(const varmap_type &a_vVar).\r
-    * Internal handling of variables changed, is now similar to function handling.\r
-    * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to\r
-      derive new parsers with a modified set of default functions and constants.\r
-    * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold\r
-      function parameter count.\r
-\r
-\r
-Rev 1.01 : July 23 2004\r
------------------------\r
-\r
-    * Support for user defined functions has been added; new functions: AddFun(), ClearFun(),\r
-      InitFunctions().\r
-    * Built in constants have been removed; the parser contained undocumented built in\r
-      constants pi, e.\r
-      There was the possibility of name conflicts with user defined variables.\r
-    * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only\r
-      argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3\r
-      arguments (array of names, array of pointers, and array length) is now marked as deprecated.\r
-    * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for\r
-      base 10, and ln for base e.\r
-\r
-\r
-Rev 1.00 : July 21 2004\r
------------------------\r
-\r
-    * Initial release\r
+
+     _____  __ _____________ _______  ______ ___________
+    /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+         \/      |__|       \/           \/     \/
+    Copyright (C) 2004 - 2020 Ingo Berg
+
+=======================================================================
+    https://beltoforion.de/en/muparser
+=======================================================================
+
+History:
+--------
+
+GitHub Master
+---------------------
+  Build System Changes (CMake):
+   * Added a new option "-DENABLE_WIDE_CHAR" to CMake for building muparser with wide character support
+   
+  Compiler Warnings fixed/disabled (Visual Studio):
+   * Disabled compiler warning 26812 (Prefer 'enum class' over 'enum')
+     I consider this a bogus warning. Use of plain old enums has not been deprecated and only MSVC is complaining. 
+   * Disabled compiler warning 4251 (... needs to have dll-interface to be used by clients of class ...)
+     When the build system was changed to CMake Linux and Windows builds were unified. Each dynamic library contains the 
+     class interface as well as the C-interface. Before the linux shared library was using the class interface and the 
+     windows dll was using the C-interface.
+    
+     Only the C-Interface is safe to use when you intent to bring an executable to another linux distribution or windows version! 
+     This is up to the client software. I cannot change this because on linux the shared library was always using the class 
+     interface. Usually this is not a problem since distributions compile all applications from scratch. 
+
+     If you use the class interface you can not take for granted that your software will run with a muparser 
+     version compiled for another operating system or linux distribution! You must either use the C-Interface if you 
+     want this or use a static library build of muparser!
+
+  Security Fixes: (The issues were present in all prior stable releases)
+   * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24167 
+   * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24355
+   
+  Bugfixes:
+   * fixed a couple of issues for building the C-Interface (muParserDLL.cpp/.h) with wide character support.
+
+Rev 2.3.2: 17.06.2020
+---------------------
+  API-Change Revertion (to 2.3.0):
+   * removed final keyword from Parser class (added in 2.3.0) as this was breaking existing Applications
+
+  Changes:
+   * made Parser class final
+   * using OpenMP is now the default settings for cmake based builds
+   * added optimization for trivial expressions. (Expressions whose RPN only has a single entry)
+   * introduced a maximum length for expressions (5000 Character)
+   * introduced a maximum length for identifiers (100 Characters)
+   * removed the MUP_MATH_EXCEPTION macro and related functionality. (C++ exceptions for divide by zero or sqrt of a negative number are no longer supported)
+   * removed ParserStack.h (replaced with std::stack)
+   * removed macros for defining E and PI (replaced with a static constants)
+   * source code is now aimed at C++17
+   * the MUP_ASSERT macro is no longer removed in release builds for better protection against segmentation faults
+
+  Security Fixes: (The issues were present in all prior stable releases)
+   * Prevented multiple access violations for malformed expressions with if then else and functions taking multiple arguments like "sum(0?1,2,3,4:5)"
+          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23330
+          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22922
+          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22938
+          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23330
+          * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23410
+   * Added additional runtime checks for release builds to prevent segmentation faults for invalid expressions
+
+  Bugfixes:
+   * Fixed an issue where the bulk mode could hang on GCC/CLANG builds due to OpenMP chunksize dropping below 1.
+
+Rev 2.3.0 - 2.3.1:
+------------------
+Short lived releases or prereleases that were replaced by 2.3.2 almost instantly due to API breaking changes. Version 2.3.2 is the successor to version 2.2.6
+
+Rev 2.2.6: 04.10.2018
+---------------------
+  Changes:
+   * Build system is now based on cmake
+   * several compiler warnings fixed
+
+Rev 2.2.5: 27.04.2015
+---------------------
+  Changes:
+   * example2 extended to work with UNICODE character set
+   * Applied patch from Issue 9
+   
+  Bugfixes:
+   * muChar_t in muParserDLL.h was not set properly when UNICODE was used
+   * muparser.dll did not build on UNICODE systems
+   
+Rev 2.2.4: 02.10.2014
+---------------------
+  Changes:
+   * explicit positive sign allowed
+
+  Bugfixes:
+   * Fix for Issue 6 (https://code.google.com/p/muparser/issues/detail?id=6)
+   * String constants did not work properly. Using more than a single one 
+     was impossible.
+   * Project Files for VS2008 and VS2010 removed from the repository 
+   * Fix for Issue 4 (https://code.google.com/p/muparser/issues/detail?id=4)
+   * Fix for VS2013 64 bit build option
+   * return type of ParserError::GetPos changed to int
+   * OpenMP support enabled in the VS2013 project files and precompiled windows DLL's
+   * Bulkmode did not evaluate properly if "=" and "," operator was used in the expression
+       
+Rev 2.2.3: 22.12.2012
+---------------------
+
+  Removed features:
+   * build files for msvc2005, borland and watcom compiler were removed
+
+  Bugfixes:
+   * Bugfix for Intel Compilers added: The power operator did not work properly 
+     with Intel C++ composer XE 2011.
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)
+   * Issue 3509860: Callbacks of functions with string parameters called twice
+     (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)
+   * Issue 3570423: example1 shows slot number in hexadecimal
+     (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)
+   * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:
+       - division by zero in constant expressions was reported with the code "ec_GENERIC" 
+          instead of "ecDIV_BY_ZERO"
+        - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions
+
+
+Rev 2.2.2: 18.02.2012
+---------------------
+  Bugfixes:
+   * Optimizer did'nt work properly for division:
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)
+
+Rev 2.2.1: 22.01.2012
+---------------------
+  Bugfixes:
+   * Optimizer bug in 64 bit systems fixed
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)
+        
+Rev 2.2.0: 22.01.2012
+---------------------
+  Improvements:
+   * Optimizer rewritten and improved. In general: more optimizations are 
+     now applied to the bytecode. The downside is that callback Functions 
+     can no longer be flagged as non-optimizable. (The flag is still present 
+     but ignored) This is necessary since the optimizer had to call the 
+     functions in order to precalculate the result (see Bugfixes). These calls 
+     posed a problems for callback functions with side  effects and if-then-else 
+     clauses in general since they undermined the shortcut evaluation prinziple.
+
+  Bugfixes:
+   * Infix operators where not properly detected in the presence of a constant 
+     name starting with an underscore which is a valid character for infix 
+     operators too (i.e. "-_pi").
+   * Issue 3463353: Callback functions are called twice during the first call to eval.
+   * Issue 3447007: GetUsedVar unnecessaryly executes callback functions.
+
+
+Rev 2.1.0: 19.11.2011
+---------------------
+  New feature:
+   * Function atan2 added
+
+  Bugfixes:
+   * Issue 3438380:  Changed behaviour of tellg with GCC >4.6 led to failures  
+                     in value detection callbacks.
+   * Issue 3438715:  only "double" is a valid MUP_BASETYPE 
+                     MUP_BASETYPE can now be any of:
+                       float, 
+                       double, 
+                       long double, 
+                       short, 
+                       unsigned short, 
+                       unsigned int, 
+                       long,
+                       unsigned long. 
+                     Previousely only floating point types were allowed. 
+                     Using "int" is still not allowed!
+   * Compiler issues with GCC 4.6 fixed
+   * Custom value recognition callbacks added with AddValIdent had lower
+     priority than built in functions. This was causing problems with 
+     hex value recognition since detection of non hex values had priority
+     over the detection of hex values. The "0" in the hex prefix "0x" would 
+     be read as a separate non-hex number leaving the rest of the expression
+     unparseable.
+
+Rev 2.0.0: 04.09.2011
+---------------------
+This release introduces a new version numbering scheme in order to make
+future changes in the ABI apparent to users of the library. The number is
+now based on the SONAME property as used by GNU/Linux. 
+
+  Changes:
+   * Beginning with this version all version numbers will be SONAME compliant
+   * Project files for MSVC2010 added
+   * Project files for MSVC2003 removed
+   * Bytecode parsing engine cleaned up and rewritten
+   * Retrieving all results of expressions made up of comma separate 
+     subexpressions is now possible with a new Eval overload.
+   * Callback functions with fixed number of arguments can now have up to 10 
+     Parameters (previous limit was 5)
+
+  New features:
+   * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )
+   * new intrinsic binary operators: "&&", "||" (logical and, or)
+   * A new bulkmode allows submitting large arrays as variables to compute large 
+     numbers of expressions with a single call. This can drastically improve 
+     parsing performance when interfacing the library from managed languages like 
+     C#. (It doesn't bring any performance benefit for C++ users though...)
+
+  Removed features:
+   * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let 
+     users the freedom of defining them on their own versions (either as logical or bitwise 
+     operators).
+   * Implementation for complex numbers removed. This was merely a hack. If you 
+     need complex numbers try muParserX which provides native support for them.
+     (see: http://beltoforion.de/muparserx/math_expression_parser_en.html)
+
+  Bugfixes:
+   * User defined operators could collide with built in operators that entirely 
+     contained their identifier. i.e. user defined "&" would not work with the built 
+     in "&&" operator since the user defined operator was detected with a higher 
+     priority resulting in a syntax error.
+   * Detection of unknown variables did not work properly in case a postfix operator
+     was defined which was part of the undefined variable.
+     i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did
+     not detect "multi" as an undefined variable.
+     (Reference:  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)
+   * Postfix operators sharing the first few characters were causing bogus parsing exception.
+     (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)
+
+Rev 1.34: 04.09.2010
+--------------------
+  Changes:
+   * The prefix needed for parsing hex values is now "0x" and no longer "$". 
+   * AddValIdent reintroduced into the DLL interface
+
+  New features:
+   * The associativity of binary operators can now be changed. The pow operator 
+     is now right associative. (This is what Mathematica is using) 
+   * Separator can now be used outside of functions. This allows compound 
+     expressions like:
+     "a=10,b=20,c=a*b" The last "argument" will be taken as the return value
+
+  Bugfixes:    
+   * The copy constructor did not copy binary operator definitions. Those were lost
+     in the copied parser instance.
+   * Mixing special characters and alphabetic characters in binary operator names 
+     led to inconsistent parsing behaviour when parsing expressions like "a ++ b" 
+     and "a++b" when "++" is defined as a binary operator. Binary operators must 
+     now consist entirely of special characters or of alphabetic ones.
+     (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)
+   * User defined operators were not exactly handled like built in operators. This 
+     led to inconsistencies in expression evaluation when using them. The results 
+     differed due to slightly different precedence rules.
+   * Using empty string arguments ("") would cause a crash of muParser
+
+
+Rev 1.32: 29.01.2010 
+--------------------
+
+  Changes:
+   * "example3" renamed to "example2"
+   * Project/Makefiles files are now provided for:
+           - msvc2003 
+           - msvc2005 
+           - msvc2008
+           - watcom   (makefile)
+           - mingw    (makefile)
+           - bcc      (makefile)
+   * Project files for borland cpp builder were removed
+
+
+  New features:
+   * Added function returning muparsers version number
+   * Added function for resetting the locale
+
+
+  Bugfixes:    
+   * Changes example1 in order to fix issues with irritating memory leak reports. 
+     Added conditional code for memory leak detection with MSVC in example1.
+     (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)
+   * Fixed some warnings for gcc
+
+
+
+Rev 1.31cp: 15.01.2010  (Maintenance release for CodeProject)
+----------------------
+
+  Changes:
+   * Archive structure changed
+   * C# wrapper added
+   * Fixed issued that prevented compiling with VS2010 Beta2
+    
+
+Rev 1.30: 09.06.2008
+--------------------
+
+  Changes:
+   * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.
+
+  New features:
+   * Setting thousands separator and decimal separator is now possible
+
+  Bugfixes:
+   * The dll interface did not provide a callback for functions without any arguments.  
+       
+
+Rev 1.29: Januar 2008
+---------------------
+
+  Unrelease Version available only via SVN.
+
+
+Rev 1.28: 02. July, 2007
+---------------------------
+  Library changes:
+  * Interface for the dynamic library changed and extended to create an interface 
+    using pure C functions only. 
+  * mupInit() removed
+
+  Build system:
+   * MSVC7 Project files removed in favor of MSVC8
+
+  Bugfixes:
+   * The dynamic library did not build on other systems than linux due to a misplaced 
+     preprocessor definition. This is fixed now.
+
+
+Rev 1.27:
+---------------------------
+
+  Build system:
+   * Modified build\ directory layout introducing some subfolders 
+     for the various IDE supported
+   * Project files for BCB and MSVC7 added
+   * Switched to use bakefile 0.2.1 which now correctly creates the 
+     "make uninstall" target for autoconf's Makefile.in
+   * Now the library debug builds are named "muparserd" instead of "muparser"
+     to allow multiple mixed release/debug builds to coexist; so e.g. on Windows
+     when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"
+
+  New Features:
+   * Factory functions can now take a user defined pointer
+   * String functions can now be used with up to two additional 
+     double parameters
+   * Support for UNICODE character types added
+   * Infix operator priority can now be changed by the user
+
+  Bugfixes:
+   * An internal error was raised when evaluating an empty 
+     expressions
+   * The error message raised in case of name collisions between 
+     implicitely defined variables and postfix operators did contain
+     misleading data.
+
+
+Rev 1.26: (unofficial release)
+------------------------------
+
+  New Features:
+   * Unary operator precedence can now be changed by the user.
+
+
+Rev 1.25: 5. February, 2006
+---------------------------
+
+  Build system: (special thanks to Francesco Montorsi for implementing it!)
+    * created a bakefile-based build system which adds support for the following win32 compilers:
+      -> MS visual C++ (6 and .NET)
+      -> BorlandC++ (5 or greater)
+      -> Mingw32 (tested with gcc 3.2)
+      -> Watcom (not tested)
+      and for GCC on Unix (using a standard autoconf's configure script).
+
+  Compatibility improvements:
+    * fixed some small warnings when using -Wall with GCC on Unix
+    * added inclusion guards for win32-specific portions of code
+    * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.
+
+
+Rev 1.24: 29. October, 2005
+---------------------------
+
+Changes:
+
+  Compatibility improvements:
+    * parser now works on 64 bit compilers
+    * (bytecode base datatype can now be changed freely)
+
+
+Rev 1.23: 19. October, 2005
+---------------------------
+
+Changes:
+
+  Bugfixes:
+    * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.
+
+  New features:
+    * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6
+
+
+Rev 1.22: October, 2005
+-----------------------
+
+Release notes:
+
+All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with
+gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. 
+This should make the code cleaner. The Borland Project files were removed. If you want to use it 
+with Borland either use the dll version or create your own project files. I can't support it since I don't 
+have this compiler at hand.
+
+Changes:
+
+  Project Changes:
+    * Borland project files removed
+      (The code should still compile with BCB but I can't provide you with project files)
+
+  Internal Changes:
+    * unnecessary template files have been removed:
+        - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp
+        - removed Files: muIParserTypes.h
+
+
+Rev 1.2 / 1.21: April, 2005
+---------------------------
+
+Release Notes:
+First of all the interface has changed so this version is not backwards compatible.
+After receiving a couple of questions about it, this version features support for
+user defined binary operators. Consequently the built in operators can now be 
+turned off, thus you can deactivate them and write complete customized parser
+subclasses that only contain the functionality you want. Another new feature is 
+the introduction of callback functions taking string arguments, implicit 
+generation of variables and the Assignment operator.
+
+  Functionality
+    * New built in operator: xor; Logical xor.
+    * New built in operator: Assignment operator; Defining variables in terms of 
+                             other variables/constants
+    * New feature: Strings as arguments for callback functions
+    * New feature: User defined binary operators
+    * New feature: ParserInt a class with a sample implementation for
+                     integer numbers.
+    * New feature: Callbacks to value regognition functions.
+
+    * Removed:  all predefined postfix operators have been removed.
+    * New project file:  Now comes with a ready to use windows DLL.
+    * New project file:  Makefile for cygwin now included.
+    * New example:  Example3 shows usage of the DLL.
+
+  Interface changes
+    * New member function: DefineOprt For adding user defined binary operators.
+    * New member function: EnableBuiltInOprt(bool) Enables/Disables built in 
+                           binary operators.
+    * New member function: AddValIdent(...) to add callbacks for custom value 
+                           recognition functions.
+    * Removed: SetVar(), SetConst().
+    * Renamed: Most interface functions have been renamed
+    * Changed: The type for multiargument callbacks multfun_type has changed. 
+               It no longer takes a std::vector as input.
+
+  Internal changes
+    * new class muParserTokenReader.h encapsulates the token identification 
+      and token assignment.
+    * Internal handling of function callbacks unified as a result the performance 
+      of the bytecode evaluation increased.
+
+
+Rev 1.10 : December 30, 2004
+----------------------------
+
+Release Notes:
+This version does not contain major new feature compared to V1.07 but its internal structure has
+changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode
+parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you
+can change its value datatype. It should work on 64-bit systems. For this reason I supply both
+versions for download. If you use V1.07 and are happy with it there is no need for updating
+your version.
+
+    * New example program: Archive now contains two demo programs: One for standard C++ and one for
+                           managed C++.
+    * New member function: RemoveVar(...) can be used for removing a single variable from the internal 
+                           storage.
+    * New member function: GetVar() can be used for querying the variable names and pointers of all
+                           variables defined in the parser.
+    * New member function: GetConst() can be used for querying all defined constants and their values.
+    * New member function: GetFunDef() can be used for querying all defined functions and the number of
+                           arguments they expect.
+    * Internal structure changed; hanging base datatype at compile time is now possible.
+    * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.
+    * Bugfix: Variable names must will now be tested if they conflict with constant or function names.
+    * Internal change:  Removed most dependencies from the C-string libraries.
+    * Internal change:  Bytecode is now stored in a separate class: ParserByteCode.h
+    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.
+    * Internal change:  Error treatment changed. ParserException is no longer derived from
+                        std::runtime_error; Internal treatment of Error messages changed.
+    * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
+                        they are used for defining the charset allowed for variable-, operator- and
+                        function names.
+
+
+Rev 1.09 : November 20, 2004
+----------------------------
+
+    * New member function:  RemoveVar(...) can be used for removing a single variable from the internal 
+                            storage.
+    * Internal structure changed; changing base datatype at compile time is now possible.
+    * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.
+    * Internal change:  Removed most dependencies from the C-string libraries.
+    * Internal change:  Bytecode is now stored in a separate class: ParserByteCode.h.
+    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.
+    * Internal change:  Error treatment changed. ParserException is no longer derived from 
+                        std::runtime_error; Internal treatment of Error messages changed.
+    * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
+      they are used for defining the charset allowed for variable-, operator- and function names.
+
+
+Rev 1.08 : November, 2004 
+-------------------------
+
+    * unpublished; experimental template version with respect to data type and underlying string
+      type (string <-> widestring). The idea was dropped...
+
+
+Rev 1.07 : September 4 2004
+---------------------------
+
+    * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some
+      issues left.
+    * Improved portability; Changes in order to allow compiling on BCB.
+    * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with
+      respect to a certain variable; added in muParser.h.
+
+
+Rev 1.06 : August 20 2004
+-------------------------
+
+    * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter
+      indicating that the function can not be optimized.
+    * Internal changes: muParserStack.h simplified; refactorings
+    * Parser is now distributed under the MIT License; all comments changed accordingly.
+
+
+Rev 1.05 : August 20 2004
+-------------------------
+
+    * Variable/constant names will now be checked for invalid characters.
+    * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().
+    * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).
+    * Predefined functions with variable number of arguments added: sum, avg, min, max.
+    * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().
+    * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().
+    * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.
+    * Internal changes: static array removed in Command code calculation routine; misc. changes.
+
+
+Rev 1.04 : August 16 2004
+-------------------------
+
+    * Support for functions with variable number of arguments added.
+    * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;
+      changed: Parser.h, Parser.cpp.
+    * Bug in the bytecode calculation function fixed (affected the unary minus operator).
+    * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).
+
+
+Rev 1.03 : August 10 2004
+-------------------------
+
+    * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),
+      ClearPostOp().
+    * Minor changes to the bytecode parsing routine.
+    * User defined functions can now have up to four parameters.
+    * Performance optimized: simple formula optimization added; (precalculation of constant parts of the
+      expression).
+    * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.
+
+
+Rev 1.02 : July 30 2004
+-----------------------
+
+    * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),
+      ClearConst().
+    * Single variables can now be added using AddVar(); you have now the choice of adding them either
+      one by one or all at the same time using SetVar(const varmap_type &a_vVar).
+    * Internal handling of variables changed, is now similar to function handling.
+    * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to
+      derive new parsers with a modified set of default functions and constants.
+    * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold
+      function parameter count.
+
+
+Rev 1.01 : July 23 2004
+-----------------------
+
+    * Support for user defined functions has been added; new functions: AddFun(), ClearFun(),
+      InitFunctions().
+    * Built in constants have been removed; the parser contained undocumented built in
+      constants pi, e.
+      There was the possibility of name conflicts with user defined variables.
+    * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only
+      argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3
+      arguments (array of names, array of pointers, and array length) is now marked as deprecated.
+    * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for
+      base 10, and ln for base e.
+
+
+Rev 1.00 : July 21 2004
+-----------------------
+
+    * Initial release
similarity index 95%
rename from bundled/muparser_v2_2_4/CMakeLists.txt
rename to bundled/muparser_v2_3_3/CMakeLists.txt
index 7edf1d4a673740e214a133610ea3232f438f296a..1fcf61cf5178c21df73dd545906e062d368daa99 100644 (file)
@@ -22,6 +22,7 @@ ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-switch)
 ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-nested-anon-types)
 ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-implicit-fallthrough)
 ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-cast-function-type)
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-float-conversion)
 
 INCLUDE_DIRECTORIES(
   include/
diff --git a/bundled/muparser_v2_3_3/LICENSE b/bundled/muparser_v2_3_3/LICENSE
new file mode 100644 (file)
index 0000000..e0a01f1
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright 2020 Ingo Berg
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/bundled/muparser_v2_3_3/include/muParser.h b/bundled/muparser_v2_3_3/include/muParser.h
new file mode 100644 (file)
index 0000000..62032aa
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_H
+#define MU_PARSER_H
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <vector>
+
+//--- Parser includes --------------------------------------------------------------------------
+#include "muParserBase.h"
+#include "muParserTemplateMagic.h"
+
+/** \file
+       \brief Definition of the standard floating point parser.
+*/
+
+namespace mu
+{
+       /** \brief Mathematical expressions parser.
+
+         Standard implementation of the mathematical expressions parser.
+         Can be used as a reference implementation for subclassing the parser.
+       */
+       class API_EXPORT_CXX Parser : public ParserBase
+       {
+       public:
+
+               Parser();
+
+               void InitCharSets() override;
+               void InitFun() override;
+               void InitConst() override;
+               void InitOprt() override;
+               void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd) override;
+
+               value_type Diff(value_type* a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const;
+
+       protected:
+
+               static int IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal);
+       };
+} // namespace mu
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserBase.h b/bundled/muparser_v2_3_3/include/muParserBase.h
new file mode 100644 (file)
index 0000000..6d32f2f
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_BASE_H
+#define MU_PARSER_BASE_H
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <cmath>
+#include <string>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <locale>
+#include <limits.h>
+
+//--- Parser includes --------------------------------------------------------------------------
+#include "muParserDef.h"
+#include "muParserTokenReader.h"
+#include "muParserBytecode.h"
+#include "muParserError.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 4251)  // ...needs to have dll-interface to be used by clients of class ...
+#endif
+
+
+namespace mu
+{
+       /** \file
+               \brief This file contains the class definition of the muparser engine.
+       */
+
+       /** \brief Mathematical expressions parser (base parser engine).
+
+               This is the implementation of a bytecode based mathematical expressions parser.
+               The formula will be parsed from string and converted into a bytecode.
+               Future calculations will be done with the bytecode instead the formula string
+               resulting in a significant performance increase.
+               Complementary to a set of internally implemented functions the parser is able to handle
+               user defined functions and variables.
+       */
+       class API_EXPORT_CXX ParserBase
+       {
+               friend class ParserTokenReader;
+
+       private:
+
+               /** \brief Typedef for the parse functions.
+
+                 The parse function do the actual work. The parser exchanges
+                 the function pointer to the parser function depending on
+                 which state it is in. (i.e. bytecode parser vs. string parser)
+               */
+               typedef value_type(ParserBase::* ParseFunction)() const;
+
+               /** \brief Type used for storing an array of values. */
+               typedef std::vector<value_type> valbuf_type;
+
+               /** \brief Type for a vector of strings. */
+               typedef std::vector<string_type> stringbuf_type;
+
+               /** \brief Typedef for the token reader. */
+               typedef ParserTokenReader token_reader_type;
+
+               /** \brief Type used for parser tokens. */
+               typedef ParserToken<value_type, string_type> token_type;
+
+               /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
+               static const int s_MaxNumOpenMPThreads;
+
+       public:
+
+               /** \brief Type of the error class.
+
+                 Included for backwards compatibility.
+               */
+               typedef ParserError exception_type;
+
+               static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
+
+               ParserBase();
+               ParserBase(const ParserBase& a_Parser);
+               ParserBase& operator=(const ParserBase& a_Parser);
+
+               virtual ~ParserBase();
+
+               value_type Eval() const;
+               value_type* Eval(int& nStackSize) const;
+               void Eval(value_type* results, int nBulkSize);
+
+               int GetNumResults() const;
+
+               void SetExpr(const string_type& a_sExpr);
+               void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr);
+
+               void SetDecSep(char_type cDecSep);
+               void SetThousandsSep(char_type cThousandsSep = 0);
+               void ResetLocale();
+
+               void EnableOptimizer(bool a_bIsOn = true);
+               void EnableBuiltInOprt(bool a_bIsOn = true);
+
+               bool HasBuiltInOprt() const;
+               void AddValIdent(identfun_type a_pCallback);
+
+               /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
+                       \brief Define a parser function without arguments.
+                       \param a_strName Name of the function
+                       \param a_pFun Pointer to the callback function
+                       \param a_bAllowOpt A flag indicating this function may be optimized
+               */
+               template<typename T>
+               void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true)
+               {
+                       AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars());
+               }
+
+               /** \fn void mu::ParserBase::DefineFunUserData
+                       \brief Define a parser function with user data (not null).
+                       \param a_strName Name of the function
+                       \param a_pFun Pointer to the callback function
+                       \param a_pUserData Pointer that will be passed back to callback (shall not be nullptr)
+                       \param a_bAllowOpt A flag indicating this function may be optimized
+               */
+               template<typename T>
+               void DefineFunUserData(const string_type& a_strName, T a_pFun, void* a_pUserData, bool a_bAllowOpt = true)
+               {
+                       AddCallback(a_strName, ParserCallback(a_pFun, a_pUserData, a_bAllowOpt), m_FunDef, ValidNameChars());
+               }
+
+               void DefineOprt(const string_type& a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false);
+               void DefineConst(const string_type& a_sName, value_type a_fVal);
+               void DefineStrConst(const string_type& a_sName, const string_type& a_strVal);
+               void DefineVar(const string_type& a_sName, value_type* a_fVar);
+               void DefinePostfixOprt(const string_type& a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true);
+               void DefineInfixOprt(const string_type& a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true);
+
+               // Clear user defined variables, constants or functions
+               void ClearVar();
+               void ClearFun();
+               void ClearConst();
+               void ClearInfixOprt();
+               void ClearPostfixOprt();
+               void ClearOprt();
+
+               void RemoveVar(const string_type& a_strVarName);
+               const varmap_type& GetUsedVar() const;
+               const varmap_type& GetVar() const;
+               const valmap_type& GetConst() const;
+               const string_type& GetExpr() const;
+               const funmap_type& GetFunDef() const;
+               string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
+               const ParserByteCode& GetByteCode() const;
+
+               const char_type** GetOprtDef() const;
+               void DefineNameChars(const char_type* a_szCharset);
+               void DefineOprtChars(const char_type* a_szCharset);
+               void DefineInfixOprtChars(const char_type* a_szCharset);
+
+               const char_type* ValidNameChars() const;
+               const char_type* ValidOprtChars() const;
+               const char_type* ValidInfixOprtChars() const;
+
+               void SetArgSep(char_type cArgSep);
+               char_type GetArgSep() const;
+
+       protected:
+
+               void Init();
+               void Error(EErrorCodes a_iErrc, int a_iPos = static_cast<int>(mu::string_type::npos), const string_type& a_strTok = string_type()) const;
+
+               virtual void InitCharSets() = 0;
+               virtual void InitFun() = 0;
+               virtual void InitConst() = 0;
+               virtual void InitOprt() = 0;
+
+               virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd);
+
+               static const char_type* c_DefaultOprt[];
+               static std::locale s_locale;  ///< The locale used by the parser
+               static bool g_DbgDumpCmdCode;
+               static bool g_DbgDumpStack;
+
+               /** \brief A facet class used to change decimal and thousands separator. */
+               template<class TChar>
+               class change_dec_sep : public std::numpunct<TChar>
+               {
+               public:
+
+                       explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
+                               :std::numpunct<TChar>()
+                               ,m_nGroup(nGroup)
+                               ,m_cDecPoint(cDecSep)
+                               ,m_cThousandsSep(cThousandsSep)
+                       {}
+
+               protected:
+
+                       char_type do_decimal_point() const override
+                       {
+                               return m_cDecPoint;
+                       }
+
+                       char_type do_thousands_sep() const override
+                       {
+                               return m_cThousandsSep;
+                       }
+
+                       std::string do_grouping() const override
+                       {
+                               // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
+                               // courtesy of Jens Bartsch
+                               // original code:
+                               //        return std::string(1, (char)m_nGroup); 
+                               // new code:
+                               return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
+                       }
+
+               private:
+
+                       int m_nGroup;
+                       char_type m_cDecPoint;
+                       char_type m_cThousandsSep;
+               };
+
+       private:
+
+               void Assign(const ParserBase& a_Parser);
+               void InitTokenReader();
+               void ReInit() const;
+
+               void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet);
+               void ApplyRemainingOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
+               void ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
+               void ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
+               void ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int iArgCount) const;
+
+               token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const;
+
+               int GetOprtPrecedence(const token_type& a_Tok) const;
+               EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const;
+
+               void CreateRPN() const;
+
+               value_type ParseString() const;
+               value_type ParseCmdCode() const;
+               value_type ParseCmdCodeShort() const;
+               value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
+
+               void  CheckName(const string_type& a_strName, const string_type& a_CharSet) const;
+               void  CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const;
+
+               void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const;
+
+               /** \brief Pointer to the parser function.
+
+                 Eval() calls the function whose address is stored there.
+               */
+               mutable ParseFunction  m_pParseFormula;
+               mutable ParserByteCode m_vRPN;        ///< The Bytecode class.
+               mutable stringbuf_type  m_vStringBuf; ///< String buffer, used for storing string function arguments
+               stringbuf_type  m_vStringVarBuf;
+
+               std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
+
+               funmap_type  m_FunDef;         ///< Map of function names and pointers.
+               funmap_type  m_PostOprtDef;    ///< Postfix operator callbacks
+               funmap_type  m_InfixOprtDef;   ///< unary infix operator.
+               funmap_type  m_OprtDef;        ///< Binary operator callbacks
+               valmap_type  m_ConstDef;       ///< user constants.
+               strmap_type  m_StrVarDef;      ///< user defined string constants
+               varmap_type  m_VarDef;         ///< user defind variables.
+
+               bool m_bBuiltInOp;             ///< Flag that can be used for switching built in operators on and off
+
+               string_type m_sNameChars;      ///< Charset for names
+               string_type m_sOprtChars;      ///< Charset for postfix/ binary operator tokens
+               string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
+
+               // items merely used for caching state information
+               mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
+               mutable int m_nFinalResultIdx;
+       };
+
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
+#endif
diff --git a/bundled/muparser_v2_3_3/include/muParserBytecode.h b/bundled/muparser_v2_3_3/include/muParserBytecode.h
new file mode 100644 (file)
index 0000000..cf16e20
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_BYTECODE_H
+#define MU_PARSER_BYTECODE_H
+
+#include <string>
+#include <stack>
+#include <vector>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+
+/** \file
+       \brief Definition of the parser bytecode class.
+*/
+
+
+namespace mu
+{
+       struct SToken
+       {
+               ECmdCode Cmd;
+
+               union
+               {
+                       struct // SValData
+                       {
+                               value_type* ptr;
+                               value_type  data;
+                               value_type  data2;
+                       } Val;
+
+                       struct // SFunData
+                       {
+                               // Note: the type is erased in generic_callable_type and the signature of the
+                               //       function to call is tracked elsewhere in regard with the number of
+                               //       parameters (args) and the general kind of function (Cmd: cmFUNC,
+                               //       cmFUNC_STR, or cmFUNC_BULK)
+                               generic_callable_type cb;
+                               int   argc;
+                               int   idx;
+                       } Fun;
+
+                       struct // SOprtData
+                       {
+                               value_type* ptr;
+                               int offset;
+                       } Oprt;
+               };
+       };
+
+
+       /** \brief Bytecode implementation of the Math Parser.
+
+               The bytecode contains the formula converted to revers polish notation stored in a continious
+               memory area. Associated with this data are operator codes, variable pointers, constant
+               values and function pointers. Those are necessary in order to calculate the result.
+               All those data items will be casted to the underlying datatype of the bytecode.
+       */
+       class ParserByteCode final
+       {
+       private:
+
+               /** \brief Token type for internal use only. */
+               typedef ParserToken<value_type, string_type> token_type;
+
+               /** \brief Token vector for storing the RPN. */
+               typedef std::vector<SToken> rpn_type;
+
+               /** \brief Position in the Calculation array. */
+               unsigned m_iStackPos;
+
+               /** \brief Maximum size needed for the stack. */
+               std::size_t m_iMaxStackSize;
+
+               /** \brief The actual rpn storage. */
+               rpn_type  m_vRPN;
+
+               bool m_bEnableOptimizer;
+
+               void ConstantFolding(ECmdCode a_Oprt);
+
+       public:
+
+               ParserByteCode();
+               ParserByteCode(const ParserByteCode& a_ByteCode);
+               ParserByteCode& operator=(const ParserByteCode& a_ByteCode);
+               void Assign(const ParserByteCode& a_ByteCode);
+
+               void AddVar(value_type* a_pVar);
+               void AddVal(value_type a_fVal);
+               void AddOp(ECmdCode a_Oprt);
+               void AddIfElse(ECmdCode a_Oprt);
+               void AddAssignOp(value_type* a_pVar);
+               void AddFun(generic_callable_type a_pFun, int a_iArgc, bool isOptimizable);
+               void AddBulkFun(generic_callable_type a_pFun, int a_iArgc);
+               void AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx);
+
+               void EnableOptimizer(bool bStat);
+
+               void Finalize();
+               void clear();
+               std::size_t GetMaxStackSize() const;
+
+               std::size_t GetSize() const
+               {
+                       return m_vRPN.size();
+               }
+
+               inline const SToken* GetBase() const
+               {
+                       if (m_vRPN.size() == 0)
+                               throw ParserError(ecINTERNAL_ERROR);
+                       else
+                               return &m_vRPN[0];
+               }
+
+               void AsciiDump();
+       };
+
+} // namespace mu
+
+#endif
+
+
diff --git a/bundled/muparser_v2_3_3/include/muParserCallback.h b/bundled/muparser_v2_3_3/include/muParserCallback.h
new file mode 100644 (file)
index 0000000..1e53f14
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2022 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef MU_PARSER_CALLBACK_H
+#define MU_PARSER_CALLBACK_H
+
+#include "muParserDef.h"
+
+/** \file
+       \brief Definition of the parser callback class.
+*/
+
+namespace mu
+{
+
+       /** \brief Encapsulation of prototypes for a numerical parser function.
+
+               Encapsulates the prototyp for numerical parser functions. The class
+               stores the number of arguments for parser functions as well
+               as additional flags indication the function is non optimizeable.
+               The pointer to the callback function pointer is stored as void*
+               and needs to be casted according to the argument count.
+               Negative argument counts indicate a parser function with a variable number
+               of arguments.
+       */
+       class API_EXPORT_CXX ParserCallback final
+       {
+       public:
+               ParserCallback(fun_type0  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type1  a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode);
+               ParserCallback(fun_type1  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);
+               ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type3  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type4  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type5  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type6  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type7  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type8  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type9  a_pFun, bool a_bAllowOpti);
+               ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);
+
+               ParserCallback(bulkfun_type0  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type1  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type2  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type3  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type4  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type5  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type6  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type7  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type8  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type9  a_pFun, bool a_bAllowOpti);
+               ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);
+
+               ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);
+
+               ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);
+               ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);
+               ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);
+               ParserCallback(strfun_type4 a_pFun, bool a_bAllowOpti);
+               ParserCallback(strfun_type5 a_pFun, bool a_bAllowOpti);
+               ParserCallback(strfun_type6 a_pFun, bool a_bAllowOpti);
+
+               // note: a_pUserData shall not be nullptr
+               ParserCallback(fun_userdata_type0  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type1  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type2  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type3  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type4  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type5  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type6  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type7  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type8  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type9  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(fun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+
+               ParserCallback(bulkfun_userdata_type0  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type1  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type2  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type3  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type4  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type5  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type6  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type7  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type8  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type9  a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(bulkfun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+
+               ParserCallback(multfun_userdata_type a_pFun, void* a_pUserData, bool a_bAllowOpti);
+
+               ParserCallback(strfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(strfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(strfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(strfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(strfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+               ParserCallback(strfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti);
+
+               ParserCallback();
+               ParserCallback(const ParserCallback& a_Fun);
+               ParserCallback & operator=(const ParserCallback& a_Fun);
+               ~ParserCallback();
+
+               ParserCallback* Clone() const;
+
+               bool  IsOptimizable() const;
+               bool  IsValid() const;
+               void* GetAddr() const;
+               void* GetUserData() const;
+               ECmdCode  GetCode() const;
+               ETypeCode GetType() const;
+               int GetPri()  const;
+               EOprtAssociativity GetAssociativity() const;
+               int GetArgc() const;
+
+       private:
+               void Assign(const ParserCallback& ref);
+
+               void* m_pFun;                   ///< Pointer to the callback function or internal data, casted to void
+
+               int   m_iArgc;                  ///< Internal representation of number of numeric function arguments
+               int   m_iPri;                   ///< Valid only for binary and infix operators; Operator precedence.
+               EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators 
+               ECmdCode  m_iCode;
+               ETypeCode m_iType;
+               bool  m_bAllowOpti;             ///< Flag indication optimizeability 
+       };
+
+
+       /** \brief Container for Callback objects. */
+       typedef std::map<string_type, ParserCallback> funmap_type;
+
+} // namespace mu
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserDef.h b/bundled/muparser_v2_3_3/include/muParserDef.h
new file mode 100644 (file)
index 0000000..13a15c8
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MUP_DEF_H
+#define MUP_DEF_H
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include "muParserFixes.h"
+
+/** \file
+       \brief This file contains standard definitions used by the parser.
+*/
+
+/** \brief Define the base datatype for values.
+
+  This datatype must be a built in value type. You can not use custom classes.
+  It should be working with all types except "int"!
+*/
+#define MUP_BASETYPE double
+
+/** \brief Activate this option in order to compile with OpenMP support.
+
+  OpenMP is used only in the bulk mode it may increase the performance a bit.
+
+  !!! DO NOT ACTIVATE THIS MACRO HERE IF YOU USE CMAKE FOR BUILDING !!!
+
+  use the cmake option instead!
+*/
+//#define MUP_USE_OPENMP
+
+#if defined(_UNICODE)
+       /** \brief Definition of the basic parser string type. */
+       #define MUP_STRING_TYPE std::wstring
+
+       #if !defined(_T)
+               #define _T(x) L##x
+       #endif // not defined _T
+#else
+       #ifndef _T
+               #define _T(x) x
+       #endif
+
+       /** \brief Definition of the basic parser string type. */
+       #define MUP_STRING_TYPE std::string
+#endif
+
+/** \brief An assertion that does not kill the program. */
+#define MUP_ASSERT(COND)                                                                                       \
+            if (!(COND))                                                                                       \
+            {                                                                                                          \
+              stringstream_type ss;                                                                    \
+              ss << _T("Assertion \"") _T(#COND) _T("\" failed: ")     \
+                 << __FILE__ << _T(" line ")                                           \
+                 << __LINE__ << _T(".");                                                       \
+              throw ParserError( ecINTERNAL_ERROR, -1, ss.str());   \
+            }
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+
+namespace mu
+{
+#if defined(_UNICODE)
+
+       /** \brief Encapsulate wcout. */
+       inline std::wostream& console()
+       {
+               return std::wcout;
+       }
+
+       /** \brief Encapsulate cin. */
+       inline std::wistream& console_in()
+       {
+               return std::wcin;
+       }
+
+#else
+
+       /** \brief Encapsulate cout.
+
+         Used for supporting UNICODE more easily.
+       */
+       inline std::ostream& console()
+       {
+               return std::cout;
+       }
+
+       /** \brief Encapsulate cin.
+
+         Used for supporting UNICODE more easily.
+       */
+       inline std::istream& console_in()
+       {
+               return std::cin;
+       }
+
+#endif
+
+       /** \brief Bytecode values.
+
+               \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
+       */
+       enum ECmdCode
+       {
+               // The following are codes for built in binary operators
+               // apart from built in operators the user has the opportunity to
+               // add user defined operators.
+               cmLE = 0,                       ///< Operator item:  less or equal
+               cmGE = 1,                       ///< Operator item:  greater or equal
+               cmNEQ = 2,                      ///< Operator item:  not equal
+               cmEQ = 3,                       ///< Operator item:  equals
+               cmLT = 4,                       ///< Operator item:  less than
+               cmGT = 5,                       ///< Operator item:  greater than
+               cmADD = 6,                      ///< Operator item:  add
+               cmSUB = 7,                      ///< Operator item:  subtract
+               cmMUL = 8,                      ///< Operator item:  multiply
+               cmDIV = 9,                      ///< Operator item:  division
+               cmPOW = 10,                     ///< Operator item:  y to the power of ...
+               cmLAND = 11,
+               cmLOR = 12,
+               cmASSIGN = 13,          ///< Operator item:  Assignment operator
+               cmBO = 14,                      ///< Operator item:  opening bracket
+               cmBC = 15,                      ///< Operator item:  closing bracket
+               cmIF = 16,                      ///< For use in the ternary if-then-else operator
+               cmELSE = 17,            ///< For use in the ternary if-then-else operator
+               cmENDIF = 18,           ///< For use in the ternary if-then-else operator
+               cmARG_SEP = 19,         ///< function argument separator
+               cmVAR = 20,                     ///< variable item
+               cmVAL = 21,                     ///< value item
+
+               // For optimization purposes
+               cmVARPOW2 = 22,
+               cmVARPOW3 = 23,
+               cmVARPOW4 = 24,
+               cmVARMUL = 25,
+
+               // operators and functions
+               cmFUNC = 26,            ///< Code for a generic function item
+               cmFUNC_STR,                     ///< Code for a function with a string parameter
+               cmFUNC_BULK,            ///< Special callbacks for Bulk mode with an additional parameter for the bulk index 
+               cmSTRING,                       ///< Code for a string token
+               cmOPRT_BIN,                     ///< user defined binary operator
+               cmOPRT_POSTFIX,         ///< code for postfix operators
+               cmOPRT_INFIX,           ///< code for infix operators
+               cmEND,                          ///< end of formula
+               cmUNKNOWN                       ///< uninitialized item
+       };
+
+       /** \brief Types internally used by the parser.
+       */
+       enum ETypeCode
+       {
+               tpSTR = 0,     ///< String type (Function arguments and constants only, no string variables)
+               tpDBL = 1,     ///< Floating point variables
+               tpVOID = 2      ///< Undefined type.
+       };
+
+
+       enum EParserVersionInfo
+       {
+               pviBRIEF,
+               pviFULL
+       };
+
+
+       /** \brief Parser operator precedence values. */
+       enum EOprtAssociativity
+       {
+               oaLEFT = 0,
+               oaRIGHT = 1,
+               oaNONE = 2
+       };
+
+
+       /** \brief Parser operator precedence values. */
+       enum EOprtPrecedence
+       {
+               // binary operators
+               prLOR = 1,
+               prLAND = 2,
+               prLOGIC = 3,    ///< logic operators
+               prCMP = 4,              ///< comparsion operators
+               prADD_SUB = 5,  ///< addition
+               prMUL_DIV = 6,  ///< multiplication/division
+               prPOW = 7,              ///< power operator priority (highest)
+
+               // infix operators
+               prINFIX = 6,    ///< Signs have a higher priority than ADD_SUB, but lower than power operator
+               prPOSTFIX = 6   ///< Postfix operator priority (currently unused)
+       };
+
+
+       /** \brief Error codes. */
+       enum EErrorCodes
+       {
+               // Formula syntax errors
+               ecUNEXPECTED_OPERATOR = 0,      ///< Unexpected binary operator found
+               ecUNASSIGNABLE_TOKEN = 1,       ///< Token can't be identified.
+               ecUNEXPECTED_EOF = 2,           ///< Unexpected end of formula. (Example: "2+sin(")
+               ecUNEXPECTED_ARG_SEP = 3,       ///< An unexpected comma has been found. (Example: "1,23")
+               ecUNEXPECTED_ARG = 4,           ///< An unexpected argument has been found
+               ecUNEXPECTED_VAL = 5,           ///< An unexpected value token has been found
+               ecUNEXPECTED_VAR = 6,           ///< An unexpected variable token has been found
+               ecUNEXPECTED_PARENS = 7,        ///< Unexpected Parenthesis, opening or closing
+               ecUNEXPECTED_STR = 8,           ///< A string has been found at an inapropriate position
+               ecSTRING_EXPECTED = 9,          ///< A string function has been called with a different type of argument
+               ecVAL_EXPECTED = 10,            ///< A numerical function has been called with a non value type of argument
+               ecMISSING_PARENS = 11,          ///< Missing parens. (Example: "3*sin(3")
+               ecUNEXPECTED_FUN = 12,          ///< Unexpected function found. (Example: "sin(8)cos(9)")
+               ecUNTERMINATED_STRING = 13,     ///< unterminated string constant. (Example: "3*valueof("hello)")
+               ecTOO_MANY_PARAMS = 14,         ///< Too many function parameters
+               ecTOO_FEW_PARAMS = 15,          ///< Too few function parameters. (Example: "ite(1<2,2)")
+               ecOPRT_TYPE_CONFLICT = 16,      ///< binary operators may only be applied to value items of the same type
+               ecSTR_RESULT = 17,                      ///< result is a string
+
+               // Invalid Parser input Parameters
+               ecINVALID_NAME = 18,                    ///< Invalid function, variable or constant name.
+               ecINVALID_BINOP_IDENT = 19,             ///< Invalid binary operator identifier
+               ecINVALID_INFIX_IDENT = 20,             ///< Invalid function, variable or constant name.
+               ecINVALID_POSTFIX_IDENT = 21,   ///< Invalid function, variable or constant name.
+
+               ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator
+               ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer 
+               ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer 
+               ecEMPTY_EXPRESSION = 25, ///< The Expression is empty
+               ecNAME_CONFLICT = 26, ///< Name conflict
+               ecOPT_PRI = 27, ///< Invalid operator priority
+               // 
+               ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
+               ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused)
+               ecGENERIC = 30, ///< Generic error
+               ecLOCALE = 31, ///< Conflict with current locale
+
+               ecUNEXPECTED_CONDITIONAL = 32,
+               ecMISSING_ELSE_CLAUSE = 33,
+               ecMISPLACED_COLON = 34,
+
+               ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35,
+
+               ecIDENTIFIER_TOO_LONG = 36, ///< Thrown when an identifier with more then 255 characters is used.
+
+               ecEXPRESSION_TOO_LONG = 37, ///< Throw an exception if the expression has more than 10000 characters. (an arbitrary limit)
+
+               ecINVALID_CHARACTERS_FOUND = 38,///< The expression or identifier contains invalid non printable characters
+
+               // internal errors
+               ecINTERNAL_ERROR = 39,    ///< Internal error of any kind.
+
+               // The last two are special entries 
+               ecCOUNT,                      ///< This is no error code, It just stores just the total number of error codes
+               ecUNDEFINED = -1  ///< Undefined message, placeholder to detect unassigned error messages
+       };
+
+       //------------------------------------------------------------------------------
+       // Basic Types
+       //------------------------------------------------------------------------------
+
+       /** \brief The numeric datatype used by the parser.
+
+         Normally this is a floating point type either single or double precision.
+       */
+       typedef MUP_BASETYPE value_type;
+
+       /** \brief The stringtype used by the parser.
+
+         Depends on whether UNICODE is used or not.
+       */
+       typedef MUP_STRING_TYPE string_type;
+
+       /** \brief The character type used by the parser.
+
+         Depends on whether UNICODE is used or not.
+       */
+       typedef string_type::value_type char_type;
+
+       /** \brief Typedef for easily using stringstream that respect the parser stringtype. */
+       typedef std::basic_stringstream<char_type, std::char_traits<char_type>, std::allocator<char_type> > stringstream_type;
+
+       // Data container types
+
+       /** \brief Type used for storing variables. */
+       typedef std::map<string_type, value_type*> varmap_type;
+
+       /** \brief Type used for storing constants. */
+       typedef std::map<string_type, value_type> valmap_type;
+
+       /** \brief Type for assigning a string name to an index in the internal string table. */
+       typedef std::map<string_type, std::size_t> strmap_type;
+
+       // Parser callbacks
+
+       /** \brief Function type used to erase type.  Voluntarily needs explicit cast with all other *fun_type*. */
+       typedef void(*erased_fun_type)();
+
+       /** \brief Callback type used for functions without arguments. */
+       typedef value_type(*fun_type0)();
+
+       /** \brief Callback type used for functions with a single arguments. */
+       typedef value_type(*fun_type1)(value_type);
+
+       /** \brief Callback type used for functions with two arguments. */
+       typedef value_type(*fun_type2)(value_type, value_type);
+
+       /** \brief Callback type used for functions with three arguments. */
+       typedef value_type(*fun_type3)(value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with four arguments. */
+       typedef value_type(*fun_type4)(value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with five arguments. */
+       typedef value_type(*fun_type5)(value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with six arguments. */
+       typedef value_type(*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with seven arguments. */
+       typedef value_type(*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with eight arguments. */
+       typedef value_type(*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with nine arguments. */
+       typedef value_type(*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with ten arguments. */
+       typedef value_type(*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions without arguments. */
+       typedef value_type(*fun_userdata_type0)(void*);
+
+       /** \brief Callback type with user data (not null) used for functions with a single arguments. */
+       typedef value_type(*fun_userdata_type1)(void*, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with two arguments. */
+       typedef value_type(*fun_userdata_type2)(void*, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with three arguments. */
+       typedef value_type(*fun_userdata_type3)(void*, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with four arguments. */
+       typedef value_type(*fun_userdata_type4)(void*, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with five arguments. */
+       typedef value_type(*fun_userdata_type5)(void*, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with six arguments. */
+       typedef value_type(*fun_userdata_type6)(void*, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with seven arguments. */
+       typedef value_type(*fun_userdata_type7)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with eight arguments. */
+       typedef value_type(*fun_userdata_type8)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with nine arguments. */
+       typedef value_type(*fun_userdata_type9)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with ten arguments. */
+       typedef value_type(*fun_userdata_type10)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions without arguments. */
+       typedef value_type(*bulkfun_type0)(int, int);
+
+       /** \brief Callback type used for functions with a single arguments. */
+       typedef value_type(*bulkfun_type1)(int, int, value_type);
+
+       /** \brief Callback type used for functions with two arguments. */
+       typedef value_type(*bulkfun_type2)(int, int, value_type, value_type);
+
+       /** \brief Callback type used for functions with three arguments. */
+       typedef value_type(*bulkfun_type3)(int, int, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with four arguments. */
+       typedef value_type(*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with five arguments. */
+       typedef value_type(*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with six arguments. */
+       typedef value_type(*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with seven arguments. */
+       typedef value_type(*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with eight arguments. */
+       typedef value_type(*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with nine arguments. */
+       typedef value_type(*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with ten arguments. */
+       typedef value_type(*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions without arguments. */
+       typedef value_type(*bulkfun_userdata_type0)(void*, int, int);
+
+       /** \brief Callback type with user data (not null) used for functions with a single arguments. */
+       typedef value_type(*bulkfun_userdata_type1)(void*, int, int, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with two arguments. */
+       typedef value_type(*bulkfun_userdata_type2)(void*, int, int, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with three arguments. */
+       typedef value_type(*bulkfun_userdata_type3)(void*, int, int, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with four arguments. */
+       typedef value_type(*bulkfun_userdata_type4)(void*, int, int, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with five arguments. */
+       typedef value_type(*bulkfun_userdata_type5)(void*, int, int, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with six arguments. */
+       typedef value_type(*bulkfun_userdata_type6)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with seven arguments. */
+       typedef value_type(*bulkfun_userdata_type7)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with eight arguments. */
+       typedef value_type(*bulkfun_userdata_type8)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with nine arguments. */
+       typedef value_type(*bulkfun_userdata_type9)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions with ten arguments. */
+       typedef value_type(*bulkfun_userdata_type10)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions with a variable argument list. */
+       typedef value_type(*multfun_type)(const value_type*, int);
+
+       /** \brief Callback type with user data (not null) used for functions and a variable argument list. */
+       typedef value_type(*multfun_userdata_type)(void*, const value_type*, int);
+
+       /** \brief Callback type used for functions taking a string as an argument. */
+       typedef value_type(*strfun_type1)(const char_type*);
+
+       /** \brief Callback type used for functions taking a string and a value as arguments. */
+       typedef value_type(*strfun_type2)(const char_type*, value_type);
+
+       /** \brief Callback type used for functions taking a string and two values as arguments. */
+       typedef value_type(*strfun_type3)(const char_type*, value_type, value_type);
+
+       /** \brief Callback type used for functions taking a string and three values as arguments. */
+       typedef value_type(*strfun_type4)(const char_type*, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions taking a string and four values as arguments. */
+       typedef value_type(*strfun_type5)(const char_type*, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type used for functions taking a string and five values as arguments. */
+       typedef value_type(*strfun_type6)(const char_type*, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string as an argument. */
+       typedef value_type(*strfun_userdata_type1)(void*, const char_type*);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string and a value as arguments. */
+       typedef value_type(*strfun_userdata_type2)(void*, const char_type*, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string and two values as arguments. */
+       typedef value_type(*strfun_userdata_type3)(void*, const char_type*, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string and a value as arguments. */
+       typedef value_type(*strfun_userdata_type4)(void*, const char_type*, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string and two values as arguments. */
+       typedef value_type(*strfun_userdata_type5)(void*, const char_type*, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback type with user data (not null) used for functions taking a string and five values as arguments. */
+       typedef value_type(*strfun_userdata_type6)(void*, const char_type*, value_type, value_type, value_type, value_type, value_type);
+
+       /** \brief Callback used for functions that identify values in a string. */
+       typedef int (*identfun_type)(const char_type* sExpr, int* nPos, value_type* fVal);
+
+       /** \brief Callback used for variable creation factory functions. */
+       typedef value_type* (*facfun_type)(const char_type*, void*);
+
+       static const int MaxLenExpression = 20000;
+       static const int MaxLenIdentifier = 100;
+       static const string_type ParserVersion = string_type(_T("2.3.3 (Release)"));
+       static const string_type ParserVersionDate = string_type(_T("20220122"));
+} // end of namespace
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserError.h b/bundled/muparser_v2_3_3/include/muParserError.h
new file mode 100644 (file)
index 0000000..90fbfdf
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_ERROR_H
+#define MU_PARSER_ERROR_H
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+#include "muParserDef.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 4251)  // ...needs to have dll-interface to be used by clients of class ...
+#endif
+
+
+/** \file
+       \brief This file defines the error class used by the parser.
+*/
+
+namespace mu
+{
+       /** \brief A class that handles the error messages.     */
+       class ParserErrorMsg final
+       {
+       public:
+               static const ParserErrorMsg& Instance();
+               string_type operator[](unsigned a_iIdx) const;
+
+       private:
+               ParserErrorMsg& operator=(const ParserErrorMsg&) = delete;
+               ParserErrorMsg(const ParserErrorMsg&) = delete;
+               ParserErrorMsg();
+
+               ~ParserErrorMsg() = default;
+
+               std::vector<string_type>  m_vErrMsg;  ///< A vector with the predefined error messages
+       };
+
+
+       /** \brief Error class of the parser.
+
+         Part of the math parser package.
+       */
+       class API_EXPORT_CXX ParserError
+       {
+       private:
+
+               /** \brief Replace all ocuurences of a substring with another string. */
+               void ReplaceSubString(string_type& strSource, const string_type& strFind, const string_type& strReplaceWith);
+               void Reset();
+
+       public:
+
+               ParserError();
+               explicit ParserError(EErrorCodes a_iErrc);
+               explicit ParserError(const string_type& sMsg);
+               ParserError(EErrorCodes a_iErrc, const string_type& sTok, const string_type& sFormula = string_type(), int a_iPos = -1);
+               ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type& sTok);
+               ParserError(const char_type* a_szMsg, int a_iPos = -1, const string_type& sTok = string_type());
+               ParserError(const ParserError& a_Obj);
+
+               ParserError& operator=(const ParserError& a_Obj);
+               ~ParserError();
+
+               void SetFormula(const string_type& a_strFormula);
+               const string_type& GetExpr() const;
+               const string_type& GetMsg() const;
+               int GetPos() const;
+               const string_type& GetToken() const;
+               EErrorCodes GetCode() const;
+
+       private:
+               string_type m_strMsg;     ///< The message string
+               string_type m_strFormula; ///< Formula string
+               string_type m_strTok;     ///< Token related with the error
+               int m_iPos;               ///< Formula position related to the error 
+               EErrorCodes m_iErrc;      ///< Error code
+               const ParserErrorMsg& m_ErrMsg;
+       };
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserFixes.h b/bundled/muparser_v2_3_3/include/muParserFixes.h
new file mode 100644 (file)
index 0000000..8042d28
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_FIXES_H
+#define MU_PARSER_FIXES_H
+
+/** \file
+       \brief This file contains compatibility fixes for some platforms.
+*/
+
+//
+// Compatibility fixes
+//
+
+/* From http://gcc.gnu.org/wiki/Visibility */
+/* Generic helper definitions for shared library support */
+#if defined _WIN32 || defined __CYGWIN__
+       #define MUPARSER_HELPER_DLL_IMPORT __declspec(dllimport)
+       #define MUPARSER_HELPER_DLL_EXPORT __declspec(dllexport)
+       #define MUPARSER_HELPER_DLL_LOCAL
+#else
+       #if __GNUC__ >= 4
+               #define MUPARSER_HELPER_DLL_IMPORT __attribute__ ((visibility ("default")))
+               #define MUPARSER_HELPER_DLL_EXPORT __attribute__ ((visibility ("default")))
+               #define MUPARSER_HELPER_DLL_LOCAL  __attribute__ ((visibility ("hidden")))
+       #else
+               #define MUPARSER_HELPER_DLL_IMPORT
+               #define MUPARSER_HELPER_DLL_EXPORT
+               #define MUPARSER_HELPER_DLL_LOCAL
+       #endif
+#endif
+
+/* 
+       Now we use the generic helper definitions above to define API_EXPORT_CXX and MUPARSER_LOCAL.
+       API_EXPORT_CXX is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
+       MUPARSER_LOCAL is used for non-api symbols.
+*/
+
+#ifndef MUPARSER_STATIC /* defined if muParser is compiled as a DLL */
+
+       #ifdef MUPARSERLIB_EXPORTS /* defined if we are building the muParser DLL (instead of using it) */
+               #define API_EXPORT_CXX MUPARSER_HELPER_DLL_EXPORT
+       #else
+               #define API_EXPORT_CXX MUPARSER_HELPER_DLL_IMPORT
+       #endif /* MUPARSER_DLL_EXPORTS */
+       #define MUPARSER_LOCAL MUPARSER_HELPER_DLL_LOCAL
+
+#else /* MUPARSER_STATIC is defined: this means muParser is a static lib. */
+
+       #define API_EXPORT_CXX
+       #define MUPARSER_LOCAL
+
+#endif /* !MUPARSER_STATIC */
+
+
+#ifdef _WIN32
+       #define API_EXPORT(TYPE) API_EXPORT_CXX TYPE __cdecl
+#else
+       #define API_EXPORT(TYPE) TYPE
+#endif
+
+
+#endif // include guard
+
+
diff --git a/bundled/muparser_v2_3_3/include/muParserInt.h b/bundled/muparser_v2_3_3/include/muParserInt.h
new file mode 100644 (file)
index 0000000..513f092
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_INT_H
+#define MU_PARSER_INT_H
+
+#include "muParserBase.h"
+#include <vector>
+
+
+/** \file
+       \brief Definition of a parser using integer value.
+*/
+
+
+namespace mu
+{
+
+       /** \brief Mathematical expressions parser.
+
+         This version of the parser handles only integer numbers. It disables the built in operators thus it is
+         slower than muParser. Integer values are stored in the double value_type and converted if needed.
+       */
+       class ParserInt : public ParserBase
+       {
+       private:
+               static int  Round(value_type v) { return (int)(v + ((v >= 0) ? 0.5 : -0.5)); };
+
+               static value_type  Abs(value_type);
+               static value_type  Sign(value_type);
+               static value_type  Ite(value_type, value_type, value_type);
+               // !! The unary Minus is a MUST, otherwise you can't use negative signs !!
+               static value_type  UnaryMinus(value_type);
+               // Functions with variable number of arguments
+               static value_type  Sum(const value_type* a_afArg, int a_iArgc);  // sum
+               static value_type  Min(const value_type* a_afArg, int a_iArgc);  // minimum
+               static value_type  Max(const value_type* a_afArg, int a_iArgc);  // maximum
+               // binary operator callbacks
+               static value_type  Add(value_type v1, value_type v2);
+               static value_type  Sub(value_type v1, value_type v2);
+               static value_type  Mul(value_type v1, value_type v2);
+               static value_type  Div(value_type v1, value_type v2);
+               static value_type  Mod(value_type v1, value_type v2);
+               static value_type  Pow(value_type v1, value_type v2);
+               static value_type  Shr(value_type v1, value_type v2);
+               static value_type  Shl(value_type v1, value_type v2);
+               static value_type  LogAnd(value_type v1, value_type v2);
+               static value_type  LogOr(value_type v1, value_type v2);
+               static value_type  And(value_type v1, value_type v2);
+               static value_type  Or(value_type v1, value_type v2);
+               static value_type  Xor(value_type v1, value_type v2);
+               static value_type  Less(value_type v1, value_type v2);
+               static value_type  Greater(value_type v1, value_type v2);
+               static value_type  LessEq(value_type v1, value_type v2);
+               static value_type  GreaterEq(value_type v1, value_type v2);
+               static value_type  Equal(value_type v1, value_type v2);
+               static value_type  NotEqual(value_type v1, value_type v2);
+               static value_type  Not(value_type v1);
+
+               static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal);
+               static int IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal);
+               static int IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal);
+
+               /** \brief A facet class used to change decimal and thousands separator. */
+               template<class TChar>
+               class change_dec_sep : public std::numpunct<TChar>
+               {
+               public:
+
+                       explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
+                               :std::numpunct<TChar>()
+                               , m_cDecPoint(cDecSep)
+                               , m_cThousandsSep(cThousandsSep)
+                               , m_nGroup(nGroup)
+                       {}
+
+               protected:
+
+                       virtual char_type do_decimal_point() const
+                       {
+                               return m_cDecPoint;
+                       }
+
+                       virtual char_type do_thousands_sep() const
+                       {
+                               return m_cThousandsSep;
+                       }
+
+                       virtual std::string do_grouping() const
+                       {
+                               // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
+                               // courtesy of Jens Bartsch
+                               // original code:
+                               //        return std::string(1, (char)m_nGroup); 
+                               // new code:
+                               return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
+                       }
+
+               private:
+
+                       int m_nGroup;
+                       char_type m_cDecPoint;
+                       char_type m_cThousandsSep;
+               };
+
+       public:
+               ParserInt();
+
+               void InitFun() override;
+               void InitOprt() override;
+               void InitConst() override;
+               void InitCharSets() override;
+       };
+
+} // namespace mu
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserTemplateMagic.h b/bundled/muparser_v2_3_3/include/muParserTemplateMagic.h
new file mode 100644 (file)
index 0000000..77fe549
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_TEMPLATE_MAGIC_H
+#define MU_PARSER_TEMPLATE_MAGIC_H
+
+#include <cmath>
+#include "muParserError.h"
+
+
+namespace mu
+{
+       //-----------------------------------------------------------------------------------------------
+       //
+       // Compile time type detection
+       //
+       //-----------------------------------------------------------------------------------------------
+
+       /** \brief A class singling out integer types at compile time using
+                          template meta programming.
+       */
+       template<typename T>
+       struct TypeInfo
+       {
+               static bool IsInteger() { return false; }
+       };
+
+       template<>
+       struct TypeInfo<char>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<short>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<int>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<long>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<unsigned char>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<unsigned short>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<unsigned int>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+       template<>
+       struct TypeInfo<unsigned long>
+       {
+               static bool IsInteger() { return true; }
+       };
+
+
+       //-----------------------------------------------------------------------------------------------
+       //
+       // Standard math functions with dummy overload for integer types
+       //
+       //-----------------------------------------------------------------------------------------------
+
+       /** \brief A template class for providing wrappers for essential math functions.
+
+         This template is spezialized for several types in order to provide a unified interface
+         for parser internal math function calls regardless of the data type.
+       */
+       template<typename T>
+       struct MathImpl
+       {
+               static T Sin(T v) { return sin(v); }
+               static T Cos(T v) { return cos(v); }
+               static T Tan(T v) { return tan(v); }
+               static T ASin(T v) { return asin(v); }
+               static T ACos(T v) { return acos(v); }
+               static T ATan(T v) { return atan(v); }
+               static T ATan2(T v1, T v2) { return atan2(v1, v2); }
+               static T Sinh(T v) { return sinh(v); }
+               static T Cosh(T v) { return cosh(v); }
+               static T Tanh(T v) { return tanh(v); }
+               static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }
+               static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }
+               static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }
+               static T Log(T v) { return log(v); }
+               static T Log2(T v) { return log(v) / log((T)2); } // Logarithm base 2
+               static T Log10(T v) { return log10(v); }         // Logarithm base 10
+               static T Exp(T v) { return exp(v); }
+               static T Abs(T v) { return (v >= 0) ? v : -v; }
+               static T Sqrt(T v) { return sqrt(v); }
+               static T Rint(T v) { return floor(v + (T)0.5); }
+               static T Sign(T v) { return (T)((v < 0) ? -1 : (v > 0) ? 1 : 0); }
+               static T Pow(T v1, T v2) { return std::pow(v1, v2); }
+
+               static T UnaryMinus(T v) { return -v; }
+               static T UnaryPlus(T v) { return v; }
+
+               static T Sum(const T *a_afArg, int a_iArgc)
+               {
+                       if (!a_iArgc)
+                               throw ParserError(_T("too few arguments for function sum."));
+
+                       T fRes = 0;
+                       for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i];
+                       return fRes;
+               }
+
+               static T Avg(const T *a_afArg, int a_iArgc)
+               {
+                       if (!a_iArgc)
+                               throw ParserError(_T("too few arguments for function avg."));
+
+                       T fRes = 0;
+                       for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i];
+                       return fRes / (T)a_iArgc;
+               }
+
+               static T Min(const T *a_afArg, int a_iArgc)
+               {
+                       if (!a_iArgc)
+                               throw ParserError(_T("too few arguments for function min."));
+
+                       T fRes = a_afArg[0];
+                       for (int i = 0; i < a_iArgc; ++i)
+                               fRes = std::min(fRes, a_afArg[i]);
+
+                       return fRes;
+               }
+
+               static T Max(const T *a_afArg, int a_iArgc)
+               {
+                       if (!a_iArgc)
+                               throw ParserError(_T("too few arguments for function max."));
+
+                       T fRes = a_afArg[0];
+                       for (int i = 0; i < a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
+
+                       return fRes;
+               }
+
+
+#if defined (__GNUG__)
+               // Bei zu genauer definition von pi kann die Berechnung von
+               // sin(pi*a) mit a=1 10 x langsamer sein! 
+               static constexpr T CONST_PI = (T)3.141592653589;
+#else
+               static constexpr T CONST_PI = (T)3.141592653589793238462643;
+#endif
+
+               static constexpr T CONST_E = (T)2.718281828459045235360287;
+       };
+}
+
+#endif
diff --git a/bundled/muparser_v2_3_3/include/muParserTest.h b/bundled/muparser_v2_3_3/include/muParserTest.h
new file mode 100644 (file)
index 0000000..22d2075
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_TEST_H
+#define MU_PARSER_TEST_H
+
+#include <string>
+#include <cstdlib>
+#include <cstdint>
+#include <numeric> // for accumulate
+#include "muParser.h"
+#include "muParserInt.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 4251)  // ...needs to have dll-interface to be used by clients of class ...
+#endif
+
+/** \file
+       \brief This file contains the parser test class.
+*/
+
+namespace mu
+{
+       /** \brief Namespace for test cases. */
+       namespace Test
+       {
+               /** \brief Test cases for unit testing. */
+               class API_EXPORT_CXX ParserTester final
+               {
+               private:
+                       static int c_iCount;
+
+                       static value_type f0() { return 42; };
+
+                       // Multiarg callbacks
+                       static value_type f1of1(value_type v) { return v; };
+
+                       static value_type f1of2(value_type v, value_type) { return v; };
+                       static value_type f2of2(value_type, value_type v) { return v; };
+
+                       static value_type f1of3(value_type v, value_type, value_type) { return v; };
+                       static value_type f2of3(value_type, value_type v, value_type) { return v; };
+                       static value_type f3of3(value_type, value_type, value_type v) { return v; };
+
+                       static value_type f1of4(value_type v, value_type, value_type, value_type) { return v; }
+                       static value_type f2of4(value_type, value_type v, value_type, value_type) { return v; }
+                       static value_type f3of4(value_type, value_type, value_type v, value_type) { return v; }
+                       static value_type f4of4(value_type, value_type, value_type, value_type v) { return v; }
+
+                       static value_type f1of5(value_type v, value_type, value_type, value_type, value_type) { return v; }
+                       static value_type f2of5(value_type, value_type v, value_type, value_type, value_type) { return v; }
+                       static value_type f3of5(value_type, value_type, value_type v, value_type, value_type) { return v; }
+                       static value_type f4of5(value_type, value_type, value_type, value_type v, value_type) { return v; }
+                       static value_type f5of5(value_type, value_type, value_type, value_type, value_type v) { return v; }
+
+                       static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 < a_fVal2) ? a_fVal1 : a_fVal2; }
+                       static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 > a_fVal2) ? a_fVal1 : a_fVal2; }
+
+                       static value_type plus2(value_type v1) { return v1 + 2; }
+                       static value_type times3(value_type v1) { return v1 * 3; }
+                       static value_type sqr(value_type v1) { return v1 * v1; }
+                       static value_type sign(value_type v) { return -v; }
+                       static value_type add(value_type v1, value_type v2) { return v1 + v2; }
+                       static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }
+
+
+                       static value_type FirstArg(const value_type* a_afArg, int a_iArgc)
+                       {
+                               if (!a_iArgc)
+                                       throw mu::Parser::exception_type(_T("too few arguments for function FirstArg."));
+
+                               return  a_afArg[0];
+                       }
+
+                       static value_type LastArg(const value_type* a_afArg, int a_iArgc)
+                       {
+                               if (!a_iArgc)
+                                       throw mu::Parser::exception_type(_T("too few arguments for function LastArg."));
+
+                               return  a_afArg[a_iArgc - 1];
+                       }
+
+                       static value_type Sum(const value_type* a_afArg, int a_iArgc)
+                       {
+                               if (!a_iArgc)
+                                       throw mu::Parser::exception_type(_T("too few arguments for function sum."));
+
+                               value_type fRes = 0;
+                               for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i];
+                               return fRes;
+                       }
+
+                       static value_type Rnd(value_type v)
+                       {
+                               return (value_type)(1 + (v * std::rand() / (RAND_MAX + 1.0)));
+                       }
+
+                       static value_type RndWithString(const char_type*)
+                       {
+                               return (value_type)(1.0 + (1000.0 * std::rand() / (RAND_MAX + 1.0)));
+                       }
+
+                       static value_type Ping()
+                       {
+                               return 10;
+                       }
+
+                       static value_type ValueOf(const char_type*)
+                       {
+                               return 123;
+                       }
+
+                       static value_type StrFun1(const char_type* v1)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return (value_type)val;
+                       }
+
+                       static value_type StrFun2(const char_type* v1, value_type v2)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return (value_type)(val + v2);
+                       }
+
+                       static value_type StrFun3(const char_type* v1, value_type v2, value_type v3)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return val + v2 + v3;
+                       }
+
+                       static value_type StrFun4(const char_type* v1, value_type v2, value_type v3, value_type v4)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return val + v2 + v3 + v4;
+                       }
+
+                       static value_type StrFun5(const char_type* v1, value_type v2, value_type v3, value_type v4, value_type v5)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return val + v2 + v3 + v4 + v5;
+                       }
+
+                       static value_type StrFun6(const char_type* v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return val + v2 + v3 + v4 + v5 + v6;
+                       }
+
+                       static value_type StrToFloat(const char_type* a_szMsg)
+                       {
+                               value_type val(0);
+                               stringstream_type(a_szMsg) >> val;
+                               return val;
+                       }
+
+                       // postfix operator callback
+                       static value_type Mega(value_type a_fVal) 
+                       {
+                               return a_fVal * (value_type)1e6; 
+                       }
+                       
+                       static value_type Micro(value_type a_fVal)
+                       {
+                               return a_fVal * (value_type)1e-6; 
+                       }
+
+                       static value_type Milli(value_type a_fVal) 
+                       {
+                               return a_fVal / (value_type)1e3; 
+                       }
+
+                       // Custom value recognition
+                       static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal);
+
+                       // With user data
+                       static value_type FunUd0(void* data) 
+                       {
+                               return reinterpret_cast<std::intptr_t>(data); 
+                       }
+
+                       static value_type FunUd1(void* data, value_type v) 
+                       {
+                               return reinterpret_cast<std::intptr_t>(data) + v; 
+                       }
+                       
+                       static value_type FunUd2(void* data, value_type v1, value_type v2) 
+                       {
+                               return reinterpret_cast<std::intptr_t>(data) + v1 + v2; 
+                       }
+
+                       static value_type FunUd10(void* data, value_type v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6, value_type v7, value_type v8, value_type v9, value_type v10)
+                       {
+                               return reinterpret_cast<std::intptr_t>(data) + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10;
+                       }
+
+                       static value_type StrFunUd3(void* data, const char_type* v1, value_type v2, value_type v3)
+                       {
+                               int val(0);
+                               stringstream_type(v1) >> val;
+                               return reinterpret_cast<std::intptr_t>(data) + val + v2 + v3;
+                       }
+
+                       static value_type SumUd(void* data, const value_type* a_afArg, int a_iArgc)
+                       {
+                               if (!a_iArgc)
+                                       throw mu::Parser::exception_type(_T("too few arguments for function sum."));
+
+                               value_type fRes = 0;
+                               for (int i = 0; i < a_iArgc; ++i) 
+                                       fRes += a_afArg[i];
+
+                               return reinterpret_cast<std::intptr_t>(data) + fRes;
+                       }
+
+                       int TestNames();
+                       int TestSyntax();
+                       int TestMultiArg();
+                       int TestPostFix();
+                       int TestExpression();
+                       int TestInfixOprt();
+                       int TestBinOprt();
+                       int TestVarConst();
+                       int TestInterface();
+                       int TestException();
+                       int TestStrArg();
+                       int TestIfThenElse();
+                       int TestBulkMode();
+                       int TestOssFuzzTestCases();
+                       int TestOptimizer();
+
+                       void Abort() const;
+
+               public:
+                       typedef int (ParserTester::* testfun_type)();
+
+                       ParserTester();
+                       int Run();
+
+               private:
+                       std::vector<testfun_type> m_vTestFun;
+                       void AddTest(testfun_type a_pFun);
+
+                       // Test Double Parser
+                       int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);
+                       int EqnTestWithVarChange(const string_type& a_str, double a_fRes1, double a_fVar1,      double a_fRes2, double a_fVar2);
+                       int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);
+
+                       // Test Int Parser
+                       int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);
+
+                       // Test Bulkmode
+                       int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass);
+
+               };
+       } // namespace Test
+} // namespace mu
+
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
+#endif
+
diff --git a/bundled/muparser_v2_3_3/include/muParserToken.h b/bundled/muparser_v2_3_3/include/muParserToken.h
new file mode 100644 (file)
index 0000000..7410a65
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_TOKEN_H
+#define MU_PARSER_TOKEN_H
+
+#include <string>
+#include <stack>
+#include <vector>
+#include <memory>
+#include <utility>
+#include <type_traits>
+#include <cstddef>
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+#include "muParserError.h"
+#include "muParserCallback.h"
+
+/** \file
+       \brief This file contains the parser token definition.
+*/
+
+namespace mu
+{
+       template <std::size_t NbParams> struct TplCallType;
+       template <> struct TplCallType<0> { using fun_type = fun_type0; using fun_userdata_type = fun_userdata_type0; using bulkfun_type = bulkfun_type0; using bulkfun_userdata_type = bulkfun_userdata_type0; };
+       template <> struct TplCallType<1> { using fun_type = fun_type1; using fun_userdata_type = fun_userdata_type1; using bulkfun_type = bulkfun_type1; using bulkfun_userdata_type = bulkfun_userdata_type1; using strfun_type = strfun_type1; using strfun_userdata_type = strfun_userdata_type1; };
+       template <> struct TplCallType<2> { using fun_type = fun_type2; using fun_userdata_type = fun_userdata_type2; using bulkfun_type = bulkfun_type2; using bulkfun_userdata_type = bulkfun_userdata_type2; using strfun_type = strfun_type2; using strfun_userdata_type = strfun_userdata_type2; };
+       template <> struct TplCallType<3> { using fun_type = fun_type3; using fun_userdata_type = fun_userdata_type3; using bulkfun_type = bulkfun_type3; using bulkfun_userdata_type = bulkfun_userdata_type3; using strfun_type = strfun_type3; using strfun_userdata_type = strfun_userdata_type3; };
+       template <> struct TplCallType<4> { using fun_type = fun_type4; using fun_userdata_type = fun_userdata_type4; using bulkfun_type = bulkfun_type4; using bulkfun_userdata_type = bulkfun_userdata_type4; using strfun_type = strfun_type4; using strfun_userdata_type = strfun_userdata_type4; };
+       template <> struct TplCallType<5> { using fun_type = fun_type5; using fun_userdata_type = fun_userdata_type5; using bulkfun_type = bulkfun_type5; using bulkfun_userdata_type = bulkfun_userdata_type5; using strfun_type = strfun_type5; using strfun_userdata_type = strfun_userdata_type5; };
+       template <> struct TplCallType<6> { using fun_type = fun_type6; using fun_userdata_type = fun_userdata_type6; using bulkfun_type = bulkfun_type6; using bulkfun_userdata_type = bulkfun_userdata_type6; using strfun_type = strfun_type6; using strfun_userdata_type = strfun_userdata_type6; };
+       template <> struct TplCallType<7> { using fun_type = fun_type7; using fun_userdata_type = fun_userdata_type7; using bulkfun_type = bulkfun_type7; using bulkfun_userdata_type = bulkfun_userdata_type7; };
+       template <> struct TplCallType<8> { using fun_type = fun_type8; using fun_userdata_type = fun_userdata_type8; using bulkfun_type = bulkfun_type8; using bulkfun_userdata_type = bulkfun_userdata_type8; };
+       template <> struct TplCallType<9> { using fun_type = fun_type9; using fun_userdata_type = fun_userdata_type9; using bulkfun_type = bulkfun_type9; using bulkfun_userdata_type = bulkfun_userdata_type9; };
+       template <> struct TplCallType<10> { using fun_type = fun_type10; using fun_userdata_type = fun_userdata_type10; using bulkfun_type = bulkfun_type10; using bulkfun_userdata_type = bulkfun_userdata_type10; };
+
+       struct generic_callable_type
+       {
+               // Note: we keep generic_callable_type a pod for the purpose of layout
+
+               erased_fun_type _pRawFun;
+               void*           _pUserData;
+
+               template <std::size_t NbParams, typename... Args>
+               value_type call_fun(Args&&... args) const
+               {
+                       static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
+                       if (_pUserData == nullptr) 
+                       {
+                               auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
+                               return (*fun_typed_ptr)(std::forward<Args>(args)...);
+                       } 
+                       else 
+                       {
+                               auto fun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_userdata_type>(_pRawFun);
+                               return (*fun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
+                       }
+               }
+
+               template <std::size_t NbParams, typename... Args>
+               value_type call_bulkfun(Args&&... args) const
+               {
+                       static_assert(NbParams == sizeof...(Args) - 2, "mismatch between NbParams and Args");
+                       if (_pUserData == nullptr) {
+                               auto bulkfun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::bulkfun_type>(_pRawFun);
+                               return (*bulkfun_typed_ptr)(std::forward<Args>(args)...);
+                       } else {
+                               auto bulkfun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::bulkfun_userdata_type>(_pRawFun);
+                               return (*bulkfun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
+                       }
+               }
+
+               value_type call_multfun(const value_type* a_afArg, int a_iArgc) const
+               {
+                       if (_pUserData == nullptr) {
+                               auto multfun_typed_ptr = reinterpret_cast<multfun_type>(_pRawFun);
+                               return (*multfun_typed_ptr)(a_afArg, a_iArgc);
+                       } else {
+                               auto multfun_userdata_typed_ptr = reinterpret_cast<multfun_userdata_type>(_pRawFun);
+                               return (*multfun_userdata_typed_ptr)(_pUserData, a_afArg, a_iArgc);
+                       }
+               }
+
+               template <std::size_t NbParams, typename... Args>
+               value_type call_strfun(Args&&... args) const
+               {
+                       static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
+                       if (_pUserData == nullptr) 
+                       {
+                               auto strfun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_type>(_pRawFun);
+                               return (*strfun_typed_ptr)(std::forward<Args>(args)...);
+                       } 
+                       else 
+                       {
+                               auto strfun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_userdata_type>(_pRawFun);
+                               return (*strfun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
+                       }
+               }
+
+               bool operator==(generic_callable_type other) const 
+               {
+                       return _pRawFun == other._pRawFun && _pUserData == other._pUserData; 
+               }
+
+               explicit operator bool() const 
+               {
+                       return _pRawFun != nullptr; 
+               }
+
+               bool operator==(std::nullptr_t) const 
+               {
+                       return _pRawFun == nullptr; 
+               }
+               
+               bool operator!=(std::nullptr_t) const 
+               {
+                       return _pRawFun != nullptr; 
+               }
+       };
+
+       static_assert(std::is_trivial<generic_callable_type>::value, "generic_callable_type shall be trivial");
+       static_assert(std::is_standard_layout<generic_callable_type>::value, "generic_callable_type shall have standard layout");
+       // C++17: static_assert(std::is_aggregate<generic_callable_type>::value, "generic_callable_type shall be an aggregate");
+
+       /** \brief Encapsulation of the data for a single formula token.
+
+               Formula token implementation. Part of the Math Parser Package.
+               Formula tokens can be either one of the following:
+               <ul>
+                       <li>value</li>
+                       <li>variable</li>
+                       <li>function with numerical arguments</li>
+                       <li>functions with a string as argument</li>
+                       <li>prefix operators</li>
+                       <li>infix operators</li>
+                       <li>binary operator</li>
+               </ul>
+       */
+       template<typename TBase, typename TString>
+       class ParserToken final
+       {
+       private:
+
+               ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
+               ETypeCode m_iType;
+               void* m_pTok;           ///< Stores Token pointer; not applicable for all tokens
+               int  m_iIdx;            ///< An otional index to an external buffer storing the token data
+               TString m_strTok;   ///< Token string
+               TString m_strVal;   ///< Value for string variables
+               value_type m_fVal;  ///< the value 
+               std::unique_ptr<ParserCallback> m_pCallback;
+
+       public:
+
+               /** \brief Constructor (default).
+
+                       Sets token to an neutral state of type cmUNKNOWN.
+                       \throw nothrow
+                       \sa ECmdCode
+               */
+               ParserToken()
+                       :m_iCode(cmUNKNOWN)
+                       , m_iType(tpVOID)
+                       , m_pTok(0)
+                       , m_iIdx(-1)
+                       , m_strTok()
+                       , m_strVal()
+                       , m_fVal(0)
+                       , m_pCallback()
+               {}
+
+               //------------------------------------------------------------------------------
+               /** \brief Create token from another one.
+
+                       Implemented by calling Assign(...)
+                       \throw nothrow
+                       \post m_iType==cmUNKNOWN
+                       \sa #Assign
+               */
+               ParserToken(const ParserToken& a_Tok)
+               {
+                       Assign(a_Tok);
+               }
+
+               
+               /** \brief Assignment operator.
+
+                       Copy token state from another token and return this.
+                       Implemented by calling Assign(...).
+                       \throw nothrow
+               */
+               ParserToken& operator=(const ParserToken& a_Tok)
+               {
+                       Assign(a_Tok);
+                       return *this;
+               }
+
+
+               /** \brief Copy token information from argument.
+
+                       \throw nothrow
+               */
+               void Assign(const ParserToken& a_Tok)
+               {
+                       m_iCode = a_Tok.m_iCode;
+                       m_pTok = a_Tok.m_pTok;
+                       m_strTok = a_Tok.m_strTok;
+                       m_iIdx = a_Tok.m_iIdx;
+                       m_strVal = a_Tok.m_strVal;
+                       m_iType = a_Tok.m_iType;
+                       m_fVal = a_Tok.m_fVal;
+                       // create new callback object if a_Tok has one 
+                       m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Assign a token type.
+
+                 Token may not be of type value, variable or function. Those have separate set functions.
+
+                 \pre [assert] a_iType!=cmVAR
+                 \pre [assert] a_iType!=cmVAL
+                 \pre [assert] a_iType!=cmFUNC
+                 \post m_fVal = 0
+                 \post m_pTok = 0
+               */
+               ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString())
+               {
+                       // The following types can't be set this way, they have special Set functions
+                       MUP_ASSERT(a_iType != cmVAR);
+                       MUP_ASSERT(a_iType != cmVAL);
+                       MUP_ASSERT(a_iType != cmFUNC);
+
+                       m_iCode = a_iType;
+                       m_iType = tpVOID;
+                       m_pTok = 0;
+                       m_strTok = a_strTok;
+                       m_iIdx = -1;
+
+                       return *this;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Set Callback type. */
+               ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
+               {
+                       MUP_ASSERT(a_pCallback.IsValid());
+
+                       m_iCode = a_pCallback.GetCode();
+                       m_iType = tpVOID;
+                       m_strTok = a_sTok;
+                       m_pCallback.reset(new ParserCallback(a_pCallback));
+
+                       m_pTok = 0;
+                       m_iIdx = -1;
+
+                       return *this;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Make this token a value token.
+
+                       Member variables not necessary for value tokens will be invalidated.
+                       \throw nothrow
+               */
+               ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString())
+               {
+                       m_iCode = cmVAL;
+                       m_iType = tpDBL;
+                       m_fVal = a_fVal;
+                       m_strTok = a_strTok;
+                       m_iIdx = -1;
+
+                       m_pTok = 0;
+                       m_pCallback.reset(0);
+
+                       return *this;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief make this token a variable token.
+
+                       Member variables not necessary for variable tokens will be invalidated.
+                       \throw nothrow
+               */
+               ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok)
+               {
+                       m_iCode = cmVAR;
+                       m_iType = tpDBL;
+                       m_strTok = a_strTok;
+                       m_iIdx = -1;
+                       m_pTok = (void*)a_pVar;
+                       m_pCallback.reset(0);
+                       return *this;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Make this token a variable token.
+
+                       Member variables not necessary for variable tokens will be invalidated.
+                       \throw nothrow
+               */
+               ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize)
+               {
+                       m_iCode = cmSTRING;
+                       m_iType = tpSTR;
+                       m_strTok = a_strTok;
+                       m_iIdx = static_cast<int>(a_iSize);
+
+                       m_pTok = 0;
+                       m_pCallback.reset(0);
+                       return *this;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Set an index associated with the token related data.
+
+                       In cmSTRFUNC - This is the index to a string table in the main parser.
+                       \param a_iIdx The index the string function result will take in the bytecode parser.
+                       \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
+               */
+               void SetIdx(int a_iIdx)
+               {
+                       if (m_iCode != cmSTRING || a_iIdx < 0)
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       m_iIdx = a_iIdx;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return Index associated with the token related data.
+
+                       In cmSTRFUNC - This is the index to a string table in the main parser.
+
+                       \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
+                       \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
+               */
+               int GetIdx() const
+               {
+                       if (m_iIdx < 0 || m_iCode != cmSTRING)
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       return m_iIdx;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return the token type.
+
+                       \return #m_iType
+                       \throw nothrow
+               */
+               ECmdCode GetCode() const
+               {
+                       if (m_pCallback.get())
+                       {
+                               return m_pCallback->GetCode();
+                       }
+                       else
+                       {
+                               return m_iCode;
+                       }
+               }
+
+               //------------------------------------------------------------------------------
+               ETypeCode GetType() const
+               {
+                       if (m_pCallback.get())
+                       {
+                               return m_pCallback->GetType();
+                       }
+                       else
+                       {
+                               return m_iType;
+                       }
+               }
+
+               //------------------------------------------------------------------------------
+               int GetPri() const
+               {
+                       if (!m_pCallback.get())
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       return m_pCallback->GetPri();
+               }
+
+               //------------------------------------------------------------------------------
+               EOprtAssociativity GetAssociativity() const
+               {
+                       if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN)
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       return m_pCallback->GetAssociativity();
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return the address of the callback function assoziated with
+                                  function and operator tokens.
+
+                       \return The pointer stored in #m_pTok.
+                       \throw exception_type if token type is non of:
+                                  <ul>
+                                        <li>cmFUNC</li>
+                                        <li>cmSTRFUNC</li>
+                                        <li>cmPOSTOP</li>
+                                        <li>cmINFIXOP</li>
+                                        <li>cmOPRT_BIN</li>
+                                  </ul>
+                       \sa ECmdCode
+               */
+               generic_callable_type GetFuncAddr() const
+               {
+                       return (m_pCallback.get())
+                               ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(),
+                                                       m_pCallback->GetUserData()}
+                               : generic_callable_type{};
+               }
+
+               //------------------------------------------------------------------------------
+               /** \biref Get value of the token.
+
+                       Only applicable to variable and value tokens.
+                       \throw exception_type if token is no value/variable token.
+               */
+               TBase GetVal() const
+               {
+                       switch (m_iCode)
+                       {
+                       case cmVAL:  return m_fVal;
+                       case cmVAR:  return *((TBase*)m_pTok);
+                       default:     throw ParserError(ecVAL_EXPECTED);
+                       }
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Get address of a variable token.
+
+                 Valid only if m_iType==CmdVar.
+                 \throw exception_type if token is no variable token.
+               */
+               TBase* GetVar() const
+               {
+                       if (m_iCode != cmVAR)
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       return (TBase*)m_pTok;
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return the number of function arguments.
+
+                 Valid only if m_iType==CmdFUNC.
+               */
+               int GetArgCount() const
+               {
+                       MUP_ASSERT(m_pCallback.get());
+
+                       if (!m_pCallback->IsValid())
+                               throw ParserError(ecINTERNAL_ERROR);
+
+                       return m_pCallback->GetArgc();
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return true if the token is a function token that can be optimized.
+               */
+               bool IsOptimizable() const
+               {
+                       return m_pCallback->IsValid() && m_pCallback->IsOptimizable();
+               }
+
+               //------------------------------------------------------------------------------
+               /** \brief Return the token identifier.
+
+                       If #m_iType is cmSTRING the token identifier is the value of the string argument
+                       for a string function.
+                       \return #m_strTok
+                       \throw nothrow
+                       \sa m_strTok
+               */
+               const TString& GetAsString() const
+               {
+                       return m_strTok;
+               }
+       };
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
+#endif
diff --git a/bundled/muparser_v2_3_3/include/muParserTokenReader.h b/bundled/muparser_v2_3_3/include/muParserTokenReader.h
new file mode 100644 (file)
index 0000000..0ea19f5
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MU_PARSER_TOKEN_READER_H
+#define MU_PARSER_TOKEN_READER_H
+
+#include <cstdio>
+#include <cstring>
+#include <list>
+#include <map>
+#include <memory>
+#include <stack>
+#include <string>
+
+#include "muParserDef.h"
+#include "muParserToken.h"
+
+/** \file
+       \brief This file contains the parser token reader definition.
+*/
+
+
+namespace mu
+{
+       // Forward declaration
+       class ParserBase;
+
+       /** \brief Token reader for the ParserBase class. */
+       class ParserTokenReader final
+       {
+       private:
+
+               typedef ParserToken<value_type, string_type> token_type;
+
+       public:
+
+               ParserTokenReader(ParserBase* a_pParent);
+               ParserTokenReader* Clone(ParserBase* a_pParent) const;
+
+               void AddValIdent(identfun_type a_pCallback);
+               void SetVarCreator(facfun_type a_pFactory, void* pUserData);
+               void SetFormula(const string_type& a_strFormula);
+               void SetArgSep(char_type cArgSep);
+
+               int GetPos() const;
+               const string_type& GetExpr() const;
+               varmap_type& GetUsedVar();
+               char_type GetArgSep() const;
+
+               void IgnoreUndefVar(bool bIgnore);
+               void ReInit();
+               token_type ReadNextToken();
+
+       private:
+
+               /** \brief Syntax codes.
+
+                       The syntax codes control the syntax check done during the first time parsing of
+                       the expression string. They are flags that indicate which tokens are allowed next
+                       if certain tokens are identified.
+               */
+               enum ESynCodes
+               {
+                       noBO = 1 << 0,                  ///< to avoid i.e. "cos(7)(" 
+                       noBC = 1 << 1,                  ///< to avoid i.e. "sin)" or "()"
+                       noVAL = 1 << 2,                 ///< to avoid i.e. "tan 2" or "sin(8)3.14"
+                       noVAR = 1 << 3,                 ///< to avoid i.e. "sin a" or "sin(8)a"
+                       noARG_SEP = 1 << 4,             ///< to avoid i.e. ",," or "+," ...
+                       noFUN = 1 << 5,                 ///< to avoid i.e. "sqrt cos" or "(1)sin"       
+                       noOPT = 1 << 6,                 ///< to avoid i.e. "(+)"
+                       noPOSTOP = 1 << 7,              ///< to avoid i.e. "(5!!)" "sin!"
+                       noINFIXOP = 1 << 8,             ///< to avoid i.e. "++4" "!!4"
+                       noEND = 1 << 9,                 ///< to avoid unexpected end of formula
+                       noSTR = 1 << 10,                ///< to block numeric arguments on string functions
+                       noASSIGN = 1 << 11,             ///< to block assignment to constant i.e. "4=7"
+                       noIF = 1 << 12,
+                       noELSE = 1 << 13,
+                       sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
+                       noANY = ~0                              ///< All of he above flags set
+               };
+
+               ParserTokenReader(const ParserTokenReader& a_Reader);
+               ParserTokenReader& operator=(const ParserTokenReader& a_Reader);
+               void Assign(const ParserTokenReader& a_Reader);
+
+               void SetParent(ParserBase* a_pParent);
+               int ExtractToken(const char_type* a_szCharSet, string_type& a_strTok, std::size_t a_iPos) const;
+               int ExtractOperatorToken(string_type& a_sTok, std::size_t a_iPos) const;
+
+               bool IsBuiltIn(token_type& a_Tok);
+               bool IsArgSep(token_type& a_Tok);
+               bool IsEOF(token_type& a_Tok);
+               bool IsInfixOpTok(token_type& a_Tok);
+               bool IsFunTok(token_type& a_Tok);
+               bool IsPostOpTok(token_type& a_Tok);
+               bool IsOprt(token_type& a_Tok);
+               bool IsValTok(token_type& a_Tok);
+               bool IsVarTok(token_type& a_Tok);
+               bool IsStrVarTok(token_type& a_Tok);
+               bool IsUndefVarTok(token_type& a_Tok);
+               bool IsString(token_type& a_Tok);
+               void Error(EErrorCodes a_iErrc, int a_iPos = -1, const string_type& a_sTok = string_type()) const;
+
+               token_type& SaveBeforeReturn(const token_type& tok);
+
+               ParserBase* m_pParser;
+               string_type m_strFormula;
+               int  m_iPos;
+               int  m_iSynFlags;
+               bool m_bIgnoreUndefVar;
+
+               const funmap_type* m_pFunDef;
+               const funmap_type* m_pPostOprtDef;
+               const funmap_type* m_pInfixOprtDef;
+               const funmap_type* m_pOprtDef;
+               const valmap_type* m_pConstDef;
+               const strmap_type* m_pStrVarDef;
+
+               varmap_type* m_pVarDef;  ///< The only non const pointer to parser internals
+               facfun_type m_pFactory;
+               void* m_pFactoryData;
+               std::list<identfun_type> m_vIdentFun; ///< Value token identification function
+               varmap_type m_UsedVar;
+               value_type m_fZero;      ///< Dummy value of zero, referenced by undefined variables
+               
+               std::stack<int> m_bracketStack;
+
+               token_type m_lastTok;
+               char_type m_cArgSep;     ///< The character used for separating function arguments
+       };
+} // namespace mu
+
+#endif
+
+
diff --git a/bundled/muparser_v2_3_3/src/muParser.cpp b/bundled/muparser_v2_3_3/src/muParser.cpp
new file mode 100644 (file)
index 0000000..0ebef2a
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParser.h"
+#include "muParserTemplateMagic.h"
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+using namespace std;
+
+/** \file
+       \brief Implementation of the standard floating point parser.
+*/
+
+
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+       //---------------------------------------------------------------------------
+       /** \brief Default value recognition callback.
+               \param [in] a_szExpr Pointer to the expression
+               \param [in, out] a_iPos Pointer to an index storing the current position within the expression
+               \param [out] a_fVal Pointer where the value should be stored in case one is found.
+               \return 1 if a value was found 0 otherwise.
+       */
+       int Parser::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
+       {
+               value_type fVal(0);
+
+               stringstream_type stream(a_szExpr);
+               stream.seekg(0);        // todo:  check if this really is necessary
+               stream.imbue(Parser::s_locale);
+               stream >> fVal;
+               stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
+
+               if (iEnd == (stringstream_type::pos_type) - 1)
+                       return 0;
+
+               *a_iPos += (int)iEnd;
+               *a_fVal = fVal;
+               return 1;
+       }
+
+
+       //---------------------------------------------------------------------------
+       /** \brief Constructor.
+
+         Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+       */
+       Parser::Parser()
+               :ParserBase()
+       {
+               AddValIdent(IsVal);
+
+               InitCharSets();
+               InitFun();
+               InitConst();
+               InitOprt();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Define the character sets.
+               \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
+
+         This function is used for initializing the default character sets that define
+         the characters to be useable in function and variable names and operators.
+       */
+       void Parser::InitCharSets()
+       {
+               DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+               DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}"));
+               DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_"));
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Initialize the default functions. */
+       void Parser::InitFun()
+       {
+               if (mu::TypeInfo<mu::value_type>::IsInteger())
+               {
+                       // When setting MUP_BASETYPE to an integer type
+                       // Place functions for dealing with integer values here
+                       // ...
+                       // ...
+                       // ...
+               }
+               else
+               {
+                       // trigonometric functions
+                       DefineFun(_T("sin"), MathImpl<value_type>::Sin);
+                       DefineFun(_T("cos"), MathImpl<value_type>::Cos);
+                       DefineFun(_T("tan"), MathImpl<value_type>::Tan);
+                       // arcus functions
+                       DefineFun(_T("asin"), MathImpl<value_type>::ASin);
+                       DefineFun(_T("acos"), MathImpl<value_type>::ACos);
+                       DefineFun(_T("atan"), MathImpl<value_type>::ATan);
+                       DefineFun(_T("atan2"), MathImpl<value_type>::ATan2);
+                       // hyperbolic functions
+                       DefineFun(_T("sinh"), MathImpl<value_type>::Sinh);
+                       DefineFun(_T("cosh"), MathImpl<value_type>::Cosh);
+                       DefineFun(_T("tanh"), MathImpl<value_type>::Tanh);
+                       // arcus hyperbolic functions
+                       DefineFun(_T("asinh"), MathImpl<value_type>::ASinh);
+                       DefineFun(_T("acosh"), MathImpl<value_type>::ACosh);
+                       DefineFun(_T("atanh"), MathImpl<value_type>::ATanh);
+                       // Logarithm functions
+                       DefineFun(_T("log2"), MathImpl<value_type>::Log2);
+                       DefineFun(_T("log10"), MathImpl<value_type>::Log10);
+                       DefineFun(_T("log"), MathImpl<value_type>::Log);
+                       DefineFun(_T("ln"), MathImpl<value_type>::Log);
+                       // misc
+                       DefineFun(_T("exp"), MathImpl<value_type>::Exp);
+                       DefineFun(_T("sqrt"), MathImpl<value_type>::Sqrt);
+                       DefineFun(_T("sign"), MathImpl<value_type>::Sign);
+                       DefineFun(_T("rint"), MathImpl<value_type>::Rint);
+                       DefineFun(_T("abs"), MathImpl<value_type>::Abs);
+                       // Functions with variable number of arguments
+                       DefineFun(_T("sum"), MathImpl<value_type>::Sum);
+                       DefineFun(_T("avg"), MathImpl<value_type>::Avg);
+                       DefineFun(_T("min"), MathImpl<value_type>::Min);
+                       DefineFun(_T("max"), MathImpl<value_type>::Max);
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Initialize constants.
+
+         By default the parser recognizes two constants. Pi ("pi") and the Eulerian
+         number ("_e").
+       */
+       void Parser::InitConst()
+       {
+               DefineConst(_T("_pi"), MathImpl<value_type>::CONST_PI);
+               DefineConst(_T("_e"), MathImpl<value_type>::CONST_E);
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Initialize operators.
+
+         By default only the unary minus operator is added.
+       */
+       void Parser::InitOprt()
+       {
+               DefineInfixOprt(_T("-"), MathImpl<value_type>::UnaryMinus);
+               DefineInfixOprt(_T("+"), MathImpl<value_type>::UnaryPlus);
+       }
+
+       //---------------------------------------------------------------------------
+       void Parser::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
+       {
+               // this is just sample code to illustrate modifying variable names on the fly.
+               // I'm not sure anyone really needs such a feature...
+               /*
+
+
+               string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
+               string sRepl = std::string("_") + sVar + "_";
+
+               int nOrigVarEnd = nEnd;
+               cout << "variable detected!\n";
+               cout << "  Expr: " << *pExpr << "\n";
+               cout << "  Start: " << nStart << "\n";
+               cout << "  End: " << nEnd << "\n";
+               cout << "  Var: \"" << sVar << "\"\n";
+               cout << "  Repl: \"" << sRepl << "\"\n";
+               nEnd = nStart + sRepl.length();
+               cout << "  End: " << nEnd << "\n";
+               pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
+               cout << "  New expr: " << *pExpr << "\n";
+               */
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Numerically differentiate with regard to a variable.
+               \param [in] a_Var Pointer to the differentiation variable.
+               \param [in] a_fPos Position at which the differentiation should take place.
+               \param [in] a_fEpsilon Epsilon used for the numerical differentiation.
+
+               Numerical differentiation uses a 5 point operator yielding a 4th order
+               formula. The default value for epsilon is 0.00074 which is
+               numeric_limits<double>::epsilon() ^ (1/5).
+       */
+       value_type Parser::Diff(value_type* a_Var, value_type  a_fPos, value_type  a_fEpsilon) const
+       {
+               value_type fRes(0);
+               value_type fBuf(*a_Var);
+               value_type f[4] = { 0,0,0,0 };
+               value_type fEpsilon(a_fEpsilon);
+
+               // Backwards compatible calculation of epsilon inc case the user doesn't provide
+               // his own epsilon
+               if (fEpsilon == 0)
+                       fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
+
+               *a_Var = a_fPos + 2 * fEpsilon;  f[0] = Eval();
+               *a_Var = a_fPos + 1 * fEpsilon;  f[1] = Eval();
+               *a_Var = a_fPos - 1 * fEpsilon;  f[2] = Eval();
+               *a_Var = a_fPos - 2 * fEpsilon;  f[3] = Eval();
+               *a_Var = fBuf; // restore variable
+
+               fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon);
+               return fRes;
+       }
+} // namespace mu
diff --git a/bundled/muparser_v2_3_3/src/muParserBase.cpp b/bundled/muparser_v2_3_3/src/muParserBase.cpp
new file mode 100644 (file)
index 0000000..a28a7fc
--- /dev/null
@@ -0,0 +1,1922 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2022 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserBase.h"
+#include "muParserTemplateMagic.h"
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <algorithm>
+#include <cmath>
+#include <memory>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <locale>
+#include <cassert>
+#include <cctype>
+
+#ifdef MUP_USE_OPENMP
+
+#include <omp.h>
+
+#endif
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+using namespace std;
+
+/** \file
+       \brief This file contains the basic implementation of the muparser engine.
+*/
+
+namespace mu
+{
+       std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));
+
+       bool ParserBase::g_DbgDumpCmdCode = false;
+       bool ParserBase::g_DbgDumpStack = false;
+
+       //------------------------------------------------------------------------------
+       /** \brief Identifiers for built in binary operators.
+
+               When defining custom binary operators with #AddOprt(...) make sure not to choose
+               names conflicting with these definitions.
+       */
+       const char_type* ParserBase::c_DefaultOprt[] =
+       {
+         _T("<="), _T(">="),  _T("!="),
+         _T("=="), _T("<"),   _T(">"),
+         _T("+"),  _T("-"),   _T("*"),
+         _T("/"),  _T("^"),   _T("&&"),
+         _T("||"), _T("="),   _T("("),
+         _T(")"),   _T("?"),  _T(":"), 0
+       };
+
+       const int ParserBase::s_MaxNumOpenMPThreads = 16;
+
+       //------------------------------------------------------------------------------
+       /** \brief Constructor.
+               \param a_szFormula the formula to interpret.
+               \throw ParserException if a_szFormula is nullptr.
+       */
+       ParserBase::ParserBase()
+               : m_pParseFormula(&ParserBase::ParseString)
+               , m_vRPN()
+               , m_vStringBuf()
+               , m_pTokenReader()
+               , m_FunDef()
+               , m_PostOprtDef()
+               , m_InfixOprtDef()
+               , m_OprtDef()
+               , m_ConstDef()
+               , m_StrVarDef()
+               , m_VarDef()
+               , m_bBuiltInOp(true)
+               , m_sNameChars()
+               , m_sOprtChars()
+               , m_sInfixOprtChars()
+               , m_vStackBuffer()
+               , m_nFinalResultIdx(0)
+       {
+               InitTokenReader();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Copy constructor.
+
+         The parser can be safely copy constructed but the bytecode is reset during
+         copy construction.
+       */
+       ParserBase::ParserBase(const ParserBase& a_Parser)
+               : m_pParseFormula(&ParserBase::ParseString)
+               , m_vRPN()
+               , m_vStringBuf()
+               , m_pTokenReader()
+               , m_FunDef()
+               , m_PostOprtDef()
+               , m_InfixOprtDef()
+               , m_OprtDef()
+               , m_ConstDef()
+               , m_StrVarDef()
+               , m_VarDef()
+               , m_bBuiltInOp(true)
+               , m_sNameChars()
+               , m_sOprtChars()
+               , m_sInfixOprtChars()
+       {
+               m_pTokenReader.reset(new token_reader_type(this));
+               Assign(a_Parser);
+       }
+
+       //---------------------------------------------------------------------------
+       ParserBase::~ParserBase()
+       {}
+
+       //---------------------------------------------------------------------------
+       /** \brief Assignment operator.
+
+         Implemented by calling Assign(a_Parser). Self assignment is suppressed.
+         \param a_Parser Object to copy to this.
+         \return *this
+         \throw nothrow
+       */
+       ParserBase& ParserBase::operator=(const ParserBase& a_Parser)
+       {
+               Assign(a_Parser);
+               return *this;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Copy state of a parser object to this.
+
+         Clears Variables and Functions of this parser.
+         Copies the states of all internal variables.
+         Resets parse function to string parse mode.
+
+         \param a_Parser the source object.
+       */
+       void ParserBase::Assign(const ParserBase& a_Parser)
+       {
+               if (&a_Parser == this)
+                       return;
+
+               // Don't copy bytecode instead cause the parser to create new bytecode
+               // by resetting the parse function.
+               ReInit();
+
+               m_ConstDef = a_Parser.m_ConstDef;         // Copy user define constants
+               m_VarDef = a_Parser.m_VarDef;           // Copy user defined variables
+               m_bBuiltInOp = a_Parser.m_bBuiltInOp;
+               m_vStringBuf = a_Parser.m_vStringBuf;
+               m_vStackBuffer = a_Parser.m_vStackBuffer;
+               m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
+               m_StrVarDef = a_Parser.m_StrVarDef;
+               m_vStringVarBuf = a_Parser.m_vStringVarBuf;
+               m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));
+
+               // Copy function and operator callbacks
+               m_FunDef = a_Parser.m_FunDef;             // Copy function definitions
+               m_PostOprtDef = a_Parser.m_PostOprtDef;   // post value unary operators
+               m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
+               m_OprtDef = a_Parser.m_OprtDef;           // binary operators
+
+               m_sNameChars = a_Parser.m_sNameChars;
+               m_sOprtChars = a_Parser.m_sOprtChars;
+               m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Set the decimal separator.
+               \param cDecSep Decimal separator as a character value.
+               \sa SetThousandsSep
+
+               By default muparser uses the "C" locale. The decimal separator of this
+               locale is overwritten by the one provided here.
+       */
+       void ParserBase::SetDecSep(char_type cDecSep)
+       {
+               char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
+               s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Sets the thousands operator.
+               \param cThousandsSep The thousands separator as a character
+               \sa SetDecSep
+
+               By default muparser uses the "C" locale. The thousands separator of this
+               locale is overwritten by the one provided here.
+       */
+       void ParserBase::SetThousandsSep(char_type cThousandsSep)
+       {
+               char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
+               s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Resets the locale.
+
+         The default locale used "." as decimal separator, no thousands separator and
+         "," as function argument separator.
+       */
+       void ParserBase::ResetLocale()
+       {
+               s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
+               SetArgSep(',');
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Initialize the token reader.
+
+         Create new token reader object and submit pointers to function, operator,
+         constant and variable definitions.
+
+         \post m_pTokenReader.get()!=0
+         \throw nothrow
+       */
+       void ParserBase::InitTokenReader()
+       {
+               m_pTokenReader.reset(new token_reader_type(this));
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Reset parser to string parsing mode and clear internal buffers.
+
+               Clear bytecode, reset the token reader.
+               \throw nothrow
+       */
+       void ParserBase::ReInit() const
+       {
+               m_pParseFormula = &ParserBase::ParseString;
+               m_vStringBuf.clear();
+               m_vRPN.clear();
+               m_pTokenReader->ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       void ParserBase::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
+       {}
+
+       //---------------------------------------------------------------------------
+       /** \brief Returns the bytecode of the current expression.
+       */
+       const ParserByteCode& ParserBase::GetByteCode() const
+       {
+               return m_vRPN;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Returns the version of muparser.
+               \param eInfo A flag indicating whether the full version info should be
+                                        returned or not.
+
+         Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS
+         are returned only if eInfo==pviFULL.
+       */
+       string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const
+       {
+               stringstream_type ss;
+
+               ss << ParserVersion;
+
+               if (eInfo == pviFULL)
+               {
+                       ss << _T(" (") << ParserVersionDate;
+                       ss << std::dec << _T("; ") << sizeof(void*) * 8 << _T("BIT");
+
+#ifdef _DEBUG
+                       ss << _T("; DEBUG");
+#else 
+                       ss << _T("; RELEASE");
+#endif
+
+#ifdef _UNICODE
+                       ss << _T("; UNICODE");
+#else
+#ifdef _MBCS
+                       ss << _T("; MBCS");
+#else
+                       ss << _T("; ASCII");
+#endif
+#endif
+
+#ifdef MUP_USE_OPENMP
+                       ss << _T("; OPENMP");
+#endif
+
+                       ss << _T(")");
+               }
+
+               return ss.str();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a value parsing function.
+
+               When parsing an expression muParser tries to detect values in the expression
+               string using different valident callbacks. Thus it's possible to parse
+               for hex values, binary values and floating point values.
+       */
+       void ParserBase::AddValIdent(identfun_type a_pCallback)
+       {
+               m_pTokenReader->AddValIdent(a_pCallback);
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Set a function that can create variable pointer for unknown expression variables.
+               \param a_pFactory A pointer to the variable factory.
+               \param pUserData A user defined context pointer.
+       */
+       void ParserBase::SetVarFactory(facfun_type a_pFactory, void* pUserData)
+       {
+               m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a function or operator callback to the parser. */
+       void ParserBase::AddCallback(
+               const string_type& a_strName,
+               const ParserCallback& a_Callback,
+               funmap_type& a_Storage,
+               const char_type* a_szCharSet)
+       {
+               if (!a_Callback.IsValid())
+                       Error(ecINVALID_FUN_PTR);
+
+               const funmap_type* pFunMap = &a_Storage;
+
+               // Check for conflicting operator or function names
+               if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
+                       Error(ecNAME_CONFLICT, -1, a_strName);
+
+               if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
+                       Error(ecNAME_CONFLICT, -1, a_strName);
+
+               if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
+                       Error(ecNAME_CONFLICT, -1, a_strName);
+
+               if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
+                       Error(ecNAME_CONFLICT, -1, a_strName);
+
+               CheckOprt(a_strName, a_Callback, a_szCharSet);
+               a_Storage[a_strName] = a_Callback;
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Check if a name contains invalid characters.
+
+               \throw ParserException if the name contains invalid characters.
+       */
+       void ParserBase::CheckOprt(const string_type& a_sName,
+               const ParserCallback& a_Callback,
+               const string_type& a_szCharSet) const
+       {
+               if (!a_sName.length() ||
+                       (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
+                       (a_sName[0] >= '0' && a_sName[0] <= '9'))
+               {
+                       switch (a_Callback.GetCode())
+                       {
+                       case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); break;
+                       case cmOPRT_INFIX:   Error(ecINVALID_INFIX_IDENT, -1, a_sName); break;
+                       default:             Error(ecINVALID_NAME, -1, a_sName);
+                       }
+               }
+       }
+
+
+       /** \brief Check if a name contains invalid characters.
+               \throw ParserException if the name contains invalid characters.
+       */
+       void ParserBase::CheckName(const string_type& a_sName, const string_type& a_szCharSet) const
+       {
+               if (!a_sName.length() ||
+                       (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
+                       (a_sName[0] >= '0' && a_sName[0] <= '9'))
+               {
+                       Error(ecINVALID_NAME);
+               }
+       }
+
+       /** \brief Set the formula.
+               \param a_strFormula Formula as string_type
+               \throw ParserException in case of syntax errors.
+
+               Triggers first time calculation thus the creation of the bytecode and
+               scanning of used variables.
+       */
+       void ParserBase::SetExpr(const string_type& a_sExpr)
+       {
+               // Check locale compatibility
+               if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(s_locale).decimal_point())
+                       Error(ecLOCALE);
+
+               // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me
+               if (a_sExpr.length() >= MaxLenExpression)
+                       Error(ecEXPRESSION_TOO_LONG, 0, a_sExpr);
+
+               m_pTokenReader->SetFormula(a_sExpr + _T(" "));
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Get the default symbols used for the built in operators.
+               \sa c_DefaultOprt
+       */
+       const char_type** ParserBase::GetOprtDef() const
+       {
+               return (const char_type**)(&c_DefaultOprt[0]);
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Define the set of valid characters to be used in names of
+                          functions, variables, constants.
+       */
+       void ParserBase::DefineNameChars(const char_type* a_szCharset)
+       {
+               m_sNameChars = a_szCharset;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Define the set of valid characters to be used in names of
+                          binary operators and postfix operators.
+       */
+       void ParserBase::DefineOprtChars(const char_type* a_szCharset)
+       {
+               m_sOprtChars = a_szCharset;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Define the set of valid characters to be used in names of
+                          infix operators.
+       */
+       void ParserBase::DefineInfixOprtChars(const char_type* a_szCharset)
+       {
+               m_sInfixOprtChars = a_szCharset;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Virtual function that defines the characters allowed in name identifiers.
+               \sa #ValidOprtChars, #ValidPrefixOprtChars
+       */
+       const char_type* ParserBase::ValidNameChars() const
+       {
+               MUP_ASSERT(m_sNameChars.size());
+               return m_sNameChars.c_str();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Virtual function that defines the characters allowed in operator definitions.
+               \sa #ValidNameChars, #ValidPrefixOprtChars
+       */
+       const char_type* ParserBase::ValidOprtChars() const
+       {
+               MUP_ASSERT(m_sOprtChars.size());
+               return m_sOprtChars.c_str();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Virtual function that defines the characters allowed in infix operator definitions.
+               \sa #ValidNameChars, #ValidOprtChars
+       */
+       const char_type* ParserBase::ValidInfixOprtChars() const
+       {
+               MUP_ASSERT(m_sInfixOprtChars.size());
+               return m_sInfixOprtChars.c_str();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a user defined operator.
+               \post Will reset the Parser to string parsing mode.
+       */
+       void ParserBase::DefinePostfixOprt(const string_type& a_sName, fun_type1 a_pFun, bool a_bAllowOpt)
+       {
+               if (a_sName.length() > MaxLenIdentifier)
+                       Error(ecIDENTIFIER_TOO_LONG);
+
+               AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), m_PostOprtDef, ValidOprtChars());
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Initialize user defined functions.
+
+         Calls the virtual functions InitFun(), InitConst() and InitOprt().
+       */
+       void ParserBase::Init()
+       {
+               InitCharSets();
+               InitFun();
+               InitConst();
+               InitOprt();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a user defined operator.
+               \post Will reset the Parser to string parsing mode.
+               \param [in] a_sName  operator Identifier
+               \param [in] a_pFun  Operator callback function
+               \param [in] a_iPrec  Operator Precedence (default=prSIGN)
+               \param [in] a_bAllowOpt  True if operator is volatile (default=false)
+               \sa EPrec
+       */
+       void ParserBase::DefineInfixOprt(const string_type& a_sName, fun_type1 a_pFun, int a_iPrec, bool a_bAllowOpt)
+       {
+               if (a_sName.length() > MaxLenIdentifier)
+                       Error(ecIDENTIFIER_TOO_LONG);
+
+               AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, ValidInfixOprtChars());
+       }
+
+
+       //---------------------------------------------------------------------------
+       /** \brief Define a binary operator.
+               \param [in] a_sName The identifier of the operator.
+               \param [in] a_pFun Pointer to the callback function.
+               \param [in] a_iPrec Precedence of the operator.
+               \param [in] a_eAssociativity The associativity of the operator.
+               \param [in] a_bAllowOpt If this is true the operator may be optimized away.
+
+               Adds a new Binary operator the the parser instance.
+       */
+       void ParserBase::DefineOprt(const string_type& a_sName, fun_type2 a_pFun, unsigned a_iPrec, EOprtAssociativity a_eAssociativity, bool a_bAllowOpt)
+       {
+               if (a_sName.length() > MaxLenIdentifier)
+                       Error(ecIDENTIFIER_TOO_LONG);
+
+               // Check for conflicts with built in operator names
+               for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i)
+               {
+                       if (a_sName == string_type(c_DefaultOprt[i]))
+                       {
+                               Error(ecBUILTIN_OVERLOAD, -1, a_sName);
+                       }
+               }
+
+               AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), m_OprtDef, ValidOprtChars());
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Define a new string constant.
+               \param [in] a_strName The name of the constant.
+               \param [in] a_strVal the value of the constant.
+       */
+       void ParserBase::DefineStrConst(const string_type& a_strName, const string_type& a_strVal)
+       {
+               // Test if a constant with that names already exists
+               if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
+                       Error(ecNAME_CONFLICT);
+
+               CheckName(a_strName, ValidNameChars());
+
+               m_vStringVarBuf.push_back(a_strVal);                // Store variable string in internal buffer
+               m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1;  // bind buffer index to variable name
+
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a user defined variable.
+               \param [in] a_sName the variable name
+               \param [in] a_pVar A pointer to the variable value.
+               \post Will reset the Parser to string parsing mode.
+               \throw ParserException in case the name contains invalid signs or a_pVar is nullptr.
+       */
+       void ParserBase::DefineVar(const string_type& a_sName, value_type* a_pVar)
+       {
+               if (a_pVar == 0)
+                       Error(ecINVALID_VAR_PTR);
+
+               if (a_sName.length() > MaxLenIdentifier)
+                       Error(ecIDENTIFIER_TOO_LONG);
+
+               // Test if a constant with that names already exists
+               if (m_ConstDef.find(a_sName) != m_ConstDef.end())
+                       Error(ecNAME_CONFLICT);
+
+               CheckName(a_sName, ValidNameChars());
+               m_VarDef[a_sName] = a_pVar;
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Add a user defined constant.
+               \param [in] a_sName The name of the constant.
+               \param [in] a_fVal the value of the constant.
+               \post Will reset the Parser to string parsing mode.
+               \throw ParserException in case the name contains invalid signs.
+       */
+       void ParserBase::DefineConst(const string_type& a_sName, value_type a_fVal)
+       {
+               if (a_sName.length() > MaxLenIdentifier)
+                       Error(ecIDENTIFIER_TOO_LONG);
+
+               CheckName(a_sName, ValidNameChars());
+               m_ConstDef[a_sName] = a_fVal;
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Get operator priority.
+               \throw ParserException if a_Oprt is no operator code
+       */
+       int ParserBase::GetOprtPrecedence(const token_type& a_Tok) const
+       {
+               switch (a_Tok.GetCode())
+               {
+                       // built in operators
+               case cmEND:      return -5;
+               case cmARG_SEP:  return -4;
+               case cmASSIGN:   return -1;
+               case cmELSE:
+               case cmIF:       return  0;
+               case cmLAND:     return  prLAND;
+               case cmLOR:      return  prLOR;
+               case cmLT:
+               case cmGT:
+               case cmLE:
+               case cmGE:
+               case cmNEQ:
+               case cmEQ:       return  prCMP;
+               case cmADD:
+               case cmSUB:      return  prADD_SUB;
+               case cmMUL:
+               case cmDIV:      return  prMUL_DIV;
+               case cmPOW:      return  prPOW;
+
+               // user defined binary operators
+               case cmOPRT_INFIX:
+               case cmOPRT_BIN: return a_Tok.GetPri();
+               default:  
+                       throw exception_type(ecINTERNAL_ERROR, 5, _T(""));
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Get operator priority.
+               \throw ParserException if a_Oprt is no operator code
+       */
+       EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type& a_Tok) const
+       {
+               switch (a_Tok.GetCode())
+               {
+               case cmASSIGN:
+               case cmLAND:
+               case cmLOR:
+               case cmLT:
+               case cmGT:
+               case cmLE:
+               case cmGE:
+               case cmNEQ:
+               case cmEQ:
+               case cmADD:
+               case cmSUB:
+               case cmMUL:
+               case cmDIV:      return oaLEFT;
+               case cmPOW:      return oaRIGHT;
+               case cmOPRT_BIN: return a_Tok.GetAssociativity();
+               default:         return oaNONE;
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Return a map containing the used variables only. */
+       const varmap_type& ParserBase::GetUsedVar() const
+       {
+               try
+               {
+                       m_pTokenReader->IgnoreUndefVar(true);
+                       CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it
+                                                // may contain references to nonexisting variables.
+                       m_pParseFormula = &ParserBase::ParseString;
+                       m_pTokenReader->IgnoreUndefVar(false);
+               }
+               catch (exception_type& /*e*/)
+               {
+                       // Make sure to stay in string parse mode, don't call ReInit()
+                       // because it deletes the array with the used variables
+                       m_pParseFormula = &ParserBase::ParseString;
+                       m_pTokenReader->IgnoreUndefVar(false);
+                       throw;
+               }
+
+               return m_pTokenReader->GetUsedVar();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Return a map containing the used variables only. */
+       const varmap_type& ParserBase::GetVar() const
+       {
+               return m_VarDef;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Return a map containing all parser constants. */
+       const valmap_type& ParserBase::GetConst() const
+       {
+               return m_ConstDef;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Return prototypes of all parser functions.
+               \return #m_FunDef
+               \sa FunProt
+               \throw nothrow
+
+               The return type is a map of the public type #funmap_type containing the prototype
+               definitions for all numerical parser functions. String functions are not part of
+               this map. The Prototype definition is encapsulated in objects of the class FunProt
+               one per parser function each associated with function names via a map construct.
+       */
+       const funmap_type& ParserBase::GetFunDef() const
+       {
+               return m_FunDef;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Retrieve the formula. */
+       const string_type& ParserBase::GetExpr() const
+       {
+               return m_pTokenReader->GetExpr();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Execute a function that takes a single string argument.
+               \param a_FunTok Function token.
+               \throw exception_type If the function token is not a string function
+       */
+       ParserBase::token_type ParserBase::ApplyStrFunc(
+               const token_type& a_FunTok,
+               const std::vector<token_type>& a_vArg) const
+       {
+               if (a_vArg.back().GetCode() != cmSTRING)
+                       Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+
+               token_type  valTok;
+               generic_callable_type pFunc = a_FunTok.GetFuncAddr();
+               MUP_ASSERT(pFunc);
+
+               try
+               {
+                       // Check function arguments; write dummy value into valtok to represent the result
+                       switch (a_FunTok.GetArgCount())
+                       {
+                       case 0: valTok.SetVal(1); a_vArg[0].GetAsString();  break;
+                       case 1: valTok.SetVal(1); a_vArg[1].GetAsString();  a_vArg[0].GetVal();  break;
+                       case 2: valTok.SetVal(1); a_vArg[2].GetAsString();  a_vArg[1].GetVal();  a_vArg[0].GetVal();  break;
+                       case 3: valTok.SetVal(1); a_vArg[3].GetAsString();  a_vArg[2].GetVal();  a_vArg[1].GetVal();  a_vArg[0].GetVal();  break;
+                       case 4: valTok.SetVal(1); a_vArg[4].GetAsString();  a_vArg[3].GetVal();  a_vArg[2].GetVal();  a_vArg[1].GetVal();  a_vArg[0].GetVal();  break;
+                       case 5: valTok.SetVal(1); a_vArg[5].GetAsString();  a_vArg[4].GetVal();  a_vArg[3].GetVal();  a_vArg[2].GetVal();  a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;
+                       default: Error(ecINTERNAL_ERROR);
+                       }
+               }
+               catch (ParserError&)
+               {
+                       Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+               }
+
+               // string functions won't be optimized
+               m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
+
+               // Push dummy value representing the function result to the stack
+               return valTok;
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Apply a function token.
+               \param iArgCount Number of Arguments actually gathered used only for multiarg functions.
+               \post The result is pushed to the value stack
+               \post The function token is removed from the stack
+               \throw exception_type if Argument count does not match function requirements.
+       */
+       void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int a_iArgCount) const
+       {
+               MUP_ASSERT(m_pTokenReader.get());
+
+               // Operator stack empty or does not contain tokens with callback functions
+               if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
+                       return;
+
+               token_type funTok = a_stOpt.top();
+               a_stOpt.pop();
+               MUP_ASSERT(funTok.GetFuncAddr() != nullptr);
+
+               // Binary operators must rely on their internal operator number
+               // since counting of operators relies on commas for function arguments
+               // binary operators do not have commas in their expression
+               int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
+
+               // determine how many parameters the function needs. To remember iArgCount includes the 
+               // string parameter whilst GetArgCount() counts only numeric parameters.
+               int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0);
+
+               // That's the number of numerical parameters
+               int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0);
+
+               if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1)
+                       Error(ecINTERNAL_ERROR);
+
+               if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
+                       Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
+
+               if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired)
+                       Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
+
+               if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired)
+                       Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
+
+               // Collect the numeric function arguments from the value stack and store them
+               // in a vector
+               std::vector<token_type> stArg;
+               for (int i = 0; i < iArgNumerical; ++i)
+               {
+                       if (a_stVal.empty())
+                               Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+                       stArg.push_back(a_stVal.top());
+                       a_stVal.pop();
+
+                       if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
+                               Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+               }
+
+               switch (funTok.GetCode())
+               {
+               case  cmFUNC_STR:
+                       if (a_stVal.empty())
+                               Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+                       stArg.push_back(a_stVal.top());
+                       a_stVal.pop();
+
+                       if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
+                               Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+                       ApplyStrFunc(funTok, stArg);
+                       break;
+
+               case  cmFUNC_BULK:
+                       m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
+                       break;
+
+               case  cmOPRT_BIN:
+               case  cmOPRT_POSTFIX:
+               case  cmOPRT_INFIX:
+               case  cmFUNC:
+                       if (funTok.GetArgCount() == -1 && iArgCount == 0)
+                               Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+                       m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical, funTok.IsOptimizable());
+                       break;
+               default:
+                       break;
+               }
+
+               // Push dummy value representing the function result to the stack
+               token_type token;
+               token.SetVal(1);
+               a_stVal.push(token);
+       }
+
+       //---------------------------------------------------------------------------
+       void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
+       {
+               // Check if there is an if Else clause to be calculated
+               while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE)
+               {
+                       MUP_ASSERT(!a_stOpt.empty())
+                       token_type opElse = a_stOpt.top();
+                       a_stOpt.pop();
+
+                       // Take the value associated with the else branch from the value stack
+                       MUP_ASSERT(!a_stVal.empty());
+                       token_type vVal2 = a_stVal.top();
+                       if (vVal2.GetType() != tpDBL)
+                               Error(ecUNEXPECTED_STR, m_pTokenReader->GetPos());
+                       
+                       a_stVal.pop();
+
+                       // it then else is a ternary operator Pop all three values from the value s
+                       // tack and just return the right value
+                       MUP_ASSERT(!a_stVal.empty());
+                       token_type vVal1 = a_stVal.top();
+                       if (vVal1.GetType() != tpDBL)
+                               Error(ecUNEXPECTED_STR, m_pTokenReader->GetPos());
+
+                       a_stVal.pop();
+
+                       MUP_ASSERT(!a_stVal.empty());
+                       token_type vExpr = a_stVal.top();
+                       a_stVal.pop();
+
+                       a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
+
+                       token_type opIf = a_stOpt.top();
+                       a_stOpt.pop();
+
+                       MUP_ASSERT(opElse.GetCode() == cmELSE);
+
+                       if (opIf.GetCode() != cmIF)
+                               Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
+
+                       m_vRPN.AddIfElse(cmENDIF);
+               } // while pending if-else-clause found
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Performs the necessary steps to write code for
+                          the execution of binary operators into the bytecode.
+       */
+       void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
+       {
+               // is it a user defined binary operator?
+               if (a_stOpt.top().GetCode() == cmOPRT_BIN)
+               {
+                       ApplyFunc(a_stOpt, a_stVal, 2);
+               }
+               else
+               {
+                       if (a_stVal.size() < 2)
+                               Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), _T("ApplyBinOprt: not enough values in value stack!"));
+
+                       token_type valTok1 = a_stVal.top();
+                       a_stVal.pop();
+
+                       token_type valTok2 = a_stVal.top();
+                       a_stVal.pop();
+
+                       token_type optTok = a_stOpt.top();
+                       a_stOpt.pop();
+
+                       token_type resTok;
+
+                       if (valTok1.GetType() != valTok2.GetType() ||
+                               (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR))
+                               Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
+
+                       if (optTok.GetCode() == cmASSIGN)
+                       {
+                               if (valTok2.GetCode() != cmVAR)
+                                       Error(ecUNEXPECTED_OPERATOR, -1, _T("="));
+
+                               m_vRPN.AddAssignOp(valTok2.GetVar());
+                       }
+                       else
+                               m_vRPN.AddOp(optTok.GetCode());
+
+                       resTok.SetVal(1);
+                       a_stVal.push(resTok);
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Apply a binary operator.
+               \param a_stOpt The operator stack
+               \param a_stVal The value stack
+       */
+       void ParserBase::ApplyRemainingOprt(std::stack<token_type>& stOpt, std::stack<token_type>& stVal) const
+       {
+               while (stOpt.size() &&
+                       stOpt.top().GetCode() != cmBO &&
+                       stOpt.top().GetCode() != cmIF)
+               {
+                       token_type tok = stOpt.top();
+                       switch (tok.GetCode())
+                       {
+                       case cmOPRT_INFIX:
+                       case cmOPRT_BIN:
+                       case cmLE:
+                       case cmGE:
+                       case cmNEQ:
+                       case cmEQ:
+                       case cmLT:
+                       case cmGT:
+                       case cmADD:
+                       case cmSUB:
+                       case cmMUL:
+                       case cmDIV:
+                       case cmPOW:
+                       case cmLAND:
+                       case cmLOR:
+                       case cmASSIGN:
+                               if (stOpt.top().GetCode() == cmOPRT_INFIX)
+                                       ApplyFunc(stOpt, stVal, 1);
+                               else
+                                       ApplyBinOprt(stOpt, stVal);
+                               break;
+
+                       case cmELSE:
+                               ApplyIfElse(stOpt, stVal);
+                               break;
+
+                       default:
+                               Error(ecINTERNAL_ERROR);
+                       }
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Parse the command code.
+               \sa ParseString(...)
+
+               Command code contains precalculated stack positions of the values and the
+               associated operators. The Stack is filled beginning from index one the
+               value at index zero is not used at all.
+       */
+       value_type ParserBase::ParseCmdCode() const
+       {
+               return ParseCmdCodeBulk(0, 0);
+       }
+
+       value_type ParserBase::ParseCmdCodeShort() const
+       {
+               const SToken *const tok = m_vRPN.GetBase();
+               value_type buf;
+
+               switch (tok->Cmd)
+               {
+               case cmVAL:             
+                       return tok->Val.data2;
+
+               case cmVAR:             
+                       return *tok->Val.ptr;
+
+               case cmVARMUL:  
+                       return *tok->Val.ptr * tok->Val.data + tok->Val.data2;
+
+               case cmVARPOW2: 
+                       buf = *(tok->Val.ptr);
+                       return buf * buf;
+
+               case  cmVARPOW3:                                
+                       buf = *(tok->Val.ptr);
+                       return buf * buf * buf;
+
+               case  cmVARPOW4:                                
+                       buf = *(tok->Val.ptr);
+                       return buf * buf * buf * buf;
+
+               // numerical function without any argument
+               case cmFUNC:
+                       return tok->Fun.cb.call_fun<0>();
+
+               // String function without a numerical argument
+               case cmFUNC_STR:
+                       return tok->Fun.cb.call_strfun<1>(m_vStringBuf[0].c_str());
+
+               default:
+                       throw ParserError(ecINTERNAL_ERROR);
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Evaluate the RPN.
+               \param nOffset The offset added to variable addresses (for bulk mode)
+               \param nThreadID OpenMP Thread id of the calling thread
+       */
+       value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const
+       {
+               assert(nThreadID <= s_MaxNumOpenMPThreads);
+
+               // Note: The check for nOffset==0 and nThreadID here is not necessary but 
+               //       brings a minor performance gain when not in bulk mode.
+               value_type *stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
+               value_type buf;
+               int sidx(0);
+               for (const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok)
+               {
+                       switch (pTok->Cmd)
+                       {
+                       // built in binary operators
+                       case  cmLE:   --sidx; stack[sidx] = stack[sidx] <= stack[sidx + 1]; continue;
+                       case  cmGE:   --sidx; stack[sidx] = stack[sidx] >= stack[sidx + 1]; continue;
+                       case  cmNEQ:  --sidx; stack[sidx] = stack[sidx] != stack[sidx + 1]; continue;
+                       case  cmEQ:   --sidx; stack[sidx] = stack[sidx] == stack[sidx + 1]; continue;
+                       case  cmLT:   --sidx; stack[sidx] = stack[sidx] < stack[sidx + 1];  continue;
+                       case  cmGT:   --sidx; stack[sidx] = stack[sidx] > stack[sidx + 1];  continue;
+                       case  cmADD:  --sidx; stack[sidx] += stack[1 + sidx]; continue;
+                       case  cmSUB:  --sidx; stack[sidx] -= stack[1 + sidx]; continue;
+                       case  cmMUL:  --sidx; stack[sidx] *= stack[1 + sidx]; continue;
+                       case  cmDIV:  --sidx;
+                               stack[sidx] /= stack[1 + sidx];
+                               continue;
+
+                       case  cmPOW:
+                               --sidx; stack[sidx] = MathImpl<value_type>::Pow(stack[sidx], stack[1 + sidx]);
+                               continue;
+
+                       case  cmLAND: --sidx; stack[sidx] = stack[sidx] && stack[sidx + 1]; continue;
+                       case  cmLOR:  --sidx; stack[sidx] = stack[sidx] || stack[sidx + 1]; continue;
+
+                       case  cmASSIGN:
+                               // Bugfix for Bulkmode:
+                               // for details see:
+                               //    https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws
+                               --sidx; 
+                               stack[sidx] = *(pTok->Oprt.ptr + nOffset) = stack[sidx + 1]; 
+                               continue;
+                               // original code:
+                               //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue;
+
+                       case  cmIF:
+                               if (stack[sidx--] == 0)
+                               {
+                                       MUP_ASSERT(sidx >= 0);
+                                       pTok += pTok->Oprt.offset;
+                               }
+                               continue;
+
+                       case  cmELSE:
+                               pTok += pTok->Oprt.offset;
+                               continue;
+
+                       case  cmENDIF:
+                               continue;
+
+                               // value and variable tokens
+                       case  cmVAR:    stack[++sidx] = *(pTok->Val.ptr + nOffset);  continue;
+                       case  cmVAL:    stack[++sidx] = pTok->Val.data2;  continue;
+
+                       case  cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
+                               stack[++sidx] = buf * buf;
+                               continue;
+
+                       case  cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
+                               stack[++sidx] = buf * buf * buf;
+                               continue;
+
+                       case  cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
+                               stack[++sidx] = buf * buf * buf * buf;
+                               continue;
+
+                       case  cmVARMUL:  
+                               stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
+                               continue;
+
+                               // Next is treatment of numeric functions
+                       case  cmFUNC:
+                       {
+                               int iArgCount = pTok->Fun.argc;
+
+                               // switch according to argument count
+                               switch (iArgCount)
+                               {
+                               case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_fun<0 >(); continue;
+                               case 1:            stack[sidx] = pTok->Fun.cb.call_fun<1 >(stack[sidx]);   continue;
+                               case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_fun<2 >(stack[sidx], stack[sidx + 1]); continue;
+                               case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_fun<3 >(stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue;
+                               case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_fun<4 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue;
+                               case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_fun<5 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue;
+                               case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_fun<6 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]); continue;
+                               case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_fun<7 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]); continue;
+                               case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_fun<8 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7]); continue;
+                               case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_fun<9 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8]); continue;
+                               case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_fun<10>(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8], stack[sidx + 9]); continue;
+                               default:
+                                       // function with variable arguments store the number as a negative value
+                                       if (iArgCount > 0)
+                                               Error(ecINTERNAL_ERROR, -1);
+
+                                       sidx -= -iArgCount - 1;
+
+                                       // <ibg 2020-06-08> From oss-fuzz. Happend when Multiarg functions and if-then-else are used incorrectly.
+                                       // Expressions where this was observed:
+                                       //              sum(0?1,2,3,4,5:6)                      -> fixed
+                                       //              avg(0>3?4:(""),0^3?4:(""))
+                                       //
+                                       // The final result normally lieas at position 1. If sixd is smaller there is something wrong.
+                                       if (sidx <= 0)
+                                               Error(ecINTERNAL_ERROR, -1);
+                                       // </ibg>
+
+                                       stack[sidx] = pTok->Fun.cb.call_multfun(&stack[sidx], -iArgCount);
+                                       continue;
+                               }
+                       }
+
+                       // Next is treatment of string functions
+                       case  cmFUNC_STR:
+                       {
+                               sidx -= pTok->Fun.argc - 1;
+
+                               // The index of the string argument in the string table
+                               int iIdxStack = pTok->Fun.idx;
+                               if (iIdxStack < 0 || iIdxStack >= (int)m_vStringBuf.size())
+                                       Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos());
+
+                               switch (pTok->Fun.argc)  // switch according to argument count
+                               {
+                               case 0: stack[sidx] = pTok->Fun.cb.call_strfun<1>(m_vStringBuf[iIdxStack].c_str()); continue;
+                               case 1: stack[sidx] = pTok->Fun.cb.call_strfun<2>(m_vStringBuf[iIdxStack].c_str(), stack[sidx]); continue;
+                               case 2: stack[sidx] = pTok->Fun.cb.call_strfun<3>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1]); continue;
+                               case 3: stack[sidx] = pTok->Fun.cb.call_strfun<4>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue;
+                               case 4: stack[sidx] = pTok->Fun.cb.call_strfun<5>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue;
+                               case 5: stack[sidx] = pTok->Fun.cb.call_strfun<6>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue;
+                               }
+
+                               continue;
+                       }
+
+                       case  cmFUNC_BULK:
+                       {
+                               int iArgCount = pTok->Fun.argc;
+
+                               // switch according to argument count
+                               switch (iArgCount)
+                               {
+                               case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<0 >(nOffset, nThreadID); continue;
+                               case 1:            stack[sidx] = pTok->Fun.cb.call_bulkfun<1 >(nOffset, nThreadID, stack[sidx]); continue;
+                               case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<2 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1]); continue;
+                               case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_bulkfun<3 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue;
+                               case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_bulkfun<4 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue;
+                               case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_bulkfun<5 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue;
+                               case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_bulkfun<6 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]); continue;
+                               case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_bulkfun<7 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]); continue;
+                               case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_bulkfun<8 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7]); continue;
+                               case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_bulkfun<9 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8]); continue;
+                               case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_bulkfun<10>(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8], stack[sidx + 9]); continue;
+                               default:
+                                       throw exception_type(ecINTERNAL_ERROR, 2, _T(""));
+                               }
+                       }
+
+                       default:
+                               throw exception_type(ecINTERNAL_ERROR, 3, _T(""));
+                       } // switch CmdCode
+               } // for all bytecode tokens
+
+               return stack[m_nFinalResultIdx];
+       }
+
+       //---------------------------------------------------------------------------
+       void ParserBase::CreateRPN() const
+       {
+               if (!m_pTokenReader->GetExpr().length())
+                       Error(ecUNEXPECTED_EOF, 0);
+
+               std::stack<token_type> stOpt, stVal;
+               std::stack<int> stArgCount;
+               token_type opta, opt;  // for storing operators
+               token_type val, tval;  // for storing value
+               int ifElseCounter = 0;
+
+               ReInit();
+
+               // The outermost counter counts the number of separated items
+               // such as in "a=10,b=20,c=c+a"
+               stArgCount.push(1);
+
+               for (;;)
+               {
+                       opt = m_pTokenReader->ReadNextToken();
+
+                       switch (opt.GetCode())
+                       {
+                       //
+                       // Next three are different kind of value entries
+                       //
+                       case cmSTRING:
+                               if (stOpt.empty())
+                                       Error(ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
+
+                               opt.SetIdx((int)m_vStringBuf.size());      // Assign buffer index to token 
+                               stVal.push(opt);
+                               m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
+                               break;
+
+                       case cmVAR:
+                               stVal.push(opt);
+                               m_vRPN.AddVar(static_cast<value_type*>(opt.GetVar()));
+                               break;
+
+                       case cmVAL:
+                               stVal.push(opt);
+                               m_vRPN.AddVal(opt.GetVal());
+                               break;
+
+                       case cmELSE:
+                               if (stArgCount.empty())
+                                       Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
+
+                               if (stArgCount.top() > 1)
+                                       Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
+
+                               stArgCount.pop();
+
+                               ifElseCounter--;
+                               if (ifElseCounter < 0)
+                                       Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
+
+                               ApplyRemainingOprt(stOpt, stVal);
+                               m_vRPN.AddIfElse(cmELSE);
+                               stOpt.push(opt);
+                               break;
+
+                       case cmARG_SEP:
+                               if (!stOpt.empty() && stOpt.top().GetCode() == cmIF)
+                                       Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
+
+                               if (stArgCount.empty())
+                                       Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
+
+                               ++stArgCount.top();
+                               // Falls through.
+                               // intentional (no break!)
+
+                       case cmEND:
+                               ApplyRemainingOprt(stOpt, stVal);
+                               break;
+
+                       case cmBC:
+                       {
+                               // The argument count for parameterless functions is zero
+                               // by default an opening bracket sets parameter count to 1
+                               // in preparation of arguments to come. If the last token
+                               // was an opening bracket we know better...
+                               if (opta.GetCode() == cmBO)
+                                       --stArgCount.top();
+
+                               ApplyRemainingOprt(stOpt, stVal);
+
+                               // Check if the bracket content has been evaluated completely
+                               if (stOpt.size() && stOpt.top().GetCode() == cmBO)
+                               {
+                                       // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
+                                       // if there is either a function or a sign pending
+                                       // neither the opening nor the closing bracket will be pushed back to
+                                       // the operator stack
+                                       // Check if a function is standing in front of the opening bracket, 
+                                       // if yes evaluate it afterwards check for infix operators
+                                       MUP_ASSERT(stArgCount.size());
+                                       int iArgCount = stArgCount.top();
+                                       stArgCount.pop();
+
+                                       stOpt.pop(); // Take opening bracket from stack
+
+                                       if (iArgCount > 1 && (stOpt.size() == 0 ||
+                                               (stOpt.top().GetCode() != cmFUNC &&
+                                                       stOpt.top().GetCode() != cmFUNC_BULK &&
+                                                       stOpt.top().GetCode() != cmFUNC_STR)))
+                                               Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
+
+                                       // The opening bracket was popped from the stack now check if there
+                                       // was a function before this bracket
+                                       if (stOpt.size() &&
+                                               stOpt.top().GetCode() != cmOPRT_INFIX &&
+                                               stOpt.top().GetCode() != cmOPRT_BIN &&
+                                               stOpt.top().GetFuncAddr() != 0)
+                                       {
+                                               ApplyFunc(stOpt, stVal, iArgCount);
+                                       }
+                               }
+                       } // if bracket content is evaluated
+                       break;
+
+                       //
+                       // Next are the binary operator entries
+                       //
+                       case cmIF:
+                               ifElseCounter++;
+                               stArgCount.push(1);
+                               // Falls through.
+                               // intentional (no break!)
+
+                       case cmLAND:
+                       case cmLOR:
+                       case cmLT:
+                       case cmGT:
+                       case cmLE:
+                       case cmGE:
+                       case cmNEQ:
+                       case cmEQ:
+                       case cmADD:
+                       case cmSUB:
+                       case cmMUL:
+                       case cmDIV:
+                       case cmPOW:
+                       case cmASSIGN:
+                       case cmOPRT_BIN:
+
+                               // A binary operator (user defined or built in) has been found. 
+                               while (
+                                       stOpt.size() &&
+                                       stOpt.top().GetCode() != cmBO &&
+                                       stOpt.top().GetCode() != cmELSE &&
+                                       stOpt.top().GetCode() != cmIF)
+                               {
+                                       int nPrec1 = GetOprtPrecedence(stOpt.top()),
+                                               nPrec2 = GetOprtPrecedence(opt);
+
+                                       if (stOpt.top().GetCode() == opt.GetCode())
+                                       {
+
+                                               // Deal with operator associativity
+                                               EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);
+                                               if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
+                                                       (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
+                                               {
+                                                       break;
+                                               }
+                                       }
+                                       else if (nPrec1 < nPrec2)
+                                       {
+                                               // In case the operators are not equal the precedence decides alone...
+                                               break;
+                                       }
+
+                                       if (stOpt.top().GetCode() == cmOPRT_INFIX)
+                                               ApplyFunc(stOpt, stVal, 1);
+                                       else
+                                               ApplyBinOprt(stOpt, stVal);
+                               } // while ( ... )
+
+                               if (opt.GetCode() == cmIF)
+                                       m_vRPN.AddIfElse(opt.GetCode());
+
+                               // The operator can't be evaluated right now, push back to the operator stack
+                               stOpt.push(opt);
+                               break;
+
+                               //
+                               // Last section contains functions and operators implicitly mapped to functions
+                               //
+                       case cmBO:
+                               stArgCount.push(1);
+                               stOpt.push(opt);
+                               break;
+
+                       case cmOPRT_INFIX:
+                       case cmFUNC:
+                       case cmFUNC_BULK:
+                       case cmFUNC_STR:
+                               stOpt.push(opt);
+                               break;
+
+                       case cmOPRT_POSTFIX:
+                               stOpt.push(opt);
+                               ApplyFunc(stOpt, stVal, 1);  // this is the postfix operator
+                               break;
+
+                       default:  Error(ecINTERNAL_ERROR, 3);
+                       } // end of switch operator-token
+
+                       opta = opt;
+
+                       if (opt.GetCode() == cmEND)
+                       {
+                               m_vRPN.Finalize();
+                               break;
+                       }
+
+                       if (ParserBase::g_DbgDumpStack)
+                       {
+                               StackDump(stVal, stOpt);
+                               m_vRPN.AsciiDump();
+                       }
+
+//                     if (ParserBase::g_DbgDumpCmdCode)
+                               //m_vRPN.AsciiDump();
+               } // while (true)
+
+               if (ParserBase::g_DbgDumpCmdCode)
+                       m_vRPN.AsciiDump();
+
+               if (ifElseCounter > 0)
+                       Error(ecMISSING_ELSE_CLAUSE);
+
+               // get the last value (= final result) from the stack
+               MUP_ASSERT(stArgCount.size() == 1);
+               m_nFinalResultIdx = stArgCount.top();
+               if (m_nFinalResultIdx == 0)
+                       Error(ecINTERNAL_ERROR, 9);
+
+               if (stVal.size() == 0)
+                       Error(ecEMPTY_EXPRESSION);
+
+               // 2020-09-17; fix for https://oss-fuzz.com/testcase-detail/5758791700971520
+               // I don't need the value stack any more. Destructively check if all values in the value 
+               // stack represent floating point values
+               while (stVal.size())
+               {
+                       if (stVal.top().GetType() != tpDBL)
+                               Error(ecSTR_RESULT);
+
+                       stVal.pop();
+               }
+
+               m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief One of the two main parse functions.
+               \sa ParseCmdCode(...)
+
+         Parse expression from input string. Perform syntax checking and create
+         bytecode. After parsing the string and creating the bytecode the function
+         pointer #m_pParseFormula will be changed to the second parse routine the
+         uses bytecode instead of string parsing.
+       */
+       value_type ParserBase::ParseString() const
+       {
+               try
+               {
+                       CreateRPN();
+
+                       if (m_vRPN.GetSize() == 2)
+                       {
+                               m_pParseFormula = &ParserBase::ParseCmdCodeShort;
+                               m_vStackBuffer[1] = (this->*m_pParseFormula)();
+                               return m_vStackBuffer[1];
+                       }
+                       else
+                       {
+                               m_pParseFormula = &ParserBase::ParseCmdCode;
+                               return (this->*m_pParseFormula)();
+                       }
+               }
+               catch (ParserError& exc)
+               {
+                       exc.SetFormula(m_pTokenReader->GetExpr());
+                       throw;
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Create an error containing the parse error position.
+
+         This function will create an Parser Exception object containing the error text and
+         its position.
+
+         \param a_iErrc [in] The error code of type #EErrorCodes.
+         \param a_iPos [in] The position where the error was detected.
+         \param a_strTok [in] The token string representation associated with the error.
+         \throw ParserException always throws that's the only purpose of this function.
+       */
+       void  ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const
+       {
+               throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear all user defined variables.
+               \throw nothrow
+
+               Resets the parser to string parsing mode by calling #ReInit.
+       */
+       void ParserBase::ClearVar()
+       {
+               m_VarDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Remove a variable from internal storage.
+               \throw nothrow
+
+               Removes a variable if it exists. If the Variable does not exist nothing will be done.
+       */
+       void ParserBase::RemoveVar(const string_type& a_strVarName)
+       {
+               varmap_type::iterator item = m_VarDef.find(a_strVarName);
+               if (item != m_VarDef.end())
+               {
+                       m_VarDef.erase(item);
+                       ReInit();
+               }
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear all functions.
+               \post Resets the parser to string parsing mode.
+               \throw nothrow
+       */
+       void ParserBase::ClearFun()
+       {
+               m_FunDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear all user defined constants.
+
+               Both numeric and string constants will be removed from the internal storage.
+               \post Resets the parser to string parsing mode.
+               \throw nothrow
+       */
+       void ParserBase::ClearConst()
+       {
+               m_ConstDef.clear();
+               m_StrVarDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear all user defined postfix operators.
+               \post Resets the parser to string parsing mode.
+               \throw nothrow
+       */
+       void ParserBase::ClearPostfixOprt()
+       {
+               m_PostOprtDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear all user defined binary operators.
+               \post Resets the parser to string parsing mode.
+               \throw nothrow
+       */
+       void ParserBase::ClearOprt()
+       {
+               m_OprtDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Clear the user defined Prefix operators.
+               \post Resets the parser to string parser mode.
+               \throw nothrow
+       */
+       void ParserBase::ClearInfixOprt()
+       {
+               m_InfixOprtDef.clear();
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Enable or disable the formula optimization feature.
+               \post Resets the parser to string parser mode.
+               \throw nothrow
+       */
+       void ParserBase::EnableOptimizer(bool a_bIsOn)
+       {
+               m_vRPN.EnableOptimizer(a_bIsOn);
+               ReInit();
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Enable the dumping of bytecode and stack content on the console.
+               \param bDumpCmd Flag to enable dumping of the current bytecode to the console.
+               \param bDumpStack Flag to enable dumping of the stack content is written to the console.
+
+          This function is for debug purposes only!
+       */
+       void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)
+       {
+               ParserBase::g_DbgDumpCmdCode = bDumpCmd;
+               ParserBase::g_DbgDumpStack = bDumpStack;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Enable or disable the built in binary operators.
+               \throw nothrow
+               \sa m_bBuiltInOp, ReInit()
+
+         If you disable the built in binary operators there will be no binary operators
+         defined. Thus you must add them manually one by one. It is not possible to
+         disable built in operators selectively. This function will Reinitialize the
+         parser by calling ReInit().
+       */
+       void ParserBase::EnableBuiltInOprt(bool a_bIsOn)
+       {
+               m_bBuiltInOp = a_bIsOn;
+               ReInit();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Query status of built in variables.
+               \return #m_bBuiltInOp; true if built in operators are enabled.
+               \throw nothrow
+       */
+       bool ParserBase::HasBuiltInOprt() const
+       {
+               return m_bBuiltInOp;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Get the argument separator character.
+       */
+       char_type ParserBase::GetArgSep() const
+       {
+               return m_pTokenReader->GetArgSep();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Set argument separator.
+               \param cArgSep the argument separator character.
+       */
+       void ParserBase::SetArgSep(char_type cArgSep)
+       {
+               m_pTokenReader->SetArgSep(cArgSep);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Dump stack content.
+
+               This function is used for debugging only.
+       */
+       void ParserBase::StackDump(const std::stack<token_type>& a_stVal, const std::stack<token_type>& a_stOprt) const
+       {
+               std::stack<token_type> stOprt(a_stOprt);
+               std::stack<token_type> stVal(a_stVal);
+
+               mu::console() << _T("\nValue stack:\n");
+               while (!stVal.empty())
+               {
+                       token_type val = stVal.top();
+                       stVal.pop();
+
+                       if (val.GetType() == tpSTR)
+                               mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");
+                       else
+                               mu::console() << _T(" ") << val.GetVal() << _T(" ");
+               }
+               mu::console() << "\nOperator stack:\n";
+
+               while (!stOprt.empty())
+               {
+                       if (stOprt.top().GetCode() <= cmASSIGN)
+                       {
+                               mu::console() << _T("OPRT_INTRNL \"")
+                                       << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
+                                       << _T("\" \n");
+                       }
+                       else
+                       {
+                               switch (stOprt.top().GetCode())
+                               {
+                               case cmVAR:   mu::console() << _T("VAR\n");  break;
+                               case cmVAL:   mu::console() << _T("VAL\n");  break;
+                               case cmFUNC:
+                                       mu::console()
+                                               << _T("FUNC \"")
+                                               << stOprt.top().GetAsString()
+                                               << _T("\"\n");
+                                       break;
+
+                               case cmFUNC_BULK:
+                                       mu::console()
+                                               << _T("FUNC_BULK \"")
+                                               << stOprt.top().GetAsString()
+                                               << _T("\"\n");
+                                       break;
+
+                               case cmOPRT_INFIX:
+                                       mu::console() << _T("OPRT_INFIX \"")
+                                               << stOprt.top().GetAsString()
+                                               << _T("\"\n");
+                                       break;
+
+                               case cmOPRT_BIN:
+                                       mu::console() << _T("OPRT_BIN \"")
+                                               << stOprt.top().GetAsString()
+                                               << _T("\"\n");
+                                       break;
+
+                               case cmFUNC_STR: mu::console() << _T("FUNC_STR\n");       break;
+                               case cmEND:      mu::console() << _T("END\n");            break;
+                               case cmUNKNOWN:  mu::console() << _T("UNKNOWN\n");        break;
+                               case cmBO:       mu::console() << _T("BRACKET \"(\"\n");  break;
+                               case cmBC:       mu::console() << _T("BRACKET \")\"\n");  break;
+                               case cmIF:       mu::console() << _T("IF\n");  break;
+                               case cmELSE:     mu::console() << _T("ELSE\n");  break;
+                               case cmENDIF:    mu::console() << _T("ENDIF\n");  break;
+                               default:         mu::console() << stOprt.top().GetCode() << _T(" ");  break;
+                               }
+                       }
+                       stOprt.pop();
+               }
+
+               mu::console() << dec << endl;
+       }
+
+       /** \brief Calculate the result.
+
+         A note on const correctness:
+         I consider it important that Calc is a const function.
+         Due to caching operations Calc changes only the state of internal variables with one exception
+         m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
+         Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update.
+
+         \pre A formula must be set.
+         \pre Variables must have been set (if needed)
+
+         \sa #m_pParseFormula
+         \return The evaluation result
+         \throw ParseException if no Formula is set or in case of any other error related to the formula.
+       */
+       value_type ParserBase::Eval() const
+       {
+               return (this->*m_pParseFormula)();
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Evaluate an expression containing comma separated subexpressions
+               \param [out] nStackSize The total number of results available
+               \return Pointer to the array containing all expression results
+
+               This member function can be used to retrieve all results of an expression
+               made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)")
+       */
+       value_type* ParserBase::Eval(int& nStackSize) const
+       {
+               if (m_vRPN.GetSize() > 0)
+               {
+                       ParseCmdCode();
+               }
+               else
+               {
+                       ParseString();
+               }
+
+               nStackSize = m_nFinalResultIdx;
+
+               // (for historic reasons the stack starts at position 1)
+               return &m_vStackBuffer[1];
+       }
+
+       //---------------------------------------------------------------------------
+       /** \brief Return the number of results on the calculation stack.
+
+         If the expression contains comma separated subexpressions (i.e. "sin(y), x+y").
+         There may be more than one return value. This function returns the number of
+         available results.
+       */
+       int ParserBase::GetNumResults() const
+       {
+               return m_nFinalResultIdx;
+       }
+
+       //---------------------------------------------------------------------------
+       void ParserBase::Eval(value_type* results, int nBulkSize)
+       {
+               CreateRPN();
+
+               int i = 0;
+
+#ifdef MUP_USE_OPENMP
+               //#define DEBUG_OMP_STUFF
+#ifdef DEBUG_OMP_STUFF
+               int* pThread = new int[nBulkSize];
+               int* pIdx = new int[nBulkSize];
+#endif
+
+               int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
+               int nThreadID = 0;
+
+#ifdef DEBUG_OMP_STUFF
+               int ct = 0;
+#endif
+               omp_set_num_threads(nMaxThreads);
+
+#pragma omp parallel for schedule(static, std::max(nBulkSize/nMaxThreads, 1)) private(nThreadID)
+               for (i = 0; i < nBulkSize; ++i)
+               {
+                       nThreadID = omp_get_thread_num();
+                       results[i] = ParseCmdCodeBulk(i, nThreadID);
+
+#ifdef DEBUG_OMP_STUFF
+#pragma omp critical
+                       {
+                               pThread[ct] = nThreadID;
+                               pIdx[ct] = i;
+                               ct++;
+                       }
+#endif
+               }
+
+#ifdef DEBUG_OMP_STUFF
+               FILE* pFile = fopen("bulk_dbg.txt", "w");
+               for (i = 0; i < nBulkSize; ++i)
+               {
+                       fprintf(pFile, "idx: %d  thread: %d \n", pIdx[i], pThread[i]);
+               }
+
+               delete[] pIdx;
+               delete[] pThread;
+
+               fclose(pFile);
+#endif
+
+#else
+               for (i = 0; i < nBulkSize; ++i)
+               {
+                       results[i] = ParseCmdCodeBulk(i, 0);
+               }
+#endif
+
+       }
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
+
diff --git a/bundled/muparser_v2_3_3/src/muParserBytecode.cpp b/bundled/muparser_v2_3_3/src/muParserBytecode.cpp
new file mode 100644 (file)
index 0000000..54427b9
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserBytecode.h"
+
+#include <algorithm>
+#include <string>
+#include <stack>
+#include <vector>
+#include <iostream>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+#include "muParserTemplateMagic.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+
+namespace mu
+{
+       /** \brief Bytecode default constructor. */
+       ParserByteCode::ParserByteCode()
+               :m_iStackPos(0)
+               , m_iMaxStackSize(0)
+               , m_vRPN()
+               , m_bEnableOptimizer(true)
+       {
+               m_vRPN.reserve(50);
+       }
+
+
+       /** \brief Copy constructor.
+
+               Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+       */
+       ParserByteCode::ParserByteCode(const ParserByteCode& a_ByteCode)
+       {
+               Assign(a_ByteCode);
+       }
+
+
+       /** \brief Assignment operator.
+
+               Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+       */
+       ParserByteCode& ParserByteCode::operator=(const ParserByteCode& a_ByteCode)
+       {
+               Assign(a_ByteCode);
+               return *this;
+       }
+
+
+       void ParserByteCode::EnableOptimizer(bool bStat)
+       {
+               m_bEnableOptimizer = bStat;
+       }
+
+
+       /** \brief Copy state of another object to this.
+
+               \throw nowthrow
+       */
+       void ParserByteCode::Assign(const ParserByteCode& a_ByteCode)
+       {
+               if (this == &a_ByteCode)
+                       return;
+
+               m_iStackPos = a_ByteCode.m_iStackPos;
+               m_vRPN = a_ByteCode.m_vRPN;
+               m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
+               m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
+       }
+
+
+       /** \brief Add a Variable pointer to bytecode.
+               \param a_pVar Pointer to be added.
+               \throw nothrow
+       */
+       void ParserByteCode::AddVar(value_type* a_pVar)
+       {
+               ++m_iStackPos;
+               m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+               // optimization does not apply
+               SToken tok;
+               tok.Cmd = cmVAR;
+               tok.Val.ptr = a_pVar;
+               tok.Val.data = 1;
+               tok.Val.data2 = 0;
+               m_vRPN.push_back(tok);
+       }
+
+
+       /** \brief Add a Variable pointer to bytecode.
+
+               Value entries in byte code consist of:
+               <ul>
+                 <li>value array position of the value</li>
+                 <li>the operator code according to ParserToken::cmVAL</li>
+                 <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
+               </ul>
+
+               \param a_pVal Value to be added.
+               \throw nothrow
+       */
+       void ParserByteCode::AddVal(value_type a_fVal)
+       {
+               ++m_iStackPos;
+               m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+               // If optimization does not apply
+               SToken tok;
+               tok.Cmd = cmVAL;
+               tok.Val.ptr = nullptr;
+               tok.Val.data = 0;
+               tok.Val.data2 = a_fVal;
+               m_vRPN.push_back(tok);
+       }
+
+
+       void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)
+       {
+               std::size_t sz = m_vRPN.size();
+               value_type& x = m_vRPN[sz - 2].Val.data2;
+               value_type& y = m_vRPN[sz - 1].Val.data2;
+
+               switch (a_Oprt)
+               {
+               case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;
+               case cmLOR:  x = (int)x || (int)y; m_vRPN.pop_back(); break;
+               case cmLT:   x = x < y;  m_vRPN.pop_back();  break;
+               case cmGT:   x = x > y;  m_vRPN.pop_back();  break;
+               case cmLE:   x = x <= y; m_vRPN.pop_back();  break;
+               case cmGE:   x = x >= y; m_vRPN.pop_back();  break;
+               case cmNEQ:  x = x != y; m_vRPN.pop_back();  break;
+               case cmEQ:   x = x == y; m_vRPN.pop_back();  break;
+               case cmADD:  x = x + y;  m_vRPN.pop_back();  break;
+               case cmSUB:  x = x - y;  m_vRPN.pop_back();  break;
+               case cmMUL:  x = x * y;  m_vRPN.pop_back();  break;
+               case cmDIV:
+                       x = x / y;
+                       m_vRPN.pop_back();
+                       break;
+
+               case cmPOW: x = MathImpl<value_type>::Pow(x, y);
+                       m_vRPN.pop_back();
+                       break;
+
+               default:
+                       break;
+               } // switch opcode
+       }
+
+
+       /** \brief Add an operator identifier to bytecode.
+
+               Operator entries in byte code consist of:
+               <ul>
+                 <li>value array position of the result</li>
+                 <li>the operator code according to ParserToken::ECmdCode</li>
+               </ul>
+
+               \sa  ParserToken::ECmdCode
+       */
+       void ParserByteCode::AddOp(ECmdCode a_Oprt)
+       {
+               bool bOptimized = false;
+
+               if (m_bEnableOptimizer)
+               {
+                       std::size_t sz = m_vRPN.size();
+
+                       // Check for foldable constants like:
+                       //   cmVAL cmVAL cmADD 
+                       // where cmADD can stand fopr any binary operator applied to
+                       // two constant values.
+                       if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL)
+                       {
+                               ConstantFolding(a_Oprt);
+                               bOptimized = true;
+                       }
+                       else
+                       {
+                               switch (a_Oprt)
+                               {
+                               case  cmPOW:
+                                       // Optimization for polynomials of low order
+                                       if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL)
+                                       {
+                                               if (m_vRPN[sz - 1].Val.data2 == 0)
+                                               {
+                                                       m_vRPN[sz - 2].Cmd = cmVAL;
+                                                       m_vRPN[sz - 2].Val.ptr = nullptr;
+                                                       m_vRPN[sz - 2].Val.data = 0;
+                                                       m_vRPN[sz - 2].Val.data2 = 1;
+                                               }
+                                               else if (m_vRPN[sz - 1].Val.data2 == 1)
+                                                       m_vRPN[sz - 2].Cmd = cmVAR;
+                                               else if (m_vRPN[sz - 1].Val.data2 == 2)
+                                                       m_vRPN[sz - 2].Cmd = cmVARPOW2;
+                                               else if (m_vRPN[sz - 1].Val.data2 == 3)
+                                                       m_vRPN[sz - 2].Cmd = cmVARPOW3;
+                                               else if (m_vRPN[sz - 1].Val.data2 == 4)
+                                                       m_vRPN[sz - 2].Cmd = cmVARPOW4;
+                                               else
+                                                       break;
+
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       break;
+
+                               case  cmSUB:
+                               case  cmADD:
+                                       // Simple optimization based on pattern recognition for a shitload of different
+                                       // bytecode combinations of addition/subtraction
+                                       if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr))
+                                       {
+                                               MUP_ASSERT(
+                                                       (m_vRPN[sz - 2].Val.ptr == nullptr && m_vRPN[sz - 1].Val.ptr != nullptr) ||
+                                                       (m_vRPN[sz - 2].Val.ptr != nullptr && m_vRPN[sz - 1].Val.ptr == nullptr) ||
+                                                       (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr));
+
+                                               m_vRPN[sz - 2].Cmd = cmVARMUL;
+                                               m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr));    // variable
+                                               m_vRPN[sz - 2].Val.data2 += ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2;  // offset
+                                               m_vRPN[sz - 2].Val.data += ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data;   // multiplicand
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       break;
+
+                               case  cmMUL:
+                                       if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR))
+                                       {
+                                               m_vRPN[sz - 2].Cmd = cmVARMUL;
+                                               m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr));
+                                               m_vRPN[sz - 2].Val.data = m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2;
+                                               m_vRPN[sz - 2].Val.data2 = 0;
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       else if (
+                                               (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
+                                               (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL))
+                                       {
+                                               // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
+                                               m_vRPN[sz - 2].Cmd = cmVARMUL;
+                                               m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr));
+                                               if (m_vRPN[sz - 1].Cmd == cmVAL)
+                                               {
+                                                       m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2;
+                                                       m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2;
+                                               }
+                                               else
+                                               {
+                                                       m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2;
+                                                       m_vRPN[sz - 2].Val.data2 = m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2;
+                                               }
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       else if (
+                                               m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR &&
+                                               m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr)
+                                       {
+                                               // Optimization: a*a -> a^2
+                                               m_vRPN[sz - 2].Cmd = cmVARPOW2;
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       break;
+
+                               case cmDIV:
+                                       if (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 1].Val.data2 != 0)
+                                       {
+                                               // Optimization: 4*a/2 -> 2*a
+                                               m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
+                                               m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
+                                               m_vRPN.pop_back();
+                                               bOptimized = true;
+                                       }
+                                       break;
+
+                                       // no optimization for other opcodes
+                               default:
+                                       break;
+                               } // switch a_Oprt
+                       }
+               }
+
+               // If optimization can't be applied just write the value
+               if (!bOptimized)
+               {
+                       --m_iStackPos;
+                       SToken tok;
+                       tok.Cmd = a_Oprt;
+                       m_vRPN.push_back(tok);
+               }
+       }
+
+
+       void ParserByteCode::AddIfElse(ECmdCode a_Oprt)
+       {
+               SToken tok;
+               tok.Cmd = a_Oprt;
+               m_vRPN.push_back(tok);
+       }
+
+
+       /** \brief Add an assignment operator
+
+               Operator entries in byte code consist of:
+               <ul>
+                 <li>cmASSIGN code</li>
+                 <li>the pointer of the destination variable</li>
+               </ul>
+
+               \sa  ParserToken::ECmdCode
+       */
+       void ParserByteCode::AddAssignOp(value_type* a_pVar)
+       {
+               --m_iStackPos;
+
+               SToken tok;
+               tok.Cmd = cmASSIGN;
+               tok.Oprt.ptr = a_pVar;
+               m_vRPN.push_back(tok);
+       }
+
+
+       /** \brief Add function to bytecode.
+
+               \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
+               \param a_pFun Pointer to function callback.
+       */
+       void ParserByteCode::AddFun(generic_callable_type a_pFun, int a_iArgc, bool isFunctionOptimizable)
+       {
+               std::size_t sz = m_vRPN.size();
+               bool optimize = false;
+
+               // only optimize functions with fixed number of more than a single arguments
+               if (isFunctionOptimizable && m_bEnableOptimizer && a_iArgc > 0)
+               {
+                       // <ibg 2020-06-10/> Unary Plus is a no-op
+                       if (a_pFun == generic_callable_type{(erased_fun_type)&MathImpl<value_type>::UnaryPlus, nullptr})
+                               return;
+
+                       optimize = true;
+
+                       for (int i = 0; i < std::abs(a_iArgc); ++i)
+                       {
+                               if (m_vRPN[sz - i - 1].Cmd != cmVAL)
+                               {
+                                       optimize = false;
+                                       break;
+                               }
+                       }
+               }
+
+               if (optimize)
+               {
+                       value_type val = 0;
+                       switch (a_iArgc)
+                       {
+                       case 1:  val = a_pFun.call_fun<1>(m_vRPN[sz - 1].Val.data2); break;
+                       case 2:  val = a_pFun.call_fun<2>(m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 3:  val = a_pFun.call_fun<3>(m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 4:  val = a_pFun.call_fun<4>(m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 5:  val = a_pFun.call_fun<5>(m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 6:  val = a_pFun.call_fun<6>(m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 7:  val = a_pFun.call_fun<7>(m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 8:  val = a_pFun.call_fun<8>(m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 9:  val = a_pFun.call_fun<9>(m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       case 10: val = a_pFun.call_fun<10>(m_vRPN[sz - 10].Val.data2, m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break;
+                       default:
+                               // For now functions with unlimited number of arguments are not optimized
+                               throw ParserError(ecINTERNAL_ERROR);
+                       }
+
+                       // remove the folded values
+                       m_vRPN.erase(m_vRPN.end() - a_iArgc, m_vRPN.end());
+
+                       SToken tok;
+                       tok.Cmd = cmVAL;
+                       tok.Val.data = 0;
+                       tok.Val.data2 = val;
+                       tok.Val.ptr = nullptr;
+                       m_vRPN.push_back(tok);
+               }
+               else
+               {
+                       SToken tok;
+                       tok.Cmd = cmFUNC;
+                       tok.Fun.argc = a_iArgc;
+                       tok.Fun.cb = a_pFun;
+                       m_vRPN.push_back(tok);
+               }
+
+               m_iStackPos = m_iStackPos - std::abs(a_iArgc) + 1;
+               m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+       }
+
+
+       /** \brief Add a bulk function to bytecode.
+
+               \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
+               \param a_pFun Pointer to function callback.
+       */
+       void ParserByteCode::AddBulkFun(generic_callable_type a_pFun, int a_iArgc)
+       {
+               m_iStackPos = m_iStackPos - a_iArgc + 1;
+               m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+               SToken tok;
+               tok.Cmd = cmFUNC_BULK;
+               tok.Fun.argc = a_iArgc;
+               tok.Fun.cb = a_pFun;
+               m_vRPN.push_back(tok);
+       }
+
+
+       /** \brief Add Strung function entry to the parser bytecode.
+               \throw nothrow
+
+               A string function entry consists of the stack position of the return value,
+               followed by a cmSTRFUNC code, the function pointer and an index into the
+               string buffer maintained by the parser.
+       */
+       void ParserByteCode::AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx)
+       {
+               m_iStackPos = m_iStackPos - a_iArgc + 1;
+
+               SToken tok;
+               tok.Cmd = cmFUNC_STR;
+               tok.Fun.argc = a_iArgc;
+               tok.Fun.idx = a_iIdx;
+               tok.Fun.cb = a_pFun;
+               m_vRPN.push_back(tok);
+
+               m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+       }
+
+
+       /** \brief Add end marker to bytecode.
+
+               \throw nothrow
+       */
+       void ParserByteCode::Finalize()
+       {
+               SToken tok;
+               tok.Cmd = cmEND;
+               m_vRPN.push_back(tok);
+               rpn_type(m_vRPN).swap(m_vRPN);     // shrink bytecode vector to fit
+
+               // Determine the if-then-else jump offsets
+               std::stack<int> stIf, stElse;
+               int idx;
+               for (int i = 0; i < (int)m_vRPN.size(); ++i)
+               {
+                       switch (m_vRPN[i].Cmd)
+                       {
+                       case cmIF:
+                               stIf.push(i);
+                               break;
+
+                       case cmELSE:
+                               stElse.push(i);
+                               idx = stIf.top();
+                               stIf.pop();
+                               m_vRPN[idx].Oprt.offset = i - idx;
+                               break;
+
+                       case cmENDIF:
+                               idx = stElse.top();
+                               stElse.pop();
+                               m_vRPN[idx].Oprt.offset = i - idx;
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+       }
+
+
+       std::size_t ParserByteCode::GetMaxStackSize() const
+       {
+               return m_iMaxStackSize + 1;
+       }
+
+
+       /** \brief Delete the bytecode.
+
+               \throw nothrow
+
+               The name of this function is a violation of my own coding guidelines
+               but this way it's more in line with the STL functions thus more
+               intuitive.
+       */
+       void ParserByteCode::clear()
+       {
+               m_vRPN.clear();
+               m_iStackPos = 0;
+               m_iMaxStackSize = 0;
+       }
+
+
+       /** \brief Dump bytecode (for debugging only!). */
+       void ParserByteCode::AsciiDump()
+       {
+               if (!m_vRPN.size())
+               {
+                       mu::console() << _T("No bytecode available\n");
+                       return;
+               }
+
+               mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");
+               for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd != cmEND; ++i)
+               {
+                       mu::console() << std::dec << i << _T(" : \t");
+                       switch (m_vRPN[i].Cmd)
+                       {
+                       case cmVAL:   mu::console() << _T("VAL \t");
+                               mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n");
+                               break;
+
+                       case cmVAR:   mu::console() << _T("VAR \t");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
+                               break;
+
+                       case cmVARPOW2: mu::console() << _T("VARPOW2 \t");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
+                               break;
+
+                       case cmVARPOW3: mu::console() << _T("VARPOW3 \t");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
+                               break;
+
+                       case cmVARPOW4: mu::console() << _T("VARPOW4 \t");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
+                               break;
+
+                       case cmVARMUL:  mu::console() << _T("VARMUL \t");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]");
+                               mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]");
+                               mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n");
+                               break;
+
+                       case cmFUNC:  mu::console() << _T("CALL\t");
+                               mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) << _T("]");
+                               mu::console() << _T("[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) << _T("]");
+                               mu::console() << _T("\n");
+                               break;
+
+                       case cmFUNC_STR:
+                               mu::console() << _T("CALL STRFUNC\t");
+                               mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
+                               mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("]");
+                               mu::console() << _T("[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) << _T("]");
+                               mu::console() << _T("[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) << _T("]");
+                               mu::console() << _T("\n");
+                               break;
+
+                       case cmLT:    mu::console() << _T("LT\n");  break;
+                       case cmGT:    mu::console() << _T("GT\n");  break;
+                       case cmLE:    mu::console() << _T("LE\n");  break;
+                       case cmGE:    mu::console() << _T("GE\n");  break;
+                       case cmEQ:    mu::console() << _T("EQ\n");  break;
+                       case cmNEQ:   mu::console() << _T("NEQ\n"); break;
+                       case cmADD:   mu::console() << _T("ADD\n"); break;
+                       case cmLAND:  mu::console() << _T("&&\n"); break;
+                       case cmLOR:   mu::console() << _T("||\n"); break;
+                       case cmSUB:   mu::console() << _T("SUB\n"); break;
+                       case cmMUL:   mu::console() << _T("MUL\n"); break;
+                       case cmDIV:   mu::console() << _T("DIV\n"); break;
+                       case cmPOW:   mu::console() << _T("POW\n"); break;
+
+                       case cmIF:    mu::console() << _T("IF\t");
+                               mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
+                               break;
+
+                       case cmELSE:  mu::console() << _T("ELSE\t");
+                               mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
+                               break;
+
+                       case cmENDIF: mu::console() << _T("ENDIF\n"); break;
+
+                       case cmASSIGN:
+                               mu::console() << _T("ASSIGN\t");
+                               mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n");
+                               break;
+
+                       default:      mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n");
+                               break;
+                       } // switch cmdCode
+               } // while bytecode
+
+               mu::console() << _T("END") << std::endl;
+       }
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
diff --git a/bundled/muparser_v2_3_3/src/muParserCallback.cpp b/bundled/muparser_v2_3_3/src/muParserCallback.cpp
new file mode 100644 (file)
index 0000000..8f2265b
--- /dev/null
@@ -0,0 +1,894 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2022 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserCallback.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+/** \file
+       \brief Implementation of the parser callback class.
+*/
+
+
+namespace mu
+{
+       static constexpr int CALLBACK_INTERNAL_VAR_ARGS         = 1 << 14;
+       static constexpr int CALLBACK_INTERNAL_FIXED_ARGS_MASK  = 0xf;
+       static constexpr int CALLBACK_INTERNAL_WITH_USER_DATA   = 1 << 13;
+
+       struct CbWithUserData
+       {
+               void*   pFun;
+               void*   pUserData;
+       };
+
+
+       ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(0)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(1)
+               , m_iPri(a_iPrec)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(a_iCode)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti)
+               : ParserCallback(a_pFun, a_bAllowOpti, -1, cmFUNC)
+       {}
+
+       
+       /** \brief Constructor for constructing function callbacks taking two arguments.
+               \throw nothrow
+       */
+       ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(2)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       /** \brief Constructor for constructing binary operator callbacks.
+               \param a_pFun Pointer to a static function taking two arguments
+               \param a_bAllowOpti A flag indicating this function can be optimized
+               \param a_iPrec The operator precedence
+               \param a_eOprtAsct The operators associativity
+               \throw nothrow
+       */
+       ParserCallback::ParserCallback(fun_type2 a_pFun,
+               bool a_bAllowOpti,
+               int a_iPrec,
+               EOprtAssociativity a_eOprtAsct)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(2)
+               , m_iPri(a_iPrec)
+               , m_eOprtAsct(a_eOprtAsct)
+               , m_iCode(cmOPRT_BIN)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(3)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(4)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(5)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(6)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(7)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(8)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(9)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(10)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(6 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(7 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(8 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(9 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(fun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(10 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(0)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(1)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       /** \brief Constructor for constructing function callbacks taking two arguments.
+               \throw nothrow
+       */
+       ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(2)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(3)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(4)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(5)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(6)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(7)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(8)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(9)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(10)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(6 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(7 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(8 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(9 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(bulkfun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(10 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_BULK)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(CALLBACK_INTERNAL_VAR_ARGS)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(multfun_userdata_type a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(CALLBACK_INTERNAL_VAR_ARGS | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC)
+               , m_iType(tpDBL)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(0)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(1)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(2)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_type4 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(3)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_type5 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(4)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+       ParserCallback::ParserCallback(strfun_type6 a_pFun, bool a_bAllowOpti)
+               :m_pFun((void*)a_pFun)
+               , m_iArgc(5)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{reinterpret_cast<void*>(a_pFun), a_pUserData})
+               , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+
+       ParserCallback::ParserCallback(strfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti)
+               :m_pFun(new CbWithUserData{ reinterpret_cast<void*>(a_pFun), a_pUserData })
+               , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmFUNC_STR)
+               , m_iType(tpSTR)
+               , m_bAllowOpti(a_bAllowOpti)
+       {}
+
+       /** \brief Default constructor.
+               \throw nothrow
+       */
+       ParserCallback::ParserCallback()
+               :m_pFun(0)
+               , m_iArgc(0)
+               , m_iPri(-1)
+               , m_eOprtAsct(oaNONE)
+               , m_iCode(cmUNKNOWN)
+               , m_iType(tpVOID)
+               , m_bAllowOpti(0)
+       {}
+
+
+       /** \brief Copy constructor.
+               \throw nothrow
+       */
+       ParserCallback::ParserCallback(const ParserCallback& ref)
+               :ParserCallback()
+       {
+               Assign(ref);
+       }
+
+       ParserCallback & ParserCallback::operator=(const ParserCallback & ref)
+       {
+               Assign(ref);
+               return *this;
+       }
+
+
+       ParserCallback::~ParserCallback()
+       {
+               if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA)
+                       delete reinterpret_cast<CbWithUserData*>(m_pFun);
+       }
+
+
+       /** \brief Copy callback from argument.
+
+               \throw nothrow
+       */
+       void ParserCallback::Assign(const ParserCallback& ref)
+       {
+               if (this == &ref)
+                       return;
+
+               if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) {
+                       delete reinterpret_cast<CbWithUserData*>(m_pFun);
+                       m_pFun = nullptr;
+               }
+
+               if (ref.m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA)
+                       m_pFun = new CbWithUserData(*reinterpret_cast<CbWithUserData*>(ref.m_pFun));
+               else
+                       m_pFun = ref.m_pFun;
+               m_iArgc = ref.m_iArgc;
+               m_bAllowOpti = ref.m_bAllowOpti;
+               m_iCode = ref.m_iCode;
+               m_iType = ref.m_iType;
+               m_iPri = ref.m_iPri;
+               m_eOprtAsct = ref.m_eOprtAsct;
+       }
+
+
+       /** \brief Clone this instance and return a pointer to the new instance. */
+       ParserCallback* ParserCallback::Clone() const
+       {
+               return new ParserCallback(*this);
+       }
+
+
+       /** \brief Return tru if the function is conservative.
+
+               Conservative functions return always the same result for the same argument.
+               \throw nothrow
+       */
+       bool ParserCallback::IsOptimizable() const
+       {
+               return m_bAllowOpti;
+       }
+
+
+       /** \brief Get the callback address for the parser function.
+
+               The type of the address is void. It needs to be recasted according to the
+               argument number to the right type.
+
+               \throw nothrow
+       */
+       void* ParserCallback::GetAddr() const
+       {
+               if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA)
+                       return reinterpret_cast<CbWithUserData*>(m_pFun)->pFun;
+               else
+                       return m_pFun;
+       }
+
+
+       /** \brief Get the user data if present, else nullptr
+
+               \throw nothrow
+       */
+       void* ParserCallback::GetUserData() const
+       {
+               if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA)
+                       return reinterpret_cast<CbWithUserData*>(m_pFun)->pUserData;
+               else
+                       return nullptr;
+       }
+
+
+       /** \brief Check that the callback looks valid
+               \throw nothrow
+
+               Check that the function pointer is not null,
+               and if there are user data that they are not null.
+       */
+       bool ParserCallback::IsValid() const
+       {
+               return GetAddr() != nullptr
+                       && !((m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA)
+                            && GetUserData() == nullptr);
+       }
+
+
+       /** \brief Return the callback code. */
+       ECmdCode  ParserCallback::GetCode() const
+       {
+               return m_iCode;
+       }
+
+
+       ETypeCode ParserCallback::GetType() const
+       {
+               return m_iType;
+       }
+
+
+       /** \brief Return the operator precedence.
+               \throw nothrown
+
+          Only valid if the callback token is an operator token (binary or infix).
+       */
+       int ParserCallback::GetPri()  const
+       {
+               return m_iPri;
+       }
+
+
+       /** \brief Return the operators associativity.
+               \throw nothrown
+
+          Only valid if the callback token is a binary operator token.
+       */
+       EOprtAssociativity ParserCallback::GetAssociativity() const
+       {
+               return m_eOprtAsct;
+       }
+
+
+       /** \brief Returns the number of numeric function Arguments.
+
+          This number is negative for functions with variable number of arguments.
+       */
+       int ParserCallback::GetArgc() const
+       {
+               return (m_iArgc & CALLBACK_INTERNAL_VAR_ARGS) ? -1 : (m_iArgc & CALLBACK_INTERNAL_FIXED_ARGS_MASK);
+       }
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
diff --git a/bundled/muparser_v2_3_3/src/muParserError.cpp b/bundled/muparser_v2_3_3/src/muParserError.cpp
new file mode 100644 (file)
index 0000000..960e48a
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserError.h"
+#include <exception>
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) // MSVC wants to force me te use enum classes or bother me with pointless warnings
+#endif
+
+namespace mu
+{
+       //------------------------------------------------------------------------------
+       const ParserErrorMsg& ParserErrorMsg::Instance()
+       {
+               static const ParserErrorMsg instance;
+               return instance;
+       }
+
+       //------------------------------------------------------------------------------
+       string_type ParserErrorMsg::operator[](unsigned a_iIdx) const
+       {
+               return (a_iIdx < m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
+       }
+
+       //---------------------------------------------------------------------------
+       ParserErrorMsg::ParserErrorMsg()
+               :m_vErrMsg(0)
+       {
+               m_vErrMsg.resize(ecCOUNT);
+
+               m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$.");
+               m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");
+               m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\".");
+               m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\".");
+               m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\".");
+               m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\".");
+               m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");
+               m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");
+               m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");
+               m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");
+               m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");
+               m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
+               m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");
+               m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");
+               m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");
+               m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");
+               m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");
+               m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");
+               m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");
+               m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");
+               m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");
+               m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");
+               m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");
+               m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");
+               m_vErrMsg[ecSTR_RESULT] = _T("Strings must only be used as function arguments!");
+               m_vErrMsg[ecGENERIC] = _T("Parser error.");
+               m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");
+               m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceded by a closing bracket.");
+               m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");
+               m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");
+               m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)");
+               m_vErrMsg[ecIDENTIFIER_TOO_LONG] = _T("Identifier too long.");
+               m_vErrMsg[ecEXPRESSION_TOO_LONG] = _T("Expression too long.");
+               m_vErrMsg[ecINVALID_CHARACTERS_FOUND] = _T("Invalid non printable characters found in expression/identifer!");
+
+               for (int i = 0; i < ecCOUNT; ++i)
+               {
+                       if (!m_vErrMsg[i].length())
+                               throw std::runtime_error("Error definitions are incomplete!");
+               }
+       }
+
+       //---------------------------------------------------------------------------
+       //
+       //  ParserError class
+       //
+       //---------------------------------------------------------------------------
+
+       /** \brief Default constructor. */
+       ParserError::ParserError()
+               :m_strMsg()
+               , m_strFormula()
+               , m_strTok()
+               , m_iPos(-1)
+               , m_iErrc(ecUNDEFINED)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief This Constructor is used for internal exceptions only.
+
+         It does not contain any information but the error code.
+       */
+       ParserError::ParserError(EErrorCodes a_iErrc)
+               :m_strMsg()
+               , m_strFormula()
+               , m_strTok()
+               , m_iPos(-1)
+               , m_iErrc(a_iErrc)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+               m_strMsg = m_ErrMsg[m_iErrc];
+               stringstream_type stream;
+               stream << (int)m_iPos;
+               ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+               ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Construct an error from a message text. */
+       ParserError::ParserError(const string_type& sMsg)
+               :m_ErrMsg(ParserErrorMsg::Instance())
+       {
+               Reset();
+               m_strMsg = sMsg;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Construct an error object.
+               \param [in] a_iErrc the error code.
+               \param [in] sTok The token string related to this error.
+               \param [in] sExpr The expression related to the error.
+               \param [in] a_iPos the position in the expression where the error occurred.
+       */
+       ParserError::ParserError(EErrorCodes iErrc,
+               const string_type& sTok,
+               const string_type& sExpr,
+               int iPos)
+               :m_strMsg()
+               , m_strFormula(sExpr)
+               , m_strTok(sTok)
+               , m_iPos(iPos)
+               , m_iErrc(iErrc)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+               m_strMsg = m_ErrMsg[m_iErrc];
+               stringstream_type stream;
+               stream << (int)m_iPos;
+               ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+               ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Construct an error object.
+               \param [in] iErrc the error code.
+               \param [in] iPos the position in the expression where the error occurred.
+               \param [in] sTok The token string related to this error.
+       */
+       ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type& sTok)
+               :m_strMsg()
+               , m_strFormula()
+               , m_strTok(sTok)
+               , m_iPos(iPos)
+               , m_iErrc(iErrc)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+               m_strMsg = m_ErrMsg[m_iErrc];
+               stringstream_type stream;
+               stream << (int)m_iPos;
+               ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+               ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Construct an error object.
+               \param [in] szMsg The error message text.
+               \param [in] iPos the position related to the error.
+               \param [in] sTok The token string related to this error.
+       */
+       ParserError::ParserError(const char_type* szMsg, int iPos, const string_type& sTok)
+               :m_strMsg(szMsg)
+               , m_strFormula()
+               , m_strTok(sTok)
+               , m_iPos(iPos)
+               , m_iErrc(ecGENERIC)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+               stringstream_type stream;
+               stream << (int)m_iPos;
+               ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+               ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Copy constructor. */
+       ParserError::ParserError(const ParserError& a_Obj)
+               :m_strMsg(a_Obj.m_strMsg)
+               , m_strFormula(a_Obj.m_strFormula)
+               , m_strTok(a_Obj.m_strTok)
+               , m_iPos(a_Obj.m_iPos)
+               , m_iErrc(a_Obj.m_iErrc)
+               , m_ErrMsg(ParserErrorMsg::Instance())
+       {
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Assignment operator. */
+       ParserError& ParserError::operator=(const ParserError& a_Obj)
+       {
+               if (this == &a_Obj)
+                       return *this;
+
+               m_strMsg = a_Obj.m_strMsg;
+               m_strFormula = a_Obj.m_strFormula;
+               m_strTok = a_Obj.m_strTok;
+               m_iPos = a_Obj.m_iPos;
+               m_iErrc = a_Obj.m_iErrc;
+               return *this;
+       }
+
+       //------------------------------------------------------------------------------
+       ParserError::~ParserError()
+       {}
+
+       //------------------------------------------------------------------------------
+       /** \brief Replace all occurrences of a substring with another string.
+               \param strFind The string that shall be replaced.
+               \param strReplaceWith The string that should be inserted instead of strFind
+       */
+       void ParserError::ReplaceSubString(string_type& strSource,
+               const string_type& strFind,
+               const string_type& strReplaceWith)
+       {
+               string_type strResult;
+               string_type::size_type iPos(0), iNext(0);
+
+               for (;;)
+               {
+                       iNext = strSource.find(strFind, iPos);
+                       strResult.append(strSource, iPos, iNext - iPos);
+
+                       if (iNext == string_type::npos)
+                               break;
+
+                       strResult.append(strReplaceWith);
+                       iPos = iNext + strFind.length();
+               }
+
+               strSource.swap(strResult);
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Reset the error object. */
+       void ParserError::Reset()
+       {
+               m_strMsg = _T("");
+               m_strFormula = _T("");
+               m_strTok = _T("");
+               m_iPos = -1;
+               m_iErrc = ecUNDEFINED;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Set the expression related to this error. */
+       void ParserError::SetFormula(const string_type& a_strFormula)
+       {
+               m_strFormula = a_strFormula;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief gets the expression related tp this error.*/
+       const string_type& ParserError::GetExpr() const
+       {
+               return m_strFormula;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Returns the message string for this error. */
+       const string_type& ParserError::GetMsg() const
+       {
+               return m_strMsg;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Return the formula position related to the error.
+
+         If the error is not related to a distinct position this will return -1
+       */
+       int ParserError::GetPos() const
+       {
+               return m_iPos;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Return string related with this token (if available). */
+       const string_type& ParserError::GetToken() const
+       {
+               return m_strTok;
+       }
+
+       //------------------------------------------------------------------------------
+       /** \brief Return the error code. */
+       EErrorCodes ParserError::GetCode() const
+       {
+               return m_iErrc;
+       }
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
diff --git a/bundled/muparser_v2_3_3/src/muParserInt.cpp b/bundled/muparser_v2_3_3/src/muParserInt.cpp
new file mode 100644 (file)
index 0000000..76189e9
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserInt.h"
+
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+using namespace std;
+
+/** \file
+       \brief Implementation of a parser using integer value.
+*/
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+       value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
+       value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; }
+       value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); }
+       value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
+       value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
+       value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
+       value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
+       value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
+       value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
+       value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
+       value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
+       value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
+       value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
+       value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
+       value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
+       value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
+       value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
+       value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
+       value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
+       value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
+       value_type ParserInt::Not(value_type v) { return !Round(v); }
+
+       value_type ParserInt::Pow(value_type v1, value_type v2)
+       {
+               return std::pow((double)Round(v1), (double)Round(v2));
+       }
+
+
+       value_type ParserInt::UnaryMinus(value_type v)
+       {
+               return -Round(v);
+       }
+
+
+       value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
+       {
+               if (!a_iArgc)
+                       throw ParserError(_T("too few arguments for function sum."));
+
+               value_type fRes = 0;
+               for (int i = 0; i < a_iArgc; ++i)
+                       fRes += a_afArg[i];
+
+               return fRes;
+       }
+
+
+       value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
+       {
+               if (!a_iArgc)
+                       throw ParserError(_T("too few arguments for function min."));
+
+               value_type fRes = a_afArg[0];
+               for (int i = 0; i < a_iArgc; ++i)
+                       fRes = std::min(fRes, a_afArg[i]);
+
+               return fRes;
+       }
+
+
+       value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
+       {
+               if (!a_iArgc)
+                       throw ParserError(_T("too few arguments for function min."));
+
+               value_type fRes = a_afArg[0];
+               for (int i = 0; i < a_iArgc; ++i)
+                       fRes = std::max(fRes, a_afArg[i]);
+
+               return fRes;
+       }
+
+
+       int ParserInt::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
+       {
+               string_type buf(a_szExpr);
+               std::size_t pos = buf.find_first_not_of(_T("0123456789"));
+
+               if (pos == std::string::npos)
+                       return 0;
+
+               stringstream_type stream(buf.substr(0, pos));
+               int iVal(0);
+
+               stream >> iVal;
+               if (stream.fail())
+                       return 0;
+
+               stringstream_type::pos_type iEnd = stream.tellg();   // Position after reading
+               if (stream.fail())
+                       iEnd = stream.str().length();
+
+               if (iEnd == (stringstream_type::pos_type) - 1)
+                       return 0;
+
+               *a_iPos += (int)iEnd;
+               *a_fVal = (value_type)iVal;
+               return 1;
+       }
+
+
+       /** \brief Check a given position in the expression for the presence of
+                          a hex value.
+               \param a_szExpr Pointer to the expression string
+               \param [in/out] a_iPos Pointer to an integer value holding the current parsing
+                          position in the expression.
+               \param [out] a_fVal Pointer to the position where the detected value shall be stored.
+
+         Hey values must be prefixed with "0x" in order to be detected properly.
+       */
+       int ParserInt::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
+       {
+               if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x'))
+                       return 0;
+
+               unsigned iVal(0);
+
+               // New code based on streams for UNICODE compliance:
+               stringstream_type::pos_type nPos(0);
+               stringstream_type ss(a_szExpr + 2);
+               ss >> std::hex >> iVal;
+               nPos = ss.tellg();
+
+               if (nPos == (stringstream_type::pos_type)0)
+                       return 1;
+
+               *a_iPos += (int)(2 + nPos);
+               *a_fVal = (value_type)iVal;
+               return 1;
+       }
+
+
+       int ParserInt::IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
+       {
+               if (a_szExpr[0] != '#')
+                       return 0;
+
+               unsigned iVal(0),
+                       iBits(sizeof(iVal) * 8),
+                       i(0);
+
+               for (i = 0; (a_szExpr[i + 1] == '0' || a_szExpr[i + 1] == '1') && i < iBits; ++i)
+                       iVal |= (int)(a_szExpr[i + 1] == '1') << ((iBits - 1) - i);
+
+               if (i == 0)
+                       return 0;
+
+               if (i == iBits)
+                       throw exception_type(_T("Binary to integer conversion error (overflow)."));
+
+               *a_fVal = (unsigned)(iVal >> (iBits - i));
+               *a_iPos += i + 1;
+
+               return 1;
+       }
+
+
+       /** \brief Constructor.
+
+               Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+       */
+       ParserInt::ParserInt()
+               :ParserBase()
+       {
+               AddValIdent(IsVal);    // lowest priority
+               AddValIdent(IsBinVal);
+               AddValIdent(IsHexVal); // highest priority
+
+               InitCharSets();
+               InitFun();
+               InitOprt();
+       }
+
+
+       void ParserInt::InitConst()
+       {
+       }
+
+
+       void ParserInt::InitCharSets()
+       {
+               DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+               DefineOprtChars(_T("+-*^/?<>=!%&|~'_"));
+               DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_"));
+       }
+
+
+       /** \brief Initialize the default functions. */
+       void ParserInt::InitFun()
+       {
+               DefineFun(_T("sign"), Sign);
+               DefineFun(_T("abs"), Abs);
+               DefineFun(_T("if"), Ite);
+               DefineFun(_T("sum"), Sum);
+               DefineFun(_T("min"), Min);
+               DefineFun(_T("max"), Max);
+       }
+
+
+       /** \brief Initialize operators. */
+       void ParserInt::InitOprt()
+       {
+               // disable all built in operators, not all of them useful for integer numbers
+               // (they don't do rounding of values)
+               EnableBuiltInOprt(false);
+
+               // Disable all built in operators, they won't work with integer numbers
+               // since they are designed for floating point numbers
+               DefineInfixOprt(_T("-"), UnaryMinus);
+               DefineInfixOprt(_T("!"), Not);
+
+               DefineOprt(_T("&"), LogAnd, prLOGIC);
+               DefineOprt(_T("|"), LogOr, prLOGIC);
+               DefineOprt(_T("&&"), And, prLOGIC);
+               DefineOprt(_T("||"), Or, prLOGIC);
+
+               DefineOprt(_T("<"), Less, prCMP);
+               DefineOprt(_T(">"), Greater, prCMP);
+               DefineOprt(_T("<="), LessEq, prCMP);
+               DefineOprt(_T(">="), GreaterEq, prCMP);
+               DefineOprt(_T("=="), Equal, prCMP);
+               DefineOprt(_T("!="), NotEqual, prCMP);
+
+               DefineOprt(_T("+"), Add, prADD_SUB);
+               DefineOprt(_T("-"), Sub, prADD_SUB);
+
+               DefineOprt(_T("*"), Mul, prMUL_DIV);
+               DefineOprt(_T("/"), Div, prMUL_DIV);
+               DefineOprt(_T("%"), Mod, prMUL_DIV);
+
+               DefineOprt(_T("^"), Pow, prPOW, oaRIGHT);
+               DefineOprt(_T(">>"), Shr, prMUL_DIV + 1);
+               DefineOprt(_T("<<"), Shl, prMUL_DIV + 1);
+       }
+
+} // namespace mu
diff --git a/bundled/muparser_v2_3_3/src/muParserTest.cpp b/bundled/muparser_v2_3_3/src/muParserTest.cpp
new file mode 100644 (file)
index 0000000..46e0af7
--- /dev/null
@@ -0,0 +1,1717 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2022 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "muParserTest.h"
+
+#include <cstdio>
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+using namespace std;
+
+/** \file
+       \brief This file contains the implementation of parser test cases.
+*/
+
+namespace mu
+{
+       namespace Test
+       {
+               int ParserTester::c_iCount = 0;
+
+               //---------------------------------------------------------------------------------------------
+               ParserTester::ParserTester()
+                       :m_vTestFun()
+               {
+                       AddTest(&ParserTester::TestNames);
+                       AddTest(&ParserTester::TestSyntax);
+                       AddTest(&ParserTester::TestPostFix);
+                       AddTest(&ParserTester::TestInfixOprt);
+                       AddTest(&ParserTester::TestVarConst);
+                       AddTest(&ParserTester::TestMultiArg);
+                       AddTest(&ParserTester::TestExpression);
+                       AddTest(&ParserTester::TestIfThenElse);
+                       AddTest(&ParserTester::TestInterface);
+                       AddTest(&ParserTester::TestBinOprt);
+                       AddTest(&ParserTester::TestException);
+                       AddTest(&ParserTester::TestStrArg);
+                       AddTest(&ParserTester::TestBulkMode);
+                       AddTest(&ParserTester::TestOptimizer);
+
+                       ParserTester::c_iCount = 0;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
+               {
+                       if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x'))
+                               return 0;
+
+                       unsigned iVal(0);
+
+                       // New code based on streams for UNICODE compliance:
+                       stringstream_type::pos_type nPos(0);
+                       stringstream_type ss(a_szExpr + 2);
+                       ss >> std::hex >> iVal;
+                       nPos = ss.tellg();
+
+                       if (nPos == (stringstream_type::pos_type)0)
+                               return 1;
+
+                       *a_iPos += (int)(2 + nPos);
+                       *a_fVal = (value_type)iVal;
+                       return 1;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::TestInterface()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing member functions...");
+
+                       // Test RemoveVar
+                       value_type afVal[3] = { 1,2,3 };
+                       Parser p;
+
+                       try
+                       {
+                               p.DefineVar(_T("a"), &afVal[0]);
+                               p.DefineVar(_T("b"), &afVal[1]);
+                               p.DefineVar(_T("c"), &afVal[2]);
+                               p.SetExpr(_T("a+b+c"));
+                               p.Eval();
+                       }
+                       catch (...)
+                       {
+                               iStat += 1;  // this is not supposed to happen 
+                       }
+
+                       try
+                       {
+                               p.RemoveVar(_T("c"));
+                               p.Eval();
+                               iStat += 1;  // not supposed to reach this, nonexisting variable "c" deleted...
+                       }
+                       catch (...)
+                       {
+                               // failure is expected...
+                       }
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::TestOptimizer()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing optimizer...");
+
+                       // Test RemoveVar
+                       Parser p;
+                       try
+                       {
+                               // test for #93 (https://github.com/beltoforion/muparser/issues/93)
+                               // expected bytecode is:
+                               // VAL, FUN
+                               {
+                                       p.DefineFun(_T("unoptimizable"), f1of1, false);
+                                       p.SetExpr(_T("unoptimizable(1)"));
+                                       p.Eval();
+
+                                       auto& bc = p.GetByteCode();
+                                       const SToken* tok = bc.GetBase();
+                                       if (bc.GetSize() != 2 && tok[1].Cmd != cmFUNC)
+                                       {
+                                               mu::console() << _T("#93 an unoptimizable expression was optimized!") << endl;
+                                               iStat += 1;
+                                       }
+                               }
+
+                               {
+                                       p.ClearFun();
+                                       p.DefineFun(_T("unoptimizable"), f1of1, true);
+                                       p.SetExpr(_T("unoptimizable(1)"));
+                                       p.Eval();
+
+                                       auto& bc = p.GetByteCode();
+                                       const SToken* tok = bc.GetBase();
+                                       if (bc.GetSize() != 1 && tok[0].Cmd != cmVAL)
+                                       {
+                                               mu::console() << _T("#93 optimizer error") << endl;
+                                               iStat += 1;
+                                       }
+                               }
+                       }
+                       catch (...)
+                       {
+                               iStat += 1;  // this is not supposed to happen 
+                       }
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::TestStrArg()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing string arguments...");
+
+                       // from oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23410
+                       iStat += ThrowTest(_T(R"(6 - 6 ? 4 : "", ? 4 : "", ? 4 : "")"), ecUNEXPECTED_STR, true);
+                       // variations:
+                       iStat += ThrowTest(_T(R"(avg(0?4:(""),1))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(1 ? 4 : "")"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(1 ? "" : 4)"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(1 ? "" : "")"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(0 ? 4 : "")"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(0 ? 4 : (""))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(1 ? 4 : "")"), ecUNEXPECTED_STR);
+
+                       // from oss-fuzz: https://oss-fuzz.com/testcase-detail/5106868061208576
+                       iStat += ThrowTest(_T(R"("","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",8)"), ecSTR_RESULT);
+
+                       // derived from oss-fuzz: https://oss-fuzz.com/testcase-detail/5758791700971520
+                       iStat += ThrowTest(_T("(\"\"), 7"), ecSTR_RESULT);
+                       iStat += ThrowTest(_T("((\"\")), 7"), ecSTR_RESULT);
+                       //iStat += ThrowTest(_T("(\"\"),(\" \"), 7, (3)"), ecSTR_RESULT);
+                       //iStat += ThrowTest(_T("(\"\"),(\"\"), 7, (3)"), ecSTR_RESULT);
+                       //iStat += ThrowTest(_T("(\"\"),(\"\"), (3)"), ecSTR_RESULT);
+                       //iStat += ThrowTest(_T("(\"\"),(\"\"), 7"), ecSTR_RESULT);
+
+
+                       // variations:
+                       iStat += ThrowTest(_T(R"("","",9)"), ecSTR_RESULT);
+
+                       iStat += EqnTest(_T("valueof(\"\")"), 123, true);   // empty string arguments caused a crash
+                       iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\")  "), 246, true);
+                       iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);
+
+                       // use in expressions with variables
+                       iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);
+                       iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);
+
+                       // string + numeric arguments
+                       iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);
+                       iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);
+                       iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);
+                       iStat += EqnTest(_T("strfun4(\"99\",1,2,3)"), 105, true);
+                       iStat += EqnTest(_T("strfun5(\"99\",1,2,3,4)"), 109, true);
+                       iStat += EqnTest(_T("strfun6(\"99\",1,2,3,4,5)"), 114, true);
+
+                       // string constants
+                       iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true);
+
+                       // user data
+                       iStat += EqnTest(_T("strfunud3_10(\"99\",1,2)"), 112, true);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::TestBulkMode()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing bulkmode...");
+
+#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \
+                       { \
+                         double res[] = { R1, R2, R3, R4 }; \
+                         iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \
+                       }
+
+                       // Bulk Variables for the test:
+                       // a: 1,2,3,4
+                       // b: 2,2,2,2
+                       // c: 3,3,3,3
+                       // d: 5,4,3,2
+                       EQN_TEST_BULK("a", 1, 1, 1, 1, false)
+                       EQN_TEST_BULK("a", 1, 2, 3, 4, true)
+                       EQN_TEST_BULK("b=a", 1, 2, 3, 4, true)
+                       EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true)
+                       EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true)
+                       EQN_TEST_BULK("a+b", 3, 4, 5, 6, true)
+                       EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true)
+#undef EQN_TEST_BULK
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               int ParserTester::TestBinOprt()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing binary operators...");
+
+                       // built in operators
+                       // xor operator
+
+                       iStat += EqnTest(_T("a++b"), 3, true);
+                       iStat += EqnTest(_T("a ++ b"), 3, true);
+                       iStat += EqnTest(_T("1++2"), 3, true);
+                       iStat += EqnTest(_T("1 ++ 2"), 3, true);
+                       iStat += EqnTest(_T("a add b"), 3, true);
+                       iStat += EqnTest(_T("1 add 2"), 3, true);
+                       iStat += EqnTest(_T("a<b"), 1, true);
+                       iStat += EqnTest(_T("b>a"), 1, true);
+                       iStat += EqnTest(_T("a>a"), 0, true);
+                       iStat += EqnTest(_T("a<a"), 0, true);
+                       iStat += EqnTest(_T("a>a"), 0, true);
+                       iStat += EqnTest(_T("a<=a"), 1, true);
+                       iStat += EqnTest(_T("a<=b"), 1, true);
+                       iStat += EqnTest(_T("b<=a"), 0, true);
+                       iStat += EqnTest(_T("a>=a"), 1, true);
+                       iStat += EqnTest(_T("b>=a"), 1, true);
+                       iStat += EqnTest(_T("a>=b"), 0, true);
+
+                       // Test logical operators, especially if user defined "&" and the internal "&&" collide
+                       iStat += EqnTest(_T("1 && 1"), 1, true);
+                       iStat += EqnTest(_T("1 && 0"), 0, true);
+                       iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true);
+                       iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true);
+                       //iStat += EqnTest(_T("12 and 255"), 12, true); 
+                       //iStat += EqnTest(_T("12 and 0"), 0, true); 
+                       iStat += EqnTest(_T("12 & 255"), 12, true);
+                       iStat += EqnTest(_T("12 & 0"), 0, true);
+                       iStat += EqnTest(_T("12&255"), 12, true);
+                       iStat += EqnTest(_T("12&0"), 0, true);
+
+                       // Assignment operator
+                       iStat += EqnTest(_T("a = b"), 2, true);
+                       iStat += EqnTest(_T("a = sin(b)"), 0.909297, true);
+                       iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);
+                       iStat += EqnTest(_T("(a=b)*2"), 4, true);
+                       iStat += EqnTest(_T("2*(a=b)"), 4, true);
+                       iStat += EqnTest(_T("2*(a=b+1)"), 6, true);
+                       iStat += EqnTest(_T("(a=b+1)*2"), 6, true);
+                       iStat += EqnTest(_T("a=c, a*10"), 30, true);
+
+                       iStat += EqnTest(_T("2^2^3"), 256, true);
+                       iStat += EqnTest(_T("1/2/3"), 1.0 / 6.0, true);
+
+                       // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3
+                       iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true);
+
+                       // Test user defined binary operators
+                       iStat += EqnTestInt(_T("1 | 2"), 3, true);
+                       iStat += EqnTestInt(_T("1 || 2"), 1, true);
+                       iStat += EqnTestInt(_T("123 & 456"), 72, true);
+                       iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);
+                       iStat += EqnTestInt(_T("1 && 0"), 0, true);
+                       iStat += EqnTestInt(_T("123 && 456"), 1, true);
+                       iStat += EqnTestInt(_T("1 << 3"), 8, true);
+                       iStat += EqnTestInt(_T("8 >> 3"), 1, true);
+                       iStat += EqnTestInt(_T("9 / 4"), 2, true);
+                       iStat += EqnTestInt(_T("9 % 4"), 1, true);
+                       iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);
+                       iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);
+                       iStat += EqnTestInt(_T("-10+1"), -9, true);
+                       iStat += EqnTestInt(_T("1+2*3"), 7, true);
+                       iStat += EqnTestInt(_T("const1 != const2"), 1, true);
+                       iStat += EqnTestInt(_T("const1 != const2"), 0, false);
+                       iStat += EqnTestInt(_T("const1 == const2"), 0, true);
+                       iStat += EqnTestInt(_T("const1 == 1"), 1, true);
+                       iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);
+                       iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);
+                       iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);
+                       iStat += EqnTestInt(_T("const1 < const2"), 1, true);
+                       iStat += EqnTestInt(_T("const2 > const1"), 1, true);
+                       iStat += EqnTestInt(_T("const1 <= 1"), 1, true);
+                       iStat += EqnTestInt(_T("const2 >= 2"), 1, true);
+                       iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);
+                       iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);
+                       iStat += EqnTestInt(_T("a != b"), 1, true);
+                       iStat += EqnTestInt(_T("a != b"), 0, false);
+                       iStat += EqnTestInt(_T("a == b"), 0, true);
+                       iStat += EqnTestInt(_T("a == 1"), 1, true);
+                       iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);
+                       iStat += EqnTestInt(_T("2*(a | b)"), 6, true);
+                       iStat += EqnTestInt(_T("2*(a | b)"), 7, false);
+                       iStat += EqnTestInt(_T("a < b"), 1, true);
+                       iStat += EqnTestInt(_T("b > a"), 1, true);
+                       iStat += EqnTestInt(_T("a <= 1"), 1, true);
+                       iStat += EqnTestInt(_T("b >= 2"), 1, true);
+                       iStat += EqnTestInt(_T("2*(a + b)"), 6, true);
+                       iStat += EqnTestInt(_T("2*(a - b)"), -2, true);
+                       iStat += EqnTestInt(_T("a + (a << b)"), 5, true);
+                       iStat += EqnTestInt(_T("-2^2"), -4, true);
+                       iStat += EqnTestInt(_T("3--a"), 4, true);
+                       iStat += EqnTestInt(_T("3+-3^2"), -6, true);
+
+                       // Test reading of hex values:
+                       iStat += EqnTestInt(_T("0xff"), 255, true);
+                       iStat += EqnTestInt(_T("10+0xff"), 265, true);
+                       iStat += EqnTestInt(_T("0xff+10"), 265, true);
+                       iStat += EqnTestInt(_T("10*0xff"), 2550, true);
+                       iStat += EqnTestInt(_T("0xff*10"), 2550, true);
+                       iStat += EqnTestInt(_T("10+0xff+1"), 266, true);
+                       iStat += EqnTestInt(_T("1+0xff+10"), 266, true);
+
+                       // incorrect: '^' is yor here, not power
+                       //    iStat += EqnTestInt("-(1+2)^2", -9, true);
+                       //    iStat += EqnTestInt("-1^3", -1, true);          
+
+                                 // Test precedence
+                                 // a=1, b=2, c=3
+                       iStat += EqnTestInt(_T("a + b * c"), 7, true);
+                       iStat += EqnTestInt(_T("a * b + c"), 5, true);
+                       iStat += EqnTestInt(_T("a<b && b>10"), 0, true);
+                       iStat += EqnTestInt(_T("a<b && b<10"), 1, true);
+
+                       iStat += EqnTestInt(_T("a + b << c"), 17, true);
+                       iStat += EqnTestInt(_T("a << b + c"), 7, true);
+                       iStat += EqnTestInt(_T("c * b < a"), 0, true);
+                       iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);
+                       iStat += EqnTestInt(_T("2^2^3"), 256, true);
+
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------------------------
+               /** \brief Check muParser name restriction enforcement. */
+               int ParserTester::TestNames()
+               {
+                       int  iStat = 0,
+                               iErr = 0;
+
+                       mu::console() << "testing name restriction enforcement...";
+
+                       Parser p;
+
+#define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG)     \
+                       iErr = 0;                                                                               \
+                       ParserTester::c_iCount++;                                               \
+                       try                                                                                             \
+                       {                                                                                               \
+                               p.Define##DOMAIN(EXPR, ARG);                \
+                               iErr = (FAIL) ? 0 : 1;                                          \
+                       }                                                                                               \
+                       catch(...)                                                                              \
+                       {                                                                                               \
+                               iErr = (!FAIL) ? 0 : 1;                                         \
+                       }                                                                                               \
+                       iStat += iErr;      
+
+                       // constant names
+                       PARSER_THROWCHECK(Const, false, _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("0a"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("9a"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("+a"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("-a"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("a-"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("a*"), 1)
+                               PARSER_THROWCHECK(Const, false, _T("a?"), 1)
+                               PARSER_THROWCHECK(Const, true, _T("a"), 1)
+                               PARSER_THROWCHECK(Const, true, _T("a_min"), 1)
+                               PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)
+                               PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)
+
+                               // variable names
+                               value_type a;
+                       p.ClearConst();
+                       PARSER_THROWCHECK(Var, false, _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), &a);
+                       PARSER_THROWCHECK(Var, false, _T("123abc"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("9a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("0a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("+a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("-a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("?a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("!a"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("a+"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("a-"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("a*"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("a?"), &a)
+                               PARSER_THROWCHECK(Var, true, _T("a"), &a)
+                               PARSER_THROWCHECK(Var, true, _T("a_min"), &a)
+                               PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)
+                               PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)
+                               PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)
+
+                               // Postfix operators
+                               // fail
+                               PARSER_THROWCHECK(PostfixOprt, false, _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), f1of1);
+                       PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)
+                               // pass
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("_"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("#"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("&&"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("||"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("&"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("|"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("++"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("--"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("?>"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)
+                               PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1)
+
+                               // Binary operator
+                               // The following must fail with builtin operators activated
+                               // p.EnableBuiltInOp(true); -> this is the default
+                               p.ClearPostfixOprt();
+                       PARSER_THROWCHECK(Oprt, false, _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), f1of2);
+                       PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2)
+                               PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2)
+
+                               // without activated built in operators it should work
+                               p.EnableBuiltInOprt(false);
+                       PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2)
+                               PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2)
+#undef PARSER_THROWCHECK
+
+                               if (iStat == 0)
+                                       mu::console() << _T("passed") << endl;
+                               else
+                                       mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestSyntax()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing syntax engine...");
+
+                       iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF);  // incomplete hex definition
+                       iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF);  // incomplete hex definition
+                       iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF);  // incomplete hex definition
+                       iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF);  // incomplete hex definition
+                       iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF);  // incomplete hex definition
+
+                       iStat += EqnTest(_T("(1+ 2*a)"), 3, true);   // Spaces within formula
+                       iStat += EqnTest(_T("sqrt((4))"), 2, true);  // Multiple brackets
+                       iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets
+                       iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets
+                       iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets
+                       iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets
+                       iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or"
+                       iStat += EqnTest(_T("(2+"), 0, false);       // missing closing bracket 
+                       iStat += EqnTest(_T("2++4"), 0, false);      // unexpected operator
+                       iStat += EqnTest(_T("2+-4"), 0, false);      // unexpected operator
+                       iStat += EqnTest(_T("(2+)"), 0, false);      // unexpected closing bracket
+                       iStat += EqnTest(_T("--2"), 0, false);       // double sign
+                       iStat += EqnTest(_T("ksdfj"), 0, false);     // unknown token
+                       iStat += EqnTest(_T("()"), 0, false);        // empty bracket without a function
+                       iStat += EqnTest(_T("5+()"), 0, false);      // empty bracket without a function
+                       iStat += EqnTest(_T("sin(cos)"), 0, false);  // unexpected function
+                       iStat += EqnTest(_T("5t6"), 0, false);       // unknown token
+                       iStat += EqnTest(_T("5 t 6"), 0, false);     // unknown token
+                       iStat += EqnTest(_T("8*"), 0, false);        // unexpected end of formula
+                       iStat += EqnTest(_T(",3"), 0, false);        // unexpected comma
+                       iStat += EqnTest(_T("3,5"), 0, false);       // unexpected comma
+                       iStat += EqnTest(_T("sin(8,8)"), 0, false);  // too many function args
+                       iStat += EqnTest(_T("(7,8)"), 0, false);     // too many function args
+                       iStat += EqnTest(_T("sin)"), 0, false);      // unexpected closing bracket
+                       iStat += EqnTest(_T("a)"), 0, false);        // unexpected closing bracket
+                       iStat += EqnTest(_T("pi)"), 0, false);       // unexpected closing bracket
+                       iStat += EqnTest(_T("sin(())"), 0, false);   // unexpected closing bracket
+                       iStat += EqnTest(_T("sin()"), 0, false);     // unexpected closing bracket
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestVarConst()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing variable/constant detection...");
+
+                       // Test if the result changes when a variable changes
+                       iStat += EqnTestWithVarChange(_T("a"), 1, 1, 2, 2);
+                       iStat += EqnTestWithVarChange(_T("2*a"), 2, 4, 3, 6);
+
+                       // distinguish constants with same basename
+                       iStat += EqnTest(_T("const"), 1, true);
+                       iStat += EqnTest(_T("const1"), 2, true);
+                       iStat += EqnTest(_T("const2"), 3, true);
+                       iStat += EqnTest(_T("2*const"), 2, true);
+                       iStat += EqnTest(_T("2*const1"), 4, true);
+                       iStat += EqnTest(_T("2*const2"), 6, true);
+                       iStat += EqnTest(_T("2*const+1"), 3, true);
+                       iStat += EqnTest(_T("2*const1+1"), 5, true);
+                       iStat += EqnTest(_T("2*const2+1"), 7, true);
+                       iStat += EqnTest(_T("const"), 0, false);
+                       iStat += EqnTest(_T("const1"), 0, false);
+                       iStat += EqnTest(_T("const2"), 0, false);
+
+                       // distinguish variables with same basename
+                       iStat += EqnTest(_T("a"), 1, true);
+                       iStat += EqnTest(_T("aa"), 2, true);
+                       iStat += EqnTest(_T("2*a"), 2, true);
+                       iStat += EqnTest(_T("2*aa"), 4, true);
+                       iStat += EqnTest(_T("2*a-1"), 1, true);
+                       iStat += EqnTest(_T("2*aa-1"), 3, true);
+
+                       // custom value recognition
+                       iStat += EqnTest(_T("0xff"), 255, true);
+                       iStat += EqnTest(_T("0x97 + 0xff"), 406, true);
+
+                       // Finally test querying of used variables
+                       try
+                       {
+                               int idx;
+                               mu::Parser p;
+                               mu::value_type vVarVal[] = { 1, 2, 3, 4, 5 };
+                               p.DefineVar(_T("a"), &vVarVal[0]);
+                               p.DefineVar(_T("b"), &vVarVal[1]);
+                               p.DefineVar(_T("c"), &vVarVal[2]);
+                               p.DefineVar(_T("d"), &vVarVal[3]);
+                               p.DefineVar(_T("e"), &vVarVal[4]);
+
+                               // Test lookup of defined variables
+                               // 4 used variables
+                               p.SetExpr(_T("a+b+c+d"));
+                               mu::varmap_type UsedVar = p.GetUsedVar();
+                               int iCount = (int)UsedVar.size();
+                               if (iCount != 4)
+                                       throw false;
+
+                               // the next check will fail if the parser 
+                               // erroneously creates new variables internally
+                               if (p.GetVar().size() != 5)
+                                       throw false;
+
+                               mu::varmap_type::const_iterator item = UsedVar.begin();
+                               for (idx = 0; item != UsedVar.end(); ++item)
+                               {
+                                       if (&vVarVal[idx++] != item->second)
+                                               throw false;
+                               }
+
+                               // Test lookup of undefined variables
+                               p.SetExpr(_T("undef1+undef2+undef3"));
+                               UsedVar = p.GetUsedVar();
+                               iCount = (int)UsedVar.size();
+                               if (iCount != 3)
+                                       throw false;
+
+                               // the next check will fail if the parser 
+                               // erroneously creates new variables internally
+                               if (p.GetVar().size() != 5)
+                                       throw false;
+
+                               for (item = UsedVar.begin(); item != UsedVar.end(); ++item)
+                               {
+                                       if (item->second != 0)
+                                               throw false; // all pointers to undefined variables must be null
+                               }
+
+                               // 1 used variables
+                               p.SetExpr(_T("a+b"));
+                               UsedVar = p.GetUsedVar();
+                               iCount = (int)UsedVar.size();
+                               if (iCount != 2) throw false;
+                               item = UsedVar.begin();
+                               for (idx = 0; item != UsedVar.end(); ++item)
+                                       if (&vVarVal[idx++] != item->second) throw false;
+
+                       }
+                       catch (...)
+                       {
+                               iStat += 1;
+                       }
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestMultiArg()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing multiarg functions...");
+
+                       // from oss-fzz.com: UNKNOWN READ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23330#c1
+                       iStat += ThrowTest(_T("6, +, +, +, +, +, +, +, +, +, +, +, +, +, +, 1, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +"), ecUNEXPECTED_ARG_SEP, true);
+
+                       // misplaced string argument                    
+                       iStat += ThrowTest(_T(R"(sin(0?4:("")))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(avg(0?4:(""),1))"), ecUNEXPECTED_STR);
+
+                       // Compound expressions
+                       iStat += EqnTest(_T("1,2,3"), 3, true);
+                       iStat += EqnTest(_T("a,b,c"), 3, true);
+                       iStat += EqnTest(_T("a=10,b=20,c=a*b"), 200, true);
+                       iStat += EqnTest(_T("1,\n2,\n3"), 3, true);
+                       iStat += EqnTest(_T("a,\nb,\nc"), 3, true);
+                       iStat += EqnTest(_T("a=10,\nb=20,\nc=a*b"), 200, true);
+                       iStat += EqnTest(_T("1,\r\n2,\r\n3"), 3, true);
+                       iStat += EqnTest(_T("a,\r\nb,\r\nc"), 3, true);
+                       iStat += EqnTest(_T("a=10,\r\nb=20,\r\nc=a*b"), 200, true);
+
+                       // picking the right argument
+                       iStat += EqnTest(_T("f1of1(1)"), 1, true);
+                       iStat += EqnTest(_T("f1of2(1, 2)"), 1, true);
+                       iStat += EqnTest(_T("f2of2(1, 2)"), 2, true);
+                       iStat += EqnTest(_T("f1of3(1, 2, 3)"), 1, true);
+                       iStat += EqnTest(_T("f2of3(1, 2, 3)"), 2, true);
+                       iStat += EqnTest(_T("f3of3(1, 2, 3)"), 3, true);
+                       iStat += EqnTest(_T("f1of4(1, 2, 3, 4)"), 1, true);
+                       iStat += EqnTest(_T("f2of4(1, 2, 3, 4)"), 2, true);
+                       iStat += EqnTest(_T("f3of4(1, 2, 3, 4)"), 3, true);
+                       iStat += EqnTest(_T("f4of4(1, 2, 3, 4)"), 4, true);
+                       iStat += EqnTest(_T("f1of5(1, 2, 3, 4, 5)"), 1, true);
+                       iStat += EqnTest(_T("f2of5(1, 2, 3, 4, 5)"), 2, true);
+                       iStat += EqnTest(_T("f3of5(1, 2, 3, 4, 5)"), 3, true);
+                       iStat += EqnTest(_T("f4of5(1, 2, 3, 4, 5)"), 4, true);
+                       iStat += EqnTest(_T("f5of5(1, 2, 3, 4, 5)"), 5, true);
+                       // Too few arguments / Too many arguments
+                       iStat += EqnTest(_T("1+ping()"), 11, true);
+                       iStat += EqnTest(_T("ping()+1"), 11, true);
+                       iStat += EqnTest(_T("2*ping()"), 20, true);
+                       iStat += EqnTest(_T("ping()*2"), 20, true);
+                       iStat += EqnTest(_T("ping(1,2)"), 0, false);
+                       iStat += EqnTest(_T("1+ping(1,2)"), 0, false);
+                       iStat += EqnTest(_T("f1of1(1,2)"), 0, false);
+                       iStat += EqnTest(_T("f1of1()"), 0, false);
+                       iStat += EqnTest(_T("f1of2(1, 2, 3)"), 0, false);
+                       iStat += EqnTest(_T("f1of2(1)"), 0, false);
+                       iStat += EqnTest(_T("f1of3(1, 2, 3, 4)"), 0, false);
+                       iStat += EqnTest(_T("f1of3(1)"), 0, false);
+                       iStat += EqnTest(_T("f1of4(1, 2, 3, 4, 5)"), 0, false);
+                       iStat += EqnTest(_T("f1of4(1)"), 0, false);
+                       iStat += EqnTest(_T("(1,2,3)"), 0, false);
+                       iStat += EqnTest(_T("1,2,3"), 0, false);
+                       iStat += EqnTest(_T("(1*a,2,3)"), 0, false);
+                       iStat += EqnTest(_T("1,2*a,3"), 0, false);
+
+                       // correct calculation of arguments
+                       iStat += EqnTest(_T("min(a, 1)"), 1, true);
+                       iStat += EqnTest(_T("min(3*2, 1)"), 1, true);
+                       iStat += EqnTest(_T("min(3*2, 1)"), 6, false);
+                       iStat += EqnTest(_T("firstArg(2,3,4)"), 2, true);
+                       iStat += EqnTest(_T("lastArg(2,3,4)"), 4, true);
+                       iStat += EqnTest(_T("min(3*a+1, 1)"), 1, true);
+                       iStat += EqnTest(_T("max(3*a+1, 1)"), 4, true);
+                       iStat += EqnTest(_T("max(3*a+1, 1)*2"), 8, true);
+                       iStat += EqnTest(_T("2*max(3*a+1, 1)+2"), 10, true);
+
+                       // functions with Variable argument count
+                       iStat += EqnTest(_T("sum(a)"), 1, true);
+                       iStat += EqnTest(_T("sum(1,2,3)"), 6, true);
+                       iStat += EqnTest(_T("sum(a,b,c)"), 6, true);
+                       iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true);
+                       iStat += EqnTest(_T("2*sum(1,2,3)"), 12, true);
+                       iStat += EqnTest(_T("2*sum(1,2,3)+2"), 14, true);
+                       iStat += EqnTest(_T("2*sum(-1,2,3)+2"), 10, true);
+                       iStat += EqnTest(_T("2*sum(-1,2,-(-a))+2"), 6, true);
+                       iStat += EqnTest(_T("2*sum(-1,10,-a)+2"), 18, true);
+                       iStat += EqnTest(_T("2*sum(1,2,3)*2"), 24, true);
+                       iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true);
+                       iStat += EqnTest(_T("sum(1*3, 4, a+2)"), 10, true);
+                       iStat += EqnTest(_T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true);
+                       iStat += EqnTest(_T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);
+
+                       // some failures
+                       iStat += EqnTest(_T("sum()"), 0, false);
+                       iStat += EqnTest(_T("sum(,)"), 0, false);
+                       iStat += EqnTest(_T("sum(1,2,)"), 0, false);
+                       iStat += EqnTest(_T("sum(,1,2)"), 0, false);
+
+                       // user data
+                       iStat += EqnTest(_T("funud0_8()"), 8, true);
+                       iStat += EqnTest(_T("funud1_16(10)"), 26, true);
+                       iStat += EqnTest(_T("funud2_24(10, 100)"), 134, true);
+                       iStat += EqnTest(_T("funud10_32(1,2,3,4,5,6,7,8,9,10)"), 87, true);
+                       iStat += EqnTest(_T("funud0_9()"), 9, true);
+                       iStat += EqnTest(_T("funud1_17(10)"), 27, true);
+                       iStat += EqnTest(_T("funud2_25(10, 100)"), 135, true);
+                       iStat += EqnTest(_T("funud10_33(1,2,3,4,5,6,7,8,9,10)"), 88, true);
+                       iStat += EqnTest(_T("sumud_100(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 124, true);
+                       iStat += EqnTest(_T("sumud_100()"), 0, false);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestInfixOprt()
+               {
+                       int iStat(0);
+                       mu::console() << "testing infix operators...";
+
+                       iStat += EqnTest(_T("+1"), +1, true);
+                       iStat += EqnTest(_T("-(+1)"), -1, true);
+                       iStat += EqnTest(_T("-(+1)*2"), -2, true);
+                       iStat += EqnTest(_T("-(+2)*sqrt(4)"), -4, true);
+                       iStat += EqnTest(_T("3-+a"), 2, true);
+                       iStat += EqnTest(_T("+1*3"), 3, true);
+
+                       iStat += EqnTest(_T("-1"), -1, true);
+                       iStat += EqnTest(_T("-(-1)"), 1, true);
+                       iStat += EqnTest(_T("-(-1)*2"), 2, true);
+                       iStat += EqnTest(_T("-(-2)*sqrt(4)"), 4, true);
+                       iStat += EqnTest(_T("-_pi"), -MathImpl<double>::CONST_PI, true);
+                       iStat += EqnTest(_T("-a"), -1, true);
+                       iStat += EqnTest(_T("-(a)"), -1, true);
+                       iStat += EqnTest(_T("-(-a)"), 1, true);
+                       iStat += EqnTest(_T("-(-a)*2"), 2, true);
+                       iStat += EqnTest(_T("-(8)"), -8, true);
+                       iStat += EqnTest(_T("-8"), -8, true);
+                       iStat += EqnTest(_T("-(2+1)"), -3, true);
+                       iStat += EqnTest(_T("-(f1of1(1+2*3)+1*2)"), -9, true);
+                       iStat += EqnTest(_T("-(-f1of1(1+2*3)+1*2)"), 5, true);
+                       iStat += EqnTest(_T("-sin(8)"), -0.989358, true);
+                       iStat += EqnTest(_T("3-(-a)"), 4, true);
+                       iStat += EqnTest(_T("3--a"), 4, true);
+                       iStat += EqnTest(_T("-1*3"), -3, true);
+
+                       // Postfix / infix priorities
+                       iStat += EqnTest(_T("~2#"), 8, true);
+                       iStat += EqnTest(_T("~f1of1(2)#"), 8, true);
+                       iStat += EqnTest(_T("~(b)#"), 8, true);
+                       iStat += EqnTest(_T("(~b)#"), 12, true);
+                       iStat += EqnTest(_T("~(2#)"), 8, true);
+                       iStat += EqnTest(_T("~(f1of1(2)#)"), 8, true);
+                       //
+                       iStat += EqnTest(_T("-2^2"), -4, true);
+                       iStat += EqnTest(_T("-(a+b)^2"), -9, true);
+                       iStat += EqnTest(_T("(-3)^2"), 9, true);
+                       iStat += EqnTest(_T("-(-2^2)"), 4, true);
+                       iStat += EqnTest(_T("3+-3^2"), -6, true);
+                       // The following assumes use of sqr as postfix operator together
+                       // with a sign operator of low priority:
+                       iStat += EqnTest(_T("-2'"), -4, true);
+                       iStat += EqnTest(_T("-(1+1)'"), -4, true);
+                       iStat += EqnTest(_T("2+-(1+1)'"), -2, true);
+                       iStat += EqnTest(_T("2+-2'"), -2, true);
+                       // This is the classic behaviour of the infix sign operator (here: "$") which is
+                       // now deprecated:
+                       iStat += EqnTest(_T("$2^2"), 4, true);
+                       iStat += EqnTest(_T("$(a+b)^2"), 9, true);
+                       iStat += EqnTest(_T("($3)^2"), 9, true);
+                       iStat += EqnTest(_T("$($2^2)"), -4, true);
+                       iStat += EqnTest(_T("3+$3^2"), 12, true);
+
+                       // infix operators sharing the first few characters
+                       iStat += EqnTest(_T("~ 123"), (value_type)123.0 + 2, true);
+                       iStat += EqnTest(_T("~~ 123"), (value_type)123.0 + 2, true);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestPostFix()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing postfix operators...");
+
+                       // application
+                       iStat += EqnTest(_T("3{m}+5"), 5.003, true);
+                       iStat += EqnTest(_T("1000{m}"), 1, true);
+                       iStat += EqnTest(_T("1000 {m}"), 1, true);
+                       iStat += EqnTest(_T("(a){m}"), 1e-3, true);
+                       iStat += EqnTest(_T("a{m}"), 1e-3, true);
+                       iStat += EqnTest(_T("a {m}"), 1e-3, true);
+                       iStat += EqnTest(_T("-(a){m}"), -1e-3, true);
+                       iStat += EqnTest(_T("-2{m}"), -2e-3, true);
+                       iStat += EqnTest(_T("-2 {m}"), -2e-3, true);
+                       iStat += EqnTest(_T("f1of1(1000){m}"), 1, true);
+                       iStat += EqnTest(_T("-f1of1(1000){m}"), -1, true);
+                       iStat += EqnTest(_T("-f1of1(-1000){m}"), 1, true);
+                       iStat += EqnTest(_T("f4of4(0,0,0,1000){m}"), 1, true);
+                       iStat += EqnTest(_T("2+(a*1000){m}"), 3, true);
+
+                       // can postfix operators "m" und "meg" be told apart properly?
+                       iStat += EqnTest(_T("2*3000meg+2"), 2 * 3e9 + 2, true);
+
+                       // some incorrect results
+                       iStat += EqnTest(_T("1000{m}"), 0.1, false);
+                       iStat += EqnTest(_T("(a){m}"), 2, false);
+                       // failure due to syntax checking
+                       iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN);  // incomplete hex definition
+                       iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);
+                       iStat += ThrowTest(_T("4 + {m}"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("{m}4"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("sin({m})"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("{m} {m}"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("{m}(8)"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("4,{m}"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("-{m}"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("2(-{m})"), ecUNEXPECTED_PARENS);
+                       iStat += ThrowTest(_T("2({m})"), ecUNEXPECTED_PARENS);
+
+                       iStat += ThrowTest(_T("multi*1.0"), ecUNASSIGNABLE_TOKEN);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestExpression()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing expression samples...");
+
+                       value_type b = 2;
+
+                       iStat += EqnTest(_T("f0()"), 42, true);
+                       iStat += EqnTest(_T("b^2"), 4, true);
+                       iStat += EqnTest(_T("b^1"), 2, true);
+                       iStat += EqnTest(_T("b^0"), 1, true);
+                       iStat += EqnTest(_T("b^-1"), 0.5, true);
+
+                       // Optimization
+                       iStat += EqnTest(_T("2*b*5"), 20, true);
+                       iStat += EqnTest(_T("2*b*5 + 4*b"), 28, true);
+                       iStat += EqnTest(_T("2*a/3"), 2.0 / 3.0, true);
+
+                       // Addition auf cmVARMUL 
+                       iStat += EqnTest(_T("3+b"), b + 3, true);
+                       iStat += EqnTest(_T("b+3"), b + 3, true);
+                       iStat += EqnTest(_T("b*3+2"), b * 3 + 2, true);
+                       iStat += EqnTest(_T("3*b+2"), b * 3 + 2, true);
+                       iStat += EqnTest(_T("2+b*3"), b * 3 + 2, true);
+                       iStat += EqnTest(_T("2+3*b"), b * 3 + 2, true);
+                       iStat += EqnTest(_T("b+3*b"), b + 3 * b, true);
+                       iStat += EqnTest(_T("3*b+b"), b + 3 * b, true);
+
+                       iStat += EqnTest(_T("2+b*3+b"), 2 + b * 3 + b, true);
+                       iStat += EqnTest(_T("b+2+b*3"), b + 2 + b * 3, true);
+
+                       iStat += EqnTest(_T("(2*b+1)*4"), (2 * b + 1) * 4, true);
+                       iStat += EqnTest(_T("4*(2*b+1)"), (2 * b + 1) * 4, true);
+
+                       // operator precedences
+                       iStat += EqnTest(_T("1+2-3*4/5^6"), 2.99923, true);
+                       iStat += EqnTest(_T("1^2/3*4-5+6"), 2.33333333, true);
+                       iStat += EqnTest(_T("1+2*3"), 7, true);
+                       iStat += EqnTest(_T("1+2*3"), 7, true);
+                       iStat += EqnTest(_T("(1+2)*3"), 9, true);
+                       iStat += EqnTest(_T("(1+2)*(-3)"), -9, true);
+                       iStat += EqnTest(_T("2/4"), 0.5, true);
+
+                       iStat += EqnTest(_T("exp(ln(7))"), 7, true);
+                       iStat += EqnTest(_T("e^ln(7)"), 7, true);
+                       iStat += EqnTest(_T("e^(ln(7))"), 7, true);
+                       iStat += EqnTest(_T("(e^(ln(7)))"), 7, true);
+                       iStat += EqnTest(_T("1-(e^(ln(7)))"), -6, true);
+                       iStat += EqnTest(_T("2*(e^(ln(7)))"), 14, true);
+                       iStat += EqnTest(_T("10^log(5)"), pow(10.0, log(5.0)), true);
+                       iStat += EqnTest(_T("10^log10(5)"), 5, true);
+                       iStat += EqnTest(_T("2^log2(4)"), 4, true);
+                       iStat += EqnTest(_T("-(sin(0)+1)"), -1, true);
+                       iStat += EqnTest(_T("-(2^1.1)"), -2.14354692, true);
+
+                       iStat += EqnTest(_T("(cos(2.41)/b)"), -0.372056, true);
+                       iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true);
+                       iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true);
+                       iStat += EqnTest(_T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true);
+
+                       // long formula (Reference: Matlab)
+                       iStat += EqnTest(
+                               _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")
+                               _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")
+                               _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")
+                               _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")
+                               _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")
+                               _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true);
+
+                       // long formula (Reference: Matlab)
+                       iStat += EqnTest(
+                               _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e")
+                               _T(")+a)))*2.77)"), -2.16995656, true);
+
+                       // long formula (Reference: Matlab)
+                       iStat += EqnTest(_T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestIfThenElse()
+               {
+                       int iStat = 0;
+                       mu::console() << _T("testing if-then-else operator...");
+
+                       // from oss-fuzz.com: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24167
+                       iStat += ThrowTest(_T(R"(0^3^avg(0>3?4:(""),0^3?4:("")))"), ecUNEXPECTED_STR);
+                       // derivatives
+                       iStat += ThrowTest(_T(R"(avg(0?(""):4,1))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(avg(0>3?4:(""),0^3?4:("")))"), ecUNEXPECTED_STR);
+
+                       iStat += ThrowTest(_T(R"(0?4:(""))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"((0)?4:(""))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"((0>3)?4:(""))"), ecUNEXPECTED_STR);
+                       iStat += ThrowTest(_T(R"(0>3?4:(""))"), ecUNEXPECTED_STR);
+
+                       // from oss-fuzz.com: https://oss-fuzz.com/testcase-detail/4777121158529024
+                       iStat += ThrowTest(_T("3!=min(0?2>2,2>5,1:6)"), ecUNEXPECTED_ARG_SEP);
+
+                       // Test error detection
+                       iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL);
+                       iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL);
+                       iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE);
+                       iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE);
+                       iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE);
+                       iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE);
+                       iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON);
+                       iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON);
+                       iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON);
+                       iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN);
+
+                       // from oss-fzz.com: UNKNOWN READ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22922#c1
+                       iStat += ThrowTest(_T("1?2:0?(7:1)"), ecMISPLACED_COLON);
+
+                       // from oss-fuzz.com: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22938
+                       iStat += ThrowTest(_T("sum(0?1,0,0:3)"), ecUNEXPECTED_ARG_SEP);
+                       iStat += ThrowTest(_T("sum(0?(1,0,0):3)"), ecUNEXPECTED_ARG);
+                       iStat += ThrowTest(_T("sum(2>3?2,4,2:4)"), ecUNEXPECTED_ARG_SEP);
+                       iStat += ThrowTest(_T("sum(2>3?2,4,sin(2):4)"), ecUNEXPECTED_ARG_SEP);
+                       iStat += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_ARG_SEP);
+                       iStat += ThrowTest(_T("sum(2>3?sin(a),4,2:4)"), ecUNEXPECTED_ARG_SEP);
+                       iStat += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_ARG_SEP);
+
+                       iStat += EqnTest(_T("1 ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true);
+                       iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true);
+                       iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true);
+                       iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true);
+                       iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true);
+                       iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true);
+                       iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);
+                       iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);
+                       iStat += EqnTest(_T("(a<b) ? c : d"), 3, true);
+                       iStat += EqnTest(_T("(a>b) ? c : d"), -2, true);
+
+                       iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true);
+                       iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true);
+                       iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);
+                       iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);
+
+                       iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);
+                       iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true);
+                       iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);
+                       iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true);
+                       iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);
+                       iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);
+                       iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);
+                       iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);
+                       iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);
+                       iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+                       iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);
+                       iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);
+                       iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);
+                       iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);
+                       iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+
+                       // todo: also add for muParserX!
+                       iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);
+                       iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);
+                       iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);
+                       iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);
+                       iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);
+
+                       iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);
+                       iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);
+                       iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);
+                       iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);
+                       iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);
+                       iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);
+                       iStat += EqnTest(_T("1>0 ? 50 :  1>0 ? 128 : 255"), 50, true);
+                       iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);
+                       iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);
+                       iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);
+                       iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);
+                       iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :  1>0 ? 32 :1>2 ? 64 : 16"), 255, true);
+                       iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);
+                       iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true);
+
+                       // assignment operators
+                       iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true);
+                       iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);
+                       iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);
+                       iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true);
+                       iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true);
+                       iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true);
+                       iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true);  // a should not change its value due to lazy calculation
+
+                       iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true);
+                       iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true);
+                       iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true);
+                       iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true);
+
+                       iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true);
+                       iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true);
+                       iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true);
+                       iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::TestException()
+               {
+                       int  iStat = 0;
+                       mu::console() << _T("testing error codes...");
+
+                       iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);
+                       iStat += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS);
+                       iStat += ThrowTest(_T("()"), ecUNEXPECTED_PARENS);
+                       iStat += ThrowTest(_T("3+()"), ecUNEXPECTED_PARENS);
+                       iStat += ThrowTest(_T("sin(3,4)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS);
+                       iStat += ThrowTest(_T("(1+2"), ecMISSING_PARENS);
+                       iStat += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL);
+                       iStat += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN);
+                       iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);
+                       iStat += ThrowTest(_T("a+b+c=10"), ecUNEXPECTED_OPERATOR);
+                       iStat += ThrowTest(_T("a=b=3"), ecUNEXPECTED_OPERATOR);
+
+                       // functions without parameter
+                       iStat += ThrowTest(_T("3+ping(2)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("3+ping(a+2)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("3+ping(sin(a)+2)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("3+ping(1+sin(a))"), ecTOO_MANY_PARAMS);
+
+                       // String function related
+                       iStat += ThrowTest(_T("valueof(\"xxx\")"), 999, false);
+                       iStat += ThrowTest(_T("valueof()"), ecUNEXPECTED_PARENS);
+                       iStat += ThrowTest(_T("1+valueof(\"abc\""), ecMISSING_PARENS);
+                       iStat += ThrowTest(_T("valueof(\"abc\""), ecMISSING_PARENS);
+                       iStat += ThrowTest(_T("valueof(\"abc"), ecUNTERMINATED_STRING);
+                       iStat += ThrowTest(_T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("valueof(3)"), ecSTRING_EXPECTED);
+                       iStat += ThrowTest(_T("sin(\"abc\")"), ecVAL_EXPECTED);
+                       iStat += ThrowTest(_T("valueof(\"\\\"abc\\\"\")"), 999, false);
+                       iStat += ThrowTest(_T("\"hello world\""), ecSTR_RESULT);
+                       iStat += ThrowTest(_T("(\"hello world\")"), ecSTR_RESULT);
+                       iStat += ThrowTest(_T("\"abcd\"+100"), ecSTR_RESULT);
+                       iStat += ThrowTest(_T("\"a\"+\"b\""), ecSTR_RESULT);
+                       iStat += ThrowTest(_T("strfun1(\"100\",3)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("strfun2(\"100\",3,5)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("strfun2(\"100\")"), ecTOO_FEW_PARAMS);
+                       iStat += ThrowTest(_T("strfun3(\"100\",6)"), ecTOO_FEW_PARAMS);
+                       iStat += ThrowTest(_T("strfun2(1,1)"), ecSTRING_EXPECTED);
+                       iStat += ThrowTest(_T("strfun2(a,1)"), ecSTRING_EXPECTED);
+                       iStat += ThrowTest(_T("strfun2(1,1,1)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("strfun2(a,1,1)"), ecTOO_MANY_PARAMS);
+                       iStat += ThrowTest(_T("strfun3(1,2,3)"), ecSTRING_EXPECTED);
+                       iStat += ThrowTest(_T("strfun3(1, \"100\",3)"), ecSTRING_EXPECTED);
+                       iStat += ThrowTest(_T("strfun3(\"1\", \"100\",3)"), ecVAL_EXPECTED);
+                       iStat += ThrowTest(_T("strfun3(\"1\", 3, \"100\")"), ecVAL_EXPECTED);
+                       iStat += ThrowTest(_T("strfun3(\"1\", \"100\", \"100\", \"100\")"), ecTOO_MANY_PARAMS);
+
+                       // assignment operator
+                       iStat += ThrowTest(_T("3=4"), ecUNEXPECTED_OPERATOR);
+                       iStat += ThrowTest(_T("sin(8)=4"), ecUNEXPECTED_OPERATOR);
+                       iStat += ThrowTest(_T("\"test\"=a"), ecSTR_RESULT);
+
+                       // <ibg 20090529>
+                       // this is now legal, for reference see:
+                       // https://sourceforge.net/forum/message.php?msg_id=7411373
+                       //      iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR);    
+                       // </ibg>
+
+                       iStat += ThrowTest(_T("(8)=5"), ecUNEXPECTED_OPERATOR);
+                       iStat += ThrowTest(_T("(a)=5"), ecUNEXPECTED_OPERATOR);
+                       iStat += ThrowTest(_T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);
+
+                       if (iStat == 0)
+                               mu::console() << _T("passed") << endl;
+                       else
+                               mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+                       return iStat;
+               }
+
+
+               //---------------------------------------------------------------------------
+               void ParserTester::AddTest(testfun_type a_pFun)
+               {
+                       m_vTestFun.push_back(a_pFun);
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::Run()
+               {
+                       int iStat = 0;
+                       try
+                       {
+                               for (int i = 0; i < (int)m_vTestFun.size(); ++i)
+                                       iStat += (this->*m_vTestFun[i])();
+                       }
+                       catch (Parser::exception_type& e)
+                       {
+                               mu::console() << "\n" << e.GetMsg() << endl;
+                               mu::console() << e.GetToken() << endl;
+                               Abort();
+                       }
+                       catch (std::exception& e)
+                       {
+                               mu::console() << e.what() << endl;
+                               Abort();
+                       }
+                       catch (...)
+                       {
+                               mu::console() << "Internal error";
+                               Abort();
+                       }
+
+                       if (iStat == 0)
+                       {
+                               mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl;
+                       }
+                       else
+                       {
+                               mu::console() << "Test failed with " << iStat
+                                       << " errors (" << ParserTester::c_iCount
+                                       << " expressions)" << endl;
+                       }
+                       ParserTester::c_iCount = 0;
+                       return iStat;
+               }
+
+
+               //---------------------------------------------------------------------------
+               int ParserTester::ThrowTest(const string_type& a_str, int a_iErrc, bool a_expectedToFail)
+               {
+                       ParserTester::c_iCount++;
+
+                       try
+                       {
+                               value_type fVal[] = { 1,1,1 };
+                               Parser p;
+
+                               p.DefineVar(_T("a"), &fVal[0]);
+                               p.DefineVar(_T("b"), &fVal[1]);
+                               p.DefineVar(_T("c"), &fVal[2]);
+                               p.DefinePostfixOprt(_T("{m}"), Milli);
+                               p.DefinePostfixOprt(_T("m"), Milli);
+                               p.DefineFun(_T("ping"), Ping);
+                               p.DefineFun(_T("valueof"), ValueOf);
+                               p.DefineFun(_T("strfun1"), StrFun1);
+                               p.DefineFun(_T("strfun2"), StrFun2);
+                               p.DefineFun(_T("strfun3"), StrFun3);
+                               p.DefineFun(_T("strfun4"), StrFun4);
+                               p.DefineFun(_T("strfun5"), StrFun5);
+                               p.DefineFun(_T("strfun6"), StrFun6);
+                               p.SetExpr(a_str);
+                               //                              p.EnableDebugDump(1, 0);
+                               p.Eval();
+                       }
+                       catch (ParserError& e)
+                       {
+                               // output the formula in case of an failed test
+                               if (a_expectedToFail == false || (a_expectedToFail == true && a_iErrc != e.GetCode()))
+                               {
+                                       mu::console() << _T("\n  ")
+                                               << _T("Expression: ") << a_str
+                                               << _T("  Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")")
+                                               << _T("  Expected:") << a_iErrc;
+                               }
+
+                               return (a_iErrc == e.GetCode()) ? 0 : 1;
+                       }
+
+                       // if a_expectedToFail == false no exception is expected
+                       bool bRet((a_expectedToFail == false) ? 0 : 1);
+                       if (bRet == 1)
+                       {
+                               mu::console() << _T("\n  ")
+                                       << _T("Expression: ") << a_str
+                                       << _T("  did evaluate; Expected error:") << a_iErrc;
+                       }
+
+                       return bRet;
+               }
+
+               //---------------------------------------------------------------------------
+               /** \brief Evaluate a tet expression.
+
+                       \return 1 in case of a failure, 0 otherwise.
+               */
+               int ParserTester::EqnTestWithVarChange(const string_type& a_str,
+                       double a_fVar1,
+                       double a_fRes1,
+                       double a_fVar2,
+                       double a_fRes2)
+               {
+                       ParserTester::c_iCount++;
+
+                       try
+                       {
+                               value_type fVal[2] = { -999, -999 }; // should be equal
+
+                               Parser  p;
+                               value_type var = 0;
+
+                               // variable
+                               p.DefineVar(_T("a"), &var);
+                               p.SetExpr(a_str);
+
+                               var = a_fVar1;
+                               fVal[0] = p.Eval();
+
+                               var = a_fVar2;
+                               fVal[1] = p.Eval();
+
+                               if (fabs(a_fRes1 - fVal[0]) > 0.0000000001)
+                                       throw std::runtime_error("incorrect result (first pass)");
+
+                               if (fabs(a_fRes2 - fVal[1]) > 0.0000000001)
+                                       throw std::runtime_error("incorrect result (second pass)");
+                       }
+                       catch (Parser::exception_type& e)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");
+                               return 1;
+                       }
+                       catch (std::exception& e)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");
+                               return 1;  // always return a failure since this exception is not expected
+                       }
+                       catch (...)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+                               return 1;  // exceptions other than ParserException are not allowed
+                       }
+
+                       return 0;
+               }
+
+               //---------------------------------------------------------------------------
+               /** \brief Evaluate a tet expression.
+
+                       \return 1 in case of a failure, 0 otherwise.
+               */
+               int ParserTester::EqnTest(const string_type& a_str, double a_fRes, bool a_fPass)
+               {
+                       ParserTester::c_iCount++;
+                       int iRet(0);
+                       value_type fVal[6] = { -999, -998, -997, -996, -995, -994 }; // initially should be different
+
+                       try
+                       {
+                               std::unique_ptr<Parser> p1;
+                               Parser  p2, p3;   // three parser objects
+                                                                 // they will be used for testing copy and assignment operators
+                               // p1 is a pointer since i'm going to delete it in order to test if
+                               // parsers after copy construction still refer to members of it.
+                               // !! If this is the case this function will crash !!
+
+                               p1.reset(new mu::Parser());
+                               // Add constants
+                               p1->DefineConst(_T("pi"), MathImpl<value_type>::CONST_PI);
+                               p1->DefineConst(_T("e"), MathImpl<value_type>::CONST_E);
+                               p1->DefineConst(_T("const"), 1);
+                               p1->DefineConst(_T("const1"), 2);
+                               p1->DefineConst(_T("const2"), 3);
+                               // string constants
+                               p1->DefineStrConst(_T("str1"), _T("1.11"));
+                               p1->DefineStrConst(_T("str2"), _T("2.22"));
+                               // variables
+                               value_type vVarVal[] = { 1, 2, 3, -2 };
+                               p1->DefineVar(_T("a"), &vVarVal[0]);
+                               p1->DefineVar(_T("aa"), &vVarVal[1]);
+                               p1->DefineVar(_T("b"), &vVarVal[1]);
+                               p1->DefineVar(_T("c"), &vVarVal[2]);
+                               p1->DefineVar(_T("d"), &vVarVal[3]);
+
+                               // custom value ident functions
+                               p1->AddValIdent(&ParserTester::IsHexVal);
+
+                               // functions
+                               p1->DefineFun(_T("ping"), Ping);
+                               p1->DefineFun(_T("f0"), f0);        // no parameter
+                               p1->DefineFun(_T("f1of1"), f1of1);  // one parameter
+                               p1->DefineFun(_T("f1of2"), f1of2);  // two parameter
+                               p1->DefineFun(_T("f2of2"), f2of2);
+                               p1->DefineFun(_T("f1of3"), f1of3);  // three parameter
+                               p1->DefineFun(_T("f2of3"), f2of3);
+                               p1->DefineFun(_T("f3of3"), f3of3);
+                               p1->DefineFun(_T("f1of4"), f1of4);  // four parameter
+                               p1->DefineFun(_T("f2of4"), f2of4);
+                               p1->DefineFun(_T("f3of4"), f3of4);
+                               p1->DefineFun(_T("f4of4"), f4of4);
+                               p1->DefineFun(_T("f1of5"), f1of5);  // five parameter
+                               p1->DefineFun(_T("f2of5"), f2of5);
+                               p1->DefineFun(_T("f3of5"), f3of5);
+                               p1->DefineFun(_T("f4of5"), f4of5);
+                               p1->DefineFun(_T("f5of5"), f5of5);
+
+                               // binary operators
+                               p1->DefineOprt(_T("add"), add, 0);
+                               p1->DefineOprt(_T("++"), add, 0);
+                               p1->DefineOprt(_T("&"), land, prLAND);
+
+                               // sample functions
+                               p1->DefineFun(_T("min"), Min);
+                               p1->DefineFun(_T("max"), Max);
+                               p1->DefineFun(_T("sum"), Sum);
+                               p1->DefineFun(_T("valueof"), ValueOf);
+                               p1->DefineFun(_T("atof"), StrToFloat);
+                               p1->DefineFun(_T("strfun1"), StrFun1);
+                               p1->DefineFun(_T("strfun2"), StrFun2);
+                               p1->DefineFun(_T("strfun3"), StrFun3);
+                               p1->DefineFun(_T("strfun4"), StrFun4);
+                               p1->DefineFun(_T("strfun5"), StrFun5);
+                               p1->DefineFun(_T("strfun6"), StrFun6);
+                               p1->DefineFun(_T("lastArg"), LastArg);
+                               p1->DefineFun(_T("firstArg"), FirstArg);
+                               p1->DefineFun(_T("order"), FirstArg);
+
+                               // functions with user data
+                               p1->DefineFunUserData(_T("funud0_8"), FunUd0, reinterpret_cast<void*>(8));
+                               p1->DefineFunUserData(_T("funud1_16"), FunUd1, reinterpret_cast<void*>(16));
+                               p1->DefineFunUserData(_T("funud2_24"), FunUd2, reinterpret_cast<void*>(24));
+                               p1->DefineFunUserData(_T("funud10_32"), FunUd10, reinterpret_cast<void*>(32));
+                               p1->DefineFunUserData(_T("funud0_9"), FunUd0, reinterpret_cast<void*>(9));
+                               p1->DefineFunUserData(_T("funud1_17"), FunUd1, reinterpret_cast<void*>(17));
+                               p1->DefineFunUserData(_T("funud2_25"), FunUd2, reinterpret_cast<void*>(25));
+                               p1->DefineFunUserData(_T("funud10_33"), FunUd10, reinterpret_cast<void*>(33));
+                               p1->DefineFunUserData(_T("strfunud3_10"), StrFunUd3, reinterpret_cast<void*>(10));
+                               p1->DefineFunUserData(_T("sumud_100"), SumUd, reinterpret_cast<void*>(100));
+
+                               // infix / postfix operator
+                               // Note: Identifiers used here do not have any meaning 
+                               //       they are mere placeholders to test certain features.
+                               p1->DefineInfixOprt(_T("$"), sign, prPOW + 1);  // sign with high priority
+                               p1->DefineInfixOprt(_T("~"), plus2);          // high priority
+                               p1->DefineInfixOprt(_T("~~"), plus2);
+                               p1->DefinePostfixOprt(_T("{m}"), Milli);
+                               p1->DefinePostfixOprt(_T("{M}"), Mega);
+                               p1->DefinePostfixOprt(_T("m"), Milli);
+                               p1->DefinePostfixOprt(_T("meg"), Mega);
+                               p1->DefinePostfixOprt(_T("#"), times3);
+                               p1->DefinePostfixOprt(_T("'"), sqr);
+                               p1->SetExpr(a_str);
+
+                               // Test bytecode integrity
+                               // String parsing and bytecode parsing must yield the same result
+                               fVal[0] = p1->Eval(); // result from stringparsing
+                               fVal[1] = p1->Eval(); // result from bytecode
+                               if (fVal[0] != fVal[1])
+                                       throw Parser::exception_type(_T("Bytecode / string parsing mismatch."));
+
+                               // Test copy and assignment operators
+                               try
+                               {
+                                       // Test copy constructor
+                                       std::vector<mu::Parser> vParser;
+                                       vParser.push_back(*(p1.get()));
+                                       mu::Parser p4 = vParser[0];   // take parser from vector
+
+                                       // destroy the originals from p2
+                                       vParser.clear();              // delete the vector
+                                       p1.reset(nullptr);
+
+                                       fVal[2] = p4.Eval();
+
+                                       // Test assignment operator
+                                       // additionally  disable Optimizer this time
+                                       mu::Parser p5;
+                                       p5 = p4;
+                                       p5.EnableOptimizer(false);
+                                       fVal[3] = p5.Eval();
+
+                                       // Test Eval function for multiple return values
+                                       // use p2 since it has the optimizer enabled!
+                                       int nNum;
+                                       p4.SetExpr(a_str); // reset bytecode to trigger #94 (https://github.com/beltoforion/muparser/issues/94)
+                                       value_type* v = p4.Eval(nNum);
+                                       fVal[4] = v[nNum - 1];
+
+                                       v = p4.Eval(nNum);
+                                       fVal[5] = v[nNum - 1];
+
+                               }
+                               catch (std::exception& e)
+                               {
+                                       mu::console() << _T("\n  ") << e.what() << _T("\n");
+                               }
+
+                               // limited floating point accuracy requires the following test
+                               bool bCloseEnough(true);
+                               for (unsigned i = 0; i < sizeof(fVal) / sizeof(value_type); ++i)
+                               {
+                                       bCloseEnough &= (fabs(a_fRes - fVal[i]) <= fabs(fVal[i] * 0.00001));
+
+                                       // The tests equations never result in infinity, if they do thats a bug.
+                                       // reference:
+                                       // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+                                       if (std::numeric_limits<value_type>::has_infinity)
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+                                       {
+                                               bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity());
+                                       }
+                               }
+
+                               iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
+
+
+                               if (iRet == 1)
+                               {
+                                       mu::console() << _T("\n  fail: ") << a_str.c_str()
+                                               << _T(" (incorrect result; expected: ") << a_fRes
+                                               << _T(" ;calculated: ") << fVal[0] << _T(",")
+                                               << fVal[1] << _T(",")
+                                               << fVal[2] << _T(",")
+                                               << fVal[3] << _T(",")
+                                               << fVal[4] << _T(",")
+                                               << fVal[5] << _T(").");
+                               }
+                       }
+                       catch (Parser::exception_type& e)
+                       {
+                               if (a_fPass)
+                               {
+                                       if (fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998)
+                                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (copy construction)");
+                                       else
+                                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");
+                                       return 1;
+                               }
+                       }
+                       catch (std::exception& e)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");
+                               return 1;  // always return a failure since this exception is not expected
+                       }
+                       catch (...)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+                               return 1;  // exceptions other than ParserException are not allowed
+                       }
+
+                       return iRet;
+               }
+
+               //---------------------------------------------------------------------------
+               int ParserTester::EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass)
+               {
+                       ParserTester::c_iCount++;
+
+                       value_type vVarVal[] = { 1, 2, 3 };   // variable values
+                       int iRet(0);
+
+                       try
+                       {
+                               value_type fVal[2] = { -99, -999 };   // results: initially should be different
+                               ParserInt p;
+                               p.DefineConst(_T("const1"), 1);
+                               p.DefineConst(_T("const2"), 2);
+                               p.DefineVar(_T("a"), &vVarVal[0]);
+                               p.DefineVar(_T("b"), &vVarVal[1]);
+                               p.DefineVar(_T("c"), &vVarVal[2]);
+
+                               p.SetExpr(a_str);
+                               fVal[0] = p.Eval(); // result from stringparsing
+                               fVal[1] = p.Eval(); // result from bytecode
+
+                               if (fVal[0] != fVal[1])
+                                       throw Parser::exception_type(_T("Bytecode corrupt."));
+
+                               iRet = ((a_fRes == fVal[0] && a_fPass) ||
+                                       (a_fRes != fVal[0] && !a_fPass)) ? 0 : 1;
+                               if (iRet == 1)
+                               {
+                                       mu::console() << _T("\n  fail: ") << a_str.c_str()
+                                               << _T(" (incorrect result; expected: ") << a_fRes
+                                               << _T(" ;calculated: ") << fVal[0] << _T(").");
+                               }
+                       }
+                       catch (Parser::exception_type& e)
+                       {
+                               if (a_fPass)
+                               {
+                                       mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+                                       iRet = 1;
+                               }
+                       }
+                       catch (...)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+                               iRet = 1;  // exceptions other than ParserException are not allowed
+                       }
+
+                       return iRet;
+               }
+
+               //---------------------------------------------------------------------------
+               /** \brief Test an expression in Bulk Mode. */
+               int ParserTester::EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass)
+               {
+                       ParserTester::c_iCount++;
+
+                       // Define Bulk Variables
+                       int nBulkSize = 4;
+                       value_type vVariableA[] = { 1, 2, 3, 4 };   // variable values
+                       value_type vVariableB[] = { 2, 2, 2, 2 };   // variable values
+                       value_type vVariableC[] = { 3, 3, 3, 3 };   // variable values
+                       value_type vResults[] = { 0, 0, 0, 0 };   // variable values
+                       int iRet(0);
+
+                       try
+                       {
+                               Parser p;
+                               p.DefineConst(_T("const1"), 1);
+                               p.DefineConst(_T("const2"), 2);
+                               p.DefineVar(_T("a"), vVariableA);
+                               p.DefineVar(_T("b"), vVariableB);
+                               p.DefineVar(_T("c"), vVariableC);
+
+                               p.SetExpr(a_str);
+                               p.Eval(vResults, nBulkSize);
+
+                               bool bCloseEnough(true);
+                               for (int i = 0; i < nBulkSize; ++i)
+                               {
+                                       bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001));
+                               }
+
+                               iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
+                               if (iRet == 1)
+                               {
+                                       mu::console() << _T("\n  fail: ") << a_str.c_str()
+                                               << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}")
+                                               << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}");
+                               }
+                       }
+                       catch (Parser::exception_type& e)
+                       {
+                               if (a_fPass)
+                               {
+                                       mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+                                       iRet = 1;
+                               }
+                       }
+                       catch (...)
+                       {
+                               mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+                               iRet = 1;  // exceptions other than ParserException are not allowed
+                       }
+
+                       return iRet;
+               }
+
+               //---------------------------------------------------------------------------
+               /** \brief Internal error in test class Test is going to be aborted. */
+               void ParserTester::Abort() const
+               {
+                       mu::console() << _T("Test failed (internal error in test class)") << endl;
+                       while (!getchar());
+                       exit(-1);
+               }
+       } // namespace test
+} // namespace mu
diff --git a/bundled/muparser_v2_3_3/src/muParserTokenReader.cpp b/bundled/muparser_v2_3_3/src/muParserTokenReader.cpp
new file mode 100644 (file)
index 0000000..312a0c5
--- /dev/null
@@ -0,0 +1,997 @@
+/*
+
+        _____  __ _____________ _______  ______ ___________
+       /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
+   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
+   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
+                \/      |__|       \/           \/     \/
+   Copyright (C) 2004 - 2021 Ingo Berg
+
+       Redistribution and use in source and binary forms, with or without modification, are permitted
+       provided that the following conditions are met:
+
+         * Redistributions of source code must retain the above copyright notice, this list of
+               conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above copyright notice, this list of
+               conditions and the following disclaimer in the documentation and/or other materials provided
+               with the distribution.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+       FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+       IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+       OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <stack>
+#include <string>
+
+#include "muParserTokenReader.h"
+#include "muParserBase.h"
+
+#if defined(_MSC_VER)
+       #pragma warning(push)
+       #pragma warning(disable : 26812) 
+#endif
+
+/** \file
+       \brief This file contains the parser token reader implementation.
+*/
+
+
+namespace mu
+{
+
+       // Forward declaration
+       class ParserBase;
+
+       /** \brief Copy constructor.
+
+               \sa Assign
+               \throw nothrow
+       */
+       ParserTokenReader::ParserTokenReader(const ParserTokenReader& a_Reader)
+       {
+               Assign(a_Reader);
+       }
+
+
+       /** \brief Assignment operator.
+
+               Self assignment will be suppressed otherwise #Assign is called.
+
+               \param a_Reader Object to copy to this token reader.
+               \throw nothrow
+       */
+       ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader& a_Reader)
+       {
+               if (&a_Reader != this)
+                       Assign(a_Reader);
+
+               return *this;
+       }
+
+
+       /** \brief Assign state of a token reader to this token reader.
+
+               \param a_Reader Object from which the state should be copied.
+               \throw nothrow
+       */
+       void ParserTokenReader::Assign(const ParserTokenReader& a_Reader)
+       {
+               m_pParser = a_Reader.m_pParser;
+               m_strFormula = a_Reader.m_strFormula;
+               m_iPos = a_Reader.m_iPos;
+               m_iSynFlags = a_Reader.m_iSynFlags;
+
+               m_UsedVar = a_Reader.m_UsedVar;
+               m_pFunDef = a_Reader.m_pFunDef;
+               m_pConstDef = a_Reader.m_pConstDef;
+               m_pVarDef = a_Reader.m_pVarDef;
+               m_pStrVarDef = a_Reader.m_pStrVarDef;
+               m_pPostOprtDef = a_Reader.m_pPostOprtDef;
+               m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;
+               m_pOprtDef = a_Reader.m_pOprtDef;
+               m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;
+               m_vIdentFun = a_Reader.m_vIdentFun;
+               m_pFactory = a_Reader.m_pFactory;
+               m_pFactoryData = a_Reader.m_pFactoryData;
+               m_bracketStack = a_Reader.m_bracketStack;
+               m_cArgSep = a_Reader.m_cArgSep;
+               m_fZero = a_Reader.m_fZero;
+               m_lastTok = a_Reader.m_lastTok;
+       }
+
+
+       /** \brief Constructor.
+
+               Create a Token reader and bind it to a parser object.
+
+               \pre [assert] a_pParser may not be NULL
+               \post #m_pParser==a_pParser
+               \param a_pParent Parent parser object of the token reader.
+       */
+       ParserTokenReader::ParserTokenReader(ParserBase* a_pParent)
+               :m_pParser(a_pParent)
+               , m_strFormula()
+               , m_iPos(0)
+               , m_iSynFlags(0)
+               , m_bIgnoreUndefVar(false)
+               , m_pFunDef(nullptr)
+               , m_pPostOprtDef(nullptr)
+               , m_pInfixOprtDef(nullptr)
+               , m_pOprtDef(nullptr)
+               , m_pConstDef(nullptr)
+               , m_pStrVarDef(nullptr)
+               , m_pVarDef(nullptr)
+               , m_pFactory(nullptr)
+               , m_pFactoryData(nullptr)
+               , m_vIdentFun()
+               , m_UsedVar()
+               , m_fZero(0)
+               , m_bracketStack()
+               , m_lastTok()
+               , m_cArgSep(',')
+       {
+               MUP_ASSERT(m_pParser != nullptr);
+               SetParent(m_pParser);
+       }
+
+
+       /** \brief Create instance of a ParserTokenReader identical with this
+                               and return its pointer.
+
+               This is a factory method the calling function must take care of the object destruction.
+
+               \return A new ParserTokenReader object.
+               \throw nothrow
+       */
+       ParserTokenReader* ParserTokenReader::Clone(ParserBase* a_pParent) const
+       {
+               std::unique_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
+               ptr->SetParent(a_pParent);
+               return ptr.release();
+       }
+
+
+       ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type& tok)
+       {
+               m_lastTok = tok;
+               return m_lastTok;
+       }
+
+
+       void ParserTokenReader::AddValIdent(identfun_type a_pCallback)
+       {
+               // Use push_front is used to give user defined callbacks a higher priority than
+               // the built in ones. Otherwise reading hex numbers would not work
+               // since the "0" in "0xff" would always be read first making parsing of 
+               // the rest impossible.
+               // reference:
+               // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956
+               m_vIdentFun.push_front(a_pCallback);
+       }
+
+
+       void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void* pUserData)
+       {
+               m_pFactory = a_pFactory;
+               m_pFactoryData = pUserData;
+       }
+
+
+       /** \brief Return the current position of the token reader in the formula string.
+
+               \return #m_iPos
+               \throw nothrow
+       */
+       int ParserTokenReader::GetPos() const
+       {
+               return m_iPos;
+       }
+
+
+       /** \brief Return a reference to the formula.
+
+               \return #m_strFormula
+               \throw nothrow
+       */
+       const string_type& ParserTokenReader::GetExpr() const
+       {
+               return m_strFormula;
+       }
+
+
+       /** \brief Return a map containing the used variables only. */
+       varmap_type& ParserTokenReader::GetUsedVar()
+       {
+               return m_UsedVar;
+       }
+
+
+       /** \brief Initialize the token Reader.
+
+               Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
+               \pre [assert] triggered if a_szFormula==0
+       */
+       void ParserTokenReader::SetFormula(const string_type& a_strFormula)
+       {
+               m_strFormula = a_strFormula;
+               ReInit();
+       }
+
+
+       /** \brief Set Flag that controls behaviour in case of undefined variables being found.
+
+         If true, the parser does not throw an exception if an undefined variable is found.
+         otherwise it does. This variable is used internally only!
+         It suppresses a "undefined variable" exception in GetUsedVar().
+         Those function should return a complete list of variables including
+         those the are not defined by the time of it's call.
+       */
+       void ParserTokenReader::IgnoreUndefVar(bool bIgnore)
+       {
+               m_bIgnoreUndefVar = bIgnore;
+       }
+
+
+       /** \brief Reset the token reader to the start of the formula.
+
+               The syntax flags will be reset to a value appropriate for the
+               start of a formula.
+               \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
+               \throw nothrow
+               \sa ESynCodes
+       */
+       void ParserTokenReader::ReInit()
+       {
+               m_iPos = 0;
+               m_iSynFlags = sfSTART_OF_LINE;
+               m_bracketStack = std::stack<int>();
+               m_UsedVar.clear();
+               m_lastTok = token_type();
+       }
+
+
+       /** \brief Read the next token from the string. */
+       ParserTokenReader::token_type ParserTokenReader::ReadNextToken()
+       {
+               MUP_ASSERT(m_pParser != nullptr);
+
+               const char_type* szExpr = m_strFormula.c_str();
+               token_type tok;
+
+               // Ignore all non printable characters when reading the expression
+               while (szExpr[m_iPos] > 0 && szExpr[m_iPos] <= 0x20)
+               {
+                       // 14-31 are control characters. I donÄt want to have to deal with such strings at all!
+                       // (see https://en.cppreference.com/w/cpp/string/byte/isprint)
+                       if (szExpr[m_iPos] >= 14 && szExpr[m_iPos] <= 31)
+                               Error(ecINVALID_CHARACTERS_FOUND, m_iPos);
+
+                       ++m_iPos;
+               }
+
+               // Check for end of formula
+               if (IsEOF(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for user defined binary operator
+               if (IsOprt(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for function token
+               if (IsFunTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check built in operators / tokens
+               if (IsBuiltIn(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for function argument separators
+               if (IsArgSep(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for values / constant tokens
+               if (IsValTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for variable tokens
+               if (IsVarTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for string variables
+               if (IsStrVarTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for String tokens
+               if (IsString(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for unary operators
+               if (IsInfixOpTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for unary operators
+               if (IsPostOpTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check String for undefined variable token. Done only if a 
+               // flag is set indicating to ignore undefined variables.
+               // This is a way to conditionally avoid an error if 
+               // undefined variables occur. 
+               // (The GetUsedVar function must suppress the error for
+               // undefined variables in order to collect all variable 
+               // names including the undefined ones.)
+               if ((m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok))
+                       return SaveBeforeReturn(tok);
+
+               // Check for unknown token
+               // 
+               // !!! From this point on there is no exit without an exception possible...
+               // 
+               string_type strTok;
+               auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos);
+               if (iEnd != m_iPos)
+                       Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
+
+               Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
+               return token_type(); // never reached
+       }
+
+
+       void ParserTokenReader::SetParent(ParserBase* a_pParent)
+       {
+               m_pParser = a_pParent;
+               m_pFunDef = &a_pParent->m_FunDef;
+               m_pOprtDef = &a_pParent->m_OprtDef;
+               m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
+               m_pPostOprtDef = &a_pParent->m_PostOprtDef;
+               m_pVarDef = &a_pParent->m_VarDef;
+               m_pStrVarDef = &a_pParent->m_StrVarDef;
+               m_pConstDef = &a_pParent->m_ConstDef;
+       }
+
+
+       /** \brief Extract all characters that belong to a certain charset.
+
+               \param a_szCharSet [in] Const char array of the characters allowed in the token.
+               \param a_strTok [out]  The string that consists entirely of characters listed in a_szCharSet.
+               \param a_iPos [in] Position in the string from where to start reading.
+               \return The Position of the first character not listed in a_szCharSet.
+               \throw nothrow
+       */
+       int ParserTokenReader::ExtractToken(const char_type* a_szCharSet, string_type& a_sTok, std::size_t a_iPos) const
+       {
+               auto iEnd = m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
+
+               if (iEnd == string_type::npos)
+                       iEnd = m_strFormula.length();
+
+               // Assign token string if there was something found
+               if (a_iPos != iEnd)
+                       a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
+
+               return static_cast<int>(iEnd);
+       }
+
+
+       /** \brief Check Expression for the presence of a binary operator token.
+
+         Userdefined binary operator "++" gives inconsistent parsing result for
+         the equations "a++b" and "a ++ b" if alphabetic characters are allowed
+         in operator tokens. To avoid this this function checks specifically
+         for operator tokens.
+       */
+       int ParserTokenReader::ExtractOperatorToken(string_type& a_sTok, std::size_t a_iPos) const
+       {
+               // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6
+               auto iEnd = m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos);
+               if (iEnd == string_type::npos)
+                       iEnd = m_strFormula.length();
+
+               // Assign token string if there was something found
+               if (a_iPos != iEnd)
+               {
+                       a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
+                       return static_cast<int>(iEnd);
+               }
+               else
+               {
+                       // There is still the chance of having to deal with an operator consisting exclusively
+                       // of alphabetic characters.
+                       return ExtractToken(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), a_sTok, (std::size_t)a_iPos);
+               }
+       }
+
+
+       /** \brief Check if a built in operator or other token can be found
+               \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+               \return true if an operator token has been found.
+       */
+       bool ParserTokenReader::IsBuiltIn(token_type& a_Tok)
+       {
+               const char_type** const pOprtDef = m_pParser->GetOprtDef(),
+                       * const szFormula = m_strFormula.c_str();
+
+               // Compare token with function and operator strings
+               // check string for operator/function
+               for (int i = 0; pOprtDef[i]; i++)
+               {
+                       std::size_t len(std::char_traits<char_type>::length(pOprtDef[i]));
+                       if (string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len))
+                       {
+                               switch (i)
+                               {
+                               case cmLAND:
+                               case cmLOR:
+                               case cmLT:
+                               case cmGT:
+                               case cmLE:
+                               case cmGE:
+                               case cmNEQ:
+                               case cmEQ:
+                               case cmADD:
+                               case cmSUB:
+                               case cmMUL:
+                               case cmDIV:
+                               case cmPOW:
+                               case cmASSIGN:
+                                       // The assignment operator need special treatment
+                                       if (i == cmASSIGN && m_iSynFlags & noASSIGN)
+                                               Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+
+                                       if (!m_pParser->HasBuiltInOprt()) continue;
+                                       if (m_iSynFlags & noOPT)
+                                       {
+                                               // Maybe its an infix operator not an operator
+                                               // Both operator types can share characters in 
+                                               // their identifiers
+                                               if (IsInfixOpTok(a_Tok))
+                                                       return true;
+
+                                               Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+                                       }
+
+                                       m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND;
+                                       break;
+
+                               case cmBO:
+                                       if (m_iSynFlags & noBO)
+                                               Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+
+                                       if (m_lastTok.GetCode() == cmFUNC)
+                                               m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
+                                       else
+                                               m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
+
+                                       m_bracketStack.push(cmBO);
+                                       break;
+
+                               case cmBC:
+                                       if (m_iSynFlags & noBC)
+                                               Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+
+                                       m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
+
+                                       if (!m_bracketStack.empty())
+                                               m_bracketStack.pop();
+                                       else
+                                               Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+                                       break;
+
+                               case cmELSE:
+                                       if (m_iSynFlags & noELSE)
+                                               Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
+
+                                       m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR;
+                                       break;
+
+                               case cmIF:
+                                       if (m_iSynFlags & noIF)
+                                               Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
+
+                                       m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR;
+                                       break;
+
+                               default:      // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
+                                       Error(ecINTERNAL_ERROR);
+                               } // switch operator id
+
+                               m_iPos += (int)len;
+                               a_Tok.Set((ECmdCode)i, pOprtDef[i]);
+                               return true;
+                       } // if operator string found
+               } // end of for all operator strings
+
+               return false;
+       }
+
+
+       bool ParserTokenReader::IsArgSep(token_type& a_Tok)
+       {
+               const char_type* szFormula = m_strFormula.c_str();
+
+               if (szFormula[m_iPos] == m_cArgSep)
+               {
+                       // copy the separator into null terminated string
+                       char_type szSep[2];
+                       szSep[0] = m_cArgSep;
+                       szSep[1] = 0;
+
+                       if (m_iSynFlags & noARG_SEP)
+                               Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
+
+                       m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
+                       m_iPos++;
+                       a_Tok.Set(cmARG_SEP, szSep);
+                       return true;
+               }
+
+               return false;
+       }
+
+
+       /** \brief Check for End of Formula.
+
+               \return true if an end of formula is found false otherwise.
+               \param a_Tok [out] If an eof is found the corresponding token will be stored there.
+               \throw nothrow
+               \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
+       */
+       bool ParserTokenReader::IsEOF(token_type& a_Tok)
+       {
+               const char_type* szFormula = m_strFormula.c_str();
+
+               // check for EOF
+               if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)
+               {
+                       if (m_iSynFlags & noEND)
+                               Error(ecUNEXPECTED_EOF, m_iPos);
+
+                       if (!m_bracketStack.empty())
+                               Error(ecMISSING_PARENS, m_iPos, _T(")"));
+
+                       m_iSynFlags = 0;
+                       a_Tok.Set(cmEND);
+                       return true;
+               }
+
+               return false;
+       }
+
+
+       /** \brief Check if a string position contains a unary infix operator.
+               \return true if a function token has been found false otherwise.
+       */
+       bool ParserTokenReader::IsInfixOpTok(token_type& a_Tok)
+       {
+               string_type sTok;
+               auto iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               // iterate over all postfix operator strings
+               funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
+               for (; it != m_pInfixOprtDef->rend(); ++it)
+               {
+                       if (sTok.find(it->first) != 0)
+                               continue;
+
+                       a_Tok.Set(it->second, it->first);
+                       m_iPos += (int)it->first.length();
+
+                       if (m_iSynFlags & noINFIXOP)
+                               Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+
+                       m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN | noARG_SEP;
+                       return true;
+               }
+
+               return false;
+
+               /*
+                       a_Tok.Set(item->second, sTok);
+                       m_iPos = (int)iEnd;
+
+                       if (m_iSynFlags & noINFIXOP)
+                         Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+
+                       m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
+                       return true;
+               */
+       }
+
+
+       /** \brief Check whether the token at a given position is a function token.
+               \param a_Tok [out] If a value token is found it will be placed here.
+               \throw ParserException if Syntaxflags do not allow a function at a_iPos
+               \return true if a function token has been found false otherwise.
+               \pre [assert] m_pParser!=0
+       */
+       bool ParserTokenReader::IsFunTok(token_type& a_Tok)
+       {
+               string_type strTok;
+               auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               funmap_type::const_iterator item = m_pFunDef->find(strTok);
+               if (item == m_pFunDef->end())
+                       return false;
+
+               // Check if the next sign is an opening bracket
+               const char_type* szFormula = m_strFormula.c_str();
+               if (szFormula[iEnd] != '(')
+                       return false;
+
+               a_Tok.Set(item->second, strTok);
+
+               m_iPos = (int)iEnd;
+               if (m_iSynFlags & noFUN)
+                       Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
+
+               m_iSynFlags = noANY ^ noBO;
+               return true;
+       }
+
+
+       /** \brief Check if a string position contains a binary operator.
+               \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+               \return true if an operator token has been found.
+       */
+       bool ParserTokenReader::IsOprt(token_type& a_Tok)
+       {
+               const char_type* const szExpr = m_strFormula.c_str();
+               string_type strTok;
+
+               auto iEnd = ExtractOperatorToken(strTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               // Check if the operator is a built in operator, if so ignore it here
+               const char_type** const pOprtDef = m_pParser->GetOprtDef();
+               for (int i = 0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
+               {
+                       if (string_type(pOprtDef[i]) == strTok)
+                               return false;
+               }
+
+               // Note:
+               // All tokens in oprt_bin_maptype are have been sorted by their length
+               // Long operators must come first! Otherwise short names (like: "add") that
+               // are part of long token names (like: "add123") will be found instead 
+               // of the long ones.
+               // Length sorting is done with ascending length so we use a reverse iterator here.
+               funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
+               for (; it != m_pOprtDef->rend(); ++it)
+               {
+                       const string_type& sID = it->first;
+                       if (sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()))
+                       {
+                               a_Tok.Set(it->second, strTok);
+
+                               // operator was found
+                               if (m_iSynFlags & noOPT)
+                               {
+                                       // An operator was found but is not expected to occur at
+                                       // this position of the formula, maybe it is an infix 
+                                       // operator, not a binary operator. Both operator types
+                                       // can share characters in their identifiers.
+                                       if (IsInfixOpTok(a_Tok))
+                                               return true;
+                                       else
+                                       {
+                                               // nope, no infix operator
+                                               return false;
+                                               //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); 
+                                       }
+
+                               }
+
+                               m_iPos += (int)sID.length();
+                               m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN;
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+
+       /** \brief Check if a string position contains a unary post value operator. */
+       bool ParserTokenReader::IsPostOpTok(token_type& a_Tok)
+       {
+               // <ibg 20110629> Do not check for postfix operators if they are not allowed at
+               //                the current expression index.
+               //
+               //  This will fix the bug reported here:  
+               //
+               //  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979
+               //
+               if (m_iSynFlags & noPOSTOP)
+                       return false;
+               // </ibg>
+
+               // Tricky problem with equations like "3m+5":
+               //     m is a postfix operator, + is a valid sign for postfix operators and 
+               //     for binary operators parser detects "m+" as operator string and 
+               //     finds no matching postfix operator.
+               // 
+               // This is a special case so this routine slightly differs from the other
+               // token readers.
+
+               // Test if there could be a postfix operator
+               string_type sTok;
+               auto iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               // iterate over all postfix operator strings
+               funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
+               for (; it != m_pPostOprtDef->rend(); ++it)
+               {
+                       if (sTok.find(it->first) != 0)
+                               continue;
+
+                       a_Tok.Set(it->second, sTok);
+                       m_iPos += (int)it->first.length();
+
+                       m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
+                       return true;
+               }
+
+               return false;
+       }
+
+
+       /** \brief Check whether the token at a given position is a value token.
+
+               Value tokens are either values or constants.
+
+               \param a_Tok [out] If a value token is found it will be placed here.
+               \return true if a value token has been found.
+       */
+       bool ParserTokenReader::IsValTok(token_type& a_Tok)
+       {
+               MUP_ASSERT(m_pConstDef != nullptr);
+               MUP_ASSERT(m_pParser != nullptr);
+
+               string_type strTok;
+               value_type fVal(0);
+
+               // 2.) Check for user defined constant
+               // Read everything that could be a constant name
+               auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos);
+               if (iEnd != m_iPos)
+               {
+                       valmap_type::const_iterator item = m_pConstDef->find(strTok);
+                       if (item != m_pConstDef->end())
+                       {
+                               m_iPos = iEnd;
+                               a_Tok.SetVal(item->second, strTok);
+
+                               if (m_iSynFlags & noVAL)
+                                       Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+                               m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
+                               return true;
+                       }
+               }
+
+               // 3.call the value recognition functions provided by the user
+               // Call user defined value recognition functions
+               std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();
+               for (item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item)
+               {
+                       int iStart = m_iPos;
+                       if ((*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal) == 1)
+                       {
+                               // 2013-11-27 Issue 2:  https://code.google.com/p/muparser/issues/detail?id=2
+                               strTok.assign(m_strFormula.c_str(), iStart, (std::size_t)m_iPos - iStart);
+
+                               if (m_iSynFlags & noVAL)
+                                       Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+                               a_Tok.SetVal(fVal, strTok);
+                               m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+
+       /** \brief Check wheter a token at a given position is a variable token.
+               \param a_Tok [out] If a variable token has been found it will be placed here.
+                 \return true if a variable token has been found.
+       */
+       bool ParserTokenReader::IsVarTok(token_type& a_Tok)
+       {
+               if (m_pVarDef->empty())
+                       return false;
+
+               string_type strTok;
+               auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               varmap_type::const_iterator item = m_pVarDef->find(strTok);
+               if (item == m_pVarDef->end())
+                       return false;
+
+               if (m_iSynFlags & noVAR)
+                       Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+               m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);
+
+               m_iPos = iEnd;
+               a_Tok.SetVar(item->second, strTok);
+               m_UsedVar[item->first] = item->second;  // Add variable to used-var-list
+
+               m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;
+
+               //  Zur Info hier die SynFlags von IsVal():
+               //    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; 
+               return true;
+       }
+
+
+       bool ParserTokenReader::IsStrVarTok(token_type& a_Tok)
+       {
+               if (!m_pStrVarDef || m_pStrVarDef->empty())
+                       return false;
+
+               string_type strTok;
+               auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos);
+               if (iEnd == m_iPos)
+                       return false;
+
+               strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
+               if (item == m_pStrVarDef->end())
+                       return false;
+
+               if (m_iSynFlags & noSTR)
+                       Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+               m_iPos = iEnd;
+               if (!m_pParser->m_vStringVarBuf.size())
+                       Error(ecINTERNAL_ERROR);
+
+               a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size());
+
+               m_iSynFlags = noANY ^ (noBC | noOPT | noEND | noARG_SEP);
+               return true;
+       }
+
+
+
+       /** \brief Check wheter a token at a given position is an undefined variable.
+
+               \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
+                 \return true if a variable token has been found.
+               \throw nothrow
+       */
+       bool ParserTokenReader::IsUndefVarTok(token_type& a_Tok)
+       {
+               string_type strTok;
+               auto iEnd(ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos));
+               if (iEnd == m_iPos)
+                       return false;
+
+               if (m_iSynFlags & noVAR)
+               {
+                       // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the 
+                       //                 token identifier. 
+                       // related bug report:
+                       // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
+                       Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
+               }
+
+               // If a factory is available implicitely create new variables
+               if (m_pFactory)
+               {
+                       value_type* fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
+                       a_Tok.SetVar(fVar, strTok);
+
+                       // Do not use m_pParser->DefineVar( strTok, fVar );
+                       // in order to define the new variable, it will clear the
+                       // m_UsedVar array which will kill previously defined variables
+                       // from the list
+                       // This is safe because the new variable can never override an existing one
+                       // because they are checked first!
+                       (*m_pVarDef)[strTok] = fVar;
+                       m_UsedVar[strTok] = fVar;  // Add variable to used-var-list
+               }
+               else
+               {
+                       a_Tok.SetVar((value_type*)&m_fZero, strTok);
+                       m_UsedVar[strTok] = 0;  // Add variable to used-var-list
+               }
+
+               m_iPos = iEnd;
+
+               // Call the variable factory in order to let it define a new parser variable
+               m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
+               return true;
+       }
+
+
+
+       /** \brief Check wheter a token at a given position is a string.
+               \param a_Tok [out] If a variable token has been found it will be placed here.
+               \return true if a string token has been found.
+               \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
+               \throw nothrow
+       */
+       bool ParserTokenReader::IsString(token_type& a_Tok)
+       {
+               if (m_strFormula[m_iPos] != '"')
+                       return false;
+
+               string_type strBuf(&m_strFormula[(std::size_t)m_iPos + 1]);
+               std::size_t iEnd(0), iSkip(0);
+
+               // parser over escaped '\"' end replace them with '"'
+               for (iEnd = (int)strBuf.find(_T('\"')); iEnd != 0 && iEnd != string_type::npos; iEnd = (int)strBuf.find(_T('\"'), iEnd))
+               {
+                       if (strBuf[iEnd - 1] != '\\') break;
+                       strBuf.replace(iEnd - 1, 2, _T("\""));
+                       iSkip++;
+               }
+
+               if (iEnd == string_type::npos)
+                       Error(ecUNTERMINATED_STRING, m_iPos, _T("\""));
+
+               string_type strTok(strBuf.begin(), strBuf.begin() + iEnd);
+
+               if (m_iSynFlags & noSTR)
+                       Error(ecUNEXPECTED_STR, m_iPos, strTok);
+
+               m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
+               a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
+
+               m_iPos += (int)strTok.length() + 2 + (int)iSkip;  // +2 for quotes; +iSkip for escape characters 
+               m_iSynFlags = noANY ^ (noARG_SEP | noBC | noOPT | noEND);
+
+               return true;
+       }
+
+
+       /** \brief Create an error containing the parse error position.
+
+         This function will create an Parser Exception object containing the error text and its position.
+
+         \param a_iErrc [in] The error code of type #EErrorCodes.
+         \param a_iPos [in] The position where the error was detected.
+         \param a_strTok [in] The token string representation associated with the error.
+         \throw ParserException always throws thats the only purpose of this function.
+       */
+       void  ParserTokenReader::Error(EErrorCodes a_iErrc,     int a_iPos,     const string_type& a_sTok) const
+       {
+               m_pParser->Error(a_iErrc, a_iPos, a_sTok);
+       }
+
+
+       void ParserTokenReader::SetArgSep(char_type cArgSep)
+       {
+               m_cArgSep = cArgSep;
+       }
+
+
+       char_type ParserTokenReader::GetArgSep() const
+       {
+               return m_cArgSep;
+       }
+} // namespace mu
+
+#if defined(_MSC_VER)
+       #pragma warning(pop)
+#endif
index 11cdeaf44c9b0dd51e405b2cc98452196fc711b1..e84e888aed4d31fd086f32755baf8d2f19268930 100644 (file)
@@ -83,4 +83,4 @@ OPTION(DEAL_II_FORCE_BUNDLED_MUPARSER
   "Always use the bundled functionparser library instead of an external one."
   OFF)
 
-SET(MUPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/muparser_v2_2_4/")
+SET(MUPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/muparser_v2_3_3/")
diff --git a/doc/news/changes/minor/20220328DavidWells b/doc/news/changes/minor/20220328DavidWells
new file mode 100644 (file)
index 0000000..6d433f4
--- /dev/null
@@ -0,0 +1,3 @@
+Changed: The bundled version of muParser has been updated to version 2.3.3.
+<br>
+(David Wells, 2022/03/28)

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.