diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..09ba761 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=false diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml new file mode 100644 index 0000000..83f25d4 --- /dev/null +++ b/.github/workflows/c-cpp.yml @@ -0,0 +1,48 @@ +name: build + +on: + push: + paths-ignore: + - '**/*.md' + pull_request: + paths-ignore: + - '**/*.md' + +env: + CMAKE_BUILD_TYPE: Debug + CMAKE_BUILD_DIR: ${{ github.workspace }}/build + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest, macOS-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Build + shell: bash + run: | + mkdir -p $CMAKE_BUILD_DIR + cd $CMAKE_BUILD_DIR + cmake -DENABLE_SAMPLES=ON -DENABLE_OPENMP=OFF -DENABLE_WIDE_CHAR=ON -DBUILD_SHARED_LIBS=ON .. + cmake --build . + + - name: Run Unit Test + shell: bash + working-directory: ${{ env.CMAKE_BUILD_DIR }} + run: | + if [[ ${{ matrix.os }} == windows* ]]; then + EXAMPLE="$CMAKE_BUILD_TYPE/example1.exe" + else + EXAMPLE="./example1" + fi + $EXAMPLE &> example.log << EOF + quit + EOF + cat example.log + grep -e "Test passed.*expressions" example.log || (grep -e "Test failed.*expressions" example.log; exit 1) diff --git a/.gitignore b/.gitignore index a571e0c..c00a815 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,19 @@ build/* out/* CMakeSettings.json /build/ +CMakeFiles/* +libmuparser.so* +CMakeCache.txt +Makefile +muparser-targets.cmake +muparser.pc +muparserConfig.cmake +muparserConfigVersion.cmake +t_ParserTest +example1 +example2 +DartConfiguration.tcl +cmake_install.cmake +CTestTestfile.cmake +gitlog.log + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ddd5355..0000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: c++ -sudo: false -compiler: - - clang - - gcc -script: - # LD_LIBRARY_PATH workaround to find clang's libomp: https://github.com/travis-ci/travis-ci/issues/8613 - - if [[ ${CC} = clang ]]; then export LD_LIBRARY_PATH=/usr/local/clang/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH; fi - - cmake -DCMAKE_C_FLAGS="-Wall" -DCMAKE_CXX_FLAGS="-Wall" -DCMAKE_INSTALL_PREFIX=~/.local/ . - - make install -j2 - - ctest --output-on-failure diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c8d57a1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "*.rmd": "markdown", + "stdexcept": "cpp", + "sstream": "cpp" + } +} \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG index 3ad1916..acffea9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,616 +1,635 @@ - - _____ __ _____________ _______ ______ ___________ - / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ - | 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 + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2023 Ingo Berg + +======================================================================= + https://beltoforion.de/en/muparser +======================================================================= + +History: +-------- + +Rev 2.3.5: 13.10.2023 +--------------------- + Bugfixes: + * Fix for #125 (bug in muParserDLL.cpp / mupDefineInfixOprt) + + Changes: + * Bitwise "and" and "or" used the same precedence. (Now bitwise and priority is higher, like in C++) + * Fix for #131 (added a SetByteCode function to allow restoring previously extracted bytecode) + + +Rev 2.3.4: 06.11.2022 +--------------------- + Build System Changes (CMake): + * cmake is using OpenMP target and setting _UNICODE preprocessor definition + Compiler Warnings: + * fix for issue #117 (sprintf deprecation warning) + + +Rev 2.3.3: 22.01.2022 +--------------------- + 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 +--------------------------- + 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index ad931c0..a33eb47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # CMake based on work from @xantares -cmake_minimum_required (VERSION 3.1.0) +cmake_minimum_required (VERSION 3.15.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -13,7 +13,7 @@ project(muParserProject) # Bump versions on release set(MUPARSER_VERSION_MAJOR 2) set(MUPARSER_VERSION_MINOR 3) -set(MUPARSER_VERSION_PATCH 2) +set(MUPARSER_VERSION_PATCH 4) set(MUPARSER_VERSION ${MUPARSER_VERSION_MAJOR}.${MUPARSER_VERSION_MINOR}.${MUPARSER_VERSION_PATCH}) # Build options @@ -24,8 +24,6 @@ option(BUILD_SHARED_LIBS "Build shared/static libs" ON) if(ENABLE_OPENMP) find_package(OpenMP REQUIRED) - set(CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") - set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "${OpenMP_CXX_FLAGS} ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") endif() # Credit: https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake/3818084 @@ -67,6 +65,7 @@ endif () if(ENABLE_OPENMP) target_compile_definitions(muparser PRIVATE MUP_USE_OPENMP) + target_link_libraries(muparser PRIVATE OpenMP::OpenMP_CXX) endif() if(ENABLE_WIDE_CHAR) @@ -110,6 +109,7 @@ export(EXPORT muparser-export FILE "${CMAKE_BINARY_DIR}/muparser-targets.cmake" NAMESPACE muparser:: ) +add_library(muparser::muparser ALIAS muparser) # Export the installed target (typically for packaging) include(CMakePackageConfigHelpers) @@ -136,6 +136,9 @@ install(FILES # Define variables for the pkg-config file set(PACKAGE_NAME muparser) +if(ENABLE_WIDE_CHAR) + set(PKG_CONFIG_FLAGS "-D_UNICODE") +endif(ENABLE_WIDE_CHAR) configure_file( muparser.pc.in ${CMAKE_BINARY_DIR}/muparser.pc diff --git a/Install.txt b/Install.txt index feb9649..e8813ca 100644 --- a/Install.txt +++ b/Install.txt @@ -4,10 +4,10 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2020 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg ======================================================================= - https://muparser.beltoforion.de + https://beltoforion.de/en/muparser/ ======================================================================= Installation diff --git a/README.rst b/README.rst index 4e14503..70ecb83 100644 --- a/README.rst +++ b/README.rst @@ -1,53 +1,76 @@ -.. image:: https://travis-ci.org/beltoforion/muparser.svg?branch=master - :target: https://travis-ci.org/beltoforion/muparser - -.. image:: https://ci.appveyor.com/api/projects/status/u4882uj8btuspj9x?svg=true - :target: https://ci.appveyor.com/project/beltoforion/muparser - -.. image:: https://img.shields.io/github/issues/beltoforion/muparser.svg?maxAge=360 - :target: https://github.com/beltoforion/muparser/issues - -.. image:: https://img.shields.io/github/release/beltoforion/muparser.svg?maxAge=360 - :target: https://github.com/beltoforion/muparser/blob/master/CHANGELOG - -.. image:: https://repology.org/badge/tiny-repos/muparser.svg - :target: https://repology.org/project/muparser/versions - - -muparser - Fast Math Parser 2.3.3 -=========================== -.. image:: http://beltoforion.de/en/muparser/images/title.jpg - - -To read the full documentation please go to: http://beltoforion.de/en/muparser. - -See Install.txt for installation - -Change Notes for Revision 2.3.3 (Prerelease) -=========================== -Security Fixes: ------------- -The following new issues, discovered by oss-fuzz are fixed: - -* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24167 (Abrt) -* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24355 (Heap-buffer-overflow READ 8) -* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25402 (Heap-buffer-overflow READ 8) - -Bugfixes: ------------ -* Fixed a couple of issues for building the C-Interface (muParserDLL.cpp/.h) with wide character support. -* fix for #93 (https://github.com/beltoforion/muparser/issues/93) -* fix for #94 (https://github.com/beltoforion/muparser/issues/94) - -Fixed Compiler Warnings: ------------ -* Visual Studio: Disabled compiler warning 26812 (Prefer 'enum class' over 'enum') Use of plain old enums has not been deprecated and only MSVC is complaining. -* Visual Studio: Disabled compiler warning 4251 (... needs to have dll-interface to be used by clients of class ...) For technical reason the DLL contains the class API and the DLL API. Just do not use the class API if you intent to share the dll accross windows versions. (The same is true for Linux but distributions do compile each application against their own library version anyway) - -Changes: ------------- -* Adding manual definitions to avoid potential issues with MSVC -* Adding missing overrides -* Added a new option "-DENABLE_WIDE_CHAR" to CMake for building muparser with wide character support -* export muparser targets, such that client projects can import it using find_package() (https://github.com/beltoforion/muparser/pull/81#event-3528671228) - +.. image:: https://ci.appveyor.com/api/projects/status/u4882uj8btuspj9x?svg=true + :target: https://ci.appveyor.com/project/beltoforion/muparser + +.. image:: https://img.shields.io/github/issues/beltoforion/muparser.svg?maxAge=360 + :target: https://github.com/beltoforion/muparser/issues + +.. image:: https://img.shields.io/github/release/beltoforion/muparser.svg?maxAge=360 + :target: https://github.com/beltoforion/muparser/blob/master/CHANGELOG + +.. image:: https://repology.org/badge/tiny-repos/muparser.svg + :target: https://repology.org/project/muparser/versions + +muparser - fast math parser library +=================================== + +.. image:: http://beltoforion.de/en/muparser/images/title.webp + +Change Notes for Revision 2.3.5 +=========================== + +Fixed Compiler Warnings: +----------- +- Fix problem with IntelLLVM fast math + +Build System: +------------ +- fix for https://github.com/beltoforion/muparser/issues/127 (minimum required cmake version set to 3.15) +- fix for https://github.com/beltoforion/muparser/issues/123 (Strange behavior of the postfix operator on macOS) +- fix for https://github.com/beltoforion/muparser/issues/132 example1 fails to builds on Windows with mingw gcc + +Change Notes for Revision 2.3.4 +=========================== + +Maintainance Release with updates of the cmake build system. + +Build System: +------------ +- cmake is using OpenMP target and setting _UNICODE preprocessor definition + +Fixed Compiler Warnings: +----------- +- fix for https://github.com/beltoforion/muparser/issues/117 (sprintf deprecated) + +Change Notes for Revision 2.3.3 +=========================== +To read the full documentation please go to: http://beltoforion.de/en/muparser. + +See Install.txt for installation + +Security Fixes: +------------ +The following new issues, discovered by oss-fuzz are fixed: + +* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24167 (Abrt) +* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24355 (Heap-buffer-overflow READ 8) +* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25402 (Heap-buffer-overflow READ 8) + +Bugfixes: +----------- +* Fixed a couple of issues for building the C-Interface (muParserDLL.cpp/.h) with wide character support. +* fix for https://github.com/beltoforion/muparser/issues/93 +* fix for https://github.com/beltoforion/muparser/issues/94 +* fix for https://github.com/beltoforion/muparser/issues/110; new expression size limit is 20000 + +Fixed Compiler Warnings: +----------- +* Visual Studio: Disabled compiler warning 26812 (Prefer 'enum class' over 'enum') Use of plain old enums has not been deprecated and only MSVC is complaining. +* Visual Studio: Disabled compiler warning 4251 (... needs to have dll-interface to be used by clients of class ...) For technical reason the DLL contains the class API and the DLL API. Just do not use the class API if you intent to share the dll accross windows versions. (The same is true for Linux but distributions do compile each application against their own library version anyway) + +Changes: +------------ +* Adding manual definitions to avoid potential issues with MSVC +* Adding missing overrides +* Added a new option "-DENABLE_WIDE_CHAR" to CMake for building muparser with wide character support +* export muparser targets, such that client projects can import it using find_package() (https://github.com/beltoforion/muparser/pull/81#event-3528671228) + diff --git a/include/muParser.h b/include/muParser.h index 62032aa..d00a976 100644 --- a/include/muParser.h +++ b/include/muParser.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/include/muParserBase.h b/include/muParserBase.h index 6d32f2f..15ac151 100644 --- a/include/muParserBase.h +++ b/include/muParserBase.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -188,6 +188,8 @@ namespace mu const char_type* ValidInfixOprtChars() const; void SetArgSep(char_type cArgSep); + void SetByteCode(const ParserByteCode& a_ByteCode); + char_type GetArgSep() const; protected: diff --git a/include/muParserBytecode.h b/include/muParserBytecode.h index cf16e20..3196aac 100644 --- a/include/muParserBytecode.h +++ b/include/muParserBytecode.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -84,7 +84,7 @@ namespace mu 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 + class API_EXPORT_CXX ParserByteCode final { private: @@ -94,9 +94,18 @@ namespace mu /** \brief Token vector for storing the RPN. */ typedef std::vector rpn_type; + /** \brief Type for a vector of strings. */ + typedef std::vector stringbuf_type; + /** \brief Position in the Calculation array. */ unsigned m_iStackPos; + /** \brief String variable storage. */ + stringbuf_type m_stringBuffer; + + /** \brief The expression associated with this bytecode. */ + string_type m_expr; + /** \brief Maximum size needed for the stack. */ std::size_t m_iMaxStackSize; @@ -142,7 +151,18 @@ namespace mu return &m_vRPN[0]; } - void AsciiDump(); + void StoreEnvironment(string_type expr, stringbuf_type const& strBuf) + { + m_stringBuffer = strBuf; + m_expr = expr; + } + + std::tuple RestoreEnvironment() const + { + return std::make_tuple(m_expr, m_stringBuffer); + } + + void AsciiDump() const; }; } // namespace mu diff --git a/include/muParserCallback.h b/include/muParserCallback.h index 2d804ee..1e53f14 100644 --- a/include/muParserCallback.h +++ b/include/muParserCallback.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + 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: @@ -85,6 +85,7 @@ namespace mu 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); @@ -118,6 +119,7 @@ namespace mu 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); diff --git a/include/muParserDLL.h b/include/muParserDLL.h index 00eea9f..14d08cd 100644 --- a/include/muParserDLL.h +++ b/include/muParserDLL.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2023 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -253,11 +253,13 @@ extern "C" muFun1_t a_pOprt, muBool_t a_bOptimize); - - API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bOptimize); + // signature changed to fix #125 (https://github.com/beltoforion/muparser/issues/125) + API_EXPORT(void) mupDefineInfixOprt( + muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + int a_iPrec, + muBool_t a_bAllowOpt); // Define character sets for identifiers API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); diff --git a/include/muParserDef.h b/include/muParserDef.h index 4986a57..599f04b 100644 --- a/include/muParserDef.h +++ b/include/muParserDef.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -207,18 +207,18 @@ namespace mu /** \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) + prLOR = 1, ///< logic or + prLAND = 2, ///< logic and + prBOR = 3, ///< bitwise or + prBAND = 4, ///< bitwise and + prCMP = 5, ///< comparsion operators + prADD_SUB = 6, ///< addition + prMUL_DIV = 7, ///< multiplication/division + prPOW = 8, ///< 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) + prINFIX = 7, ///< Signs have a higher priority than ADD_SUB, but lower than power operator + prPOSTFIX = 7 ///< Postfix operator priority (currently unused) }; @@ -276,7 +276,9 @@ namespace mu ecINVALID_CHARACTERS_FOUND = 38,///< The expression or identifier contains invalid non printable characters // internal errors - ecINTERNAL_ERROR = 39, ///< Internal error of any kind. + ecINTERNAL_ERROR = 39, ///< Internal error of any kind. + + ecBYTECODE_IMPORT_EXPORT_DISABLED = 40, ///< Bytecode cannot be exported. // The last two are special entries ecCOUNT, ///< This is no error code, It just stores just the total number of error codes @@ -471,12 +473,15 @@ namespace mu /** \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 a value as arguments. */ + /** \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 two values as arguments. */ + /** \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*); @@ -492,16 +497,19 @@ namespace mu /** \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 = 5000; + static const int MaxLenExpression = 20000; static const int MaxLenIdentifier = 100; - static const string_type ParserVersion = string_type(_T("2.3.3 (Development Build)")); - static const string_type ParserVersionDate = string_type(_T("20210328")); + static const string_type ParserVersion = string_type(_T("2.3.4 (Develop)")); + static const string_type ParserVersionDate = string_type(_T("20231224")); } // end of namespace #if defined(_MSC_VER) diff --git a/include/muParserError.h b/include/muParserError.h index 90fbfdf..a6564bb 100644 --- a/include/muParserError.h +++ b/include/muParserError.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/include/muParserFixes.h b/include/muParserFixes.h index 8042d28..afcd6bd 100644 --- a/include/muParserFixes.h +++ b/include/muParserFixes.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/include/muParserInt.h b/include/muParserInt.h index 513f092..cad708f 100644 --- a/include/muParserInt.h +++ b/include/muParserInt.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -69,8 +69,8 @@ namespace mu 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 BitAnd(value_type v1, value_type v2); + static value_type BitOr(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); diff --git a/include/muParserTemplateMagic.h b/include/muParserTemplateMagic.h index 77fe549..f20b392 100644 --- a/include/muParserTemplateMagic.h +++ b/include/muParserTemplateMagic.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/include/muParserTest.h b/include/muParserTest.h index c7fd166..a3582cd 100644 --- a/include/muParserTest.h +++ b/include/muParserTest.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -171,6 +171,13 @@ namespace mu 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); @@ -252,7 +259,8 @@ namespace mu int TestBulkMode(); int TestOssFuzzTestCases(); int TestOptimizer(); - + int TestLocalization(); + void Abort() const; public: @@ -268,6 +276,7 @@ namespace mu // 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 EqnTestLocalized(const string_type& a_str, double a_fRes, bool a_fPass); int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); // Test Int Parser diff --git a/include/muParserToken.h b/include/muParserToken.h index 527f8ef..3a40d06 100644 --- a/include/muParserToken.h +++ b/include/muParserToken.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -58,7 +58,7 @@ namespace mu 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; }; + 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; }; diff --git a/include/muParserTokenReader.h b/include/muParserTokenReader.h index 0ea19f5..b3739fa 100644 --- a/include/muParserTokenReader.h +++ b/include/muParserTokenReader.h @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -51,7 +51,7 @@ namespace mu class ParserBase; /** \brief Token reader for the ParserBase class. */ - class ParserTokenReader final + class API_EXPORT_CXX ParserTokenReader final { private: @@ -67,6 +67,15 @@ namespace mu void SetFormula(const string_type& a_strFormula); void SetArgSep(char_type cArgSep); + /** \brief Check whether a variable factory is installed. + + Variable factories automatically create new variables when a unknown variable is found in an expression. + */ + bool HasVarCreator() const + { + return m_pFactory != nullptr; + } + int GetPos() const; const string_type& GetExpr() const; varmap_type& GetUsedVar(); diff --git a/muparser.pc.in b/muparser.pc.in index be535ff..646787c 100644 --- a/muparser.pc.in +++ b/muparser.pc.in @@ -8,4 +8,4 @@ Description: Mathematical expressions parser library Version: @MUPARSER_VERSION@ Requires: Libs: -L${libdir} -lmuparser -Cflags: -I${includedir} +Cflags: -I${includedir} @PKG_CONFIG_FLAGS@ diff --git a/samples/example1/example1.cpp b/samples/example1/example1.cpp index 1b3461c..6982d59 100644 --- a/samples/example1/example1.cpp +++ b/samples/example1/example1.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + 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: @@ -39,6 +39,7 @@ #include "muParserTest.h" #include "muParser.h" +#include "muParserBytecode.h" using namespace std; using namespace mu; @@ -189,7 +190,7 @@ static void Splash() mu::console() << _T(R"( |__|_| /____/| __(____ /___| /___ >\___ >|__| )") << _T("\n"); mu::console() << _T(R"( \/ |__| \/ \/ \/ )") << _T("\n"); mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n"); - mu::console() << _T(" (C) 2004 - 2020 Ingo Berg\n"); + mu::console() << _T(" (C) 2022 Ingo Berg\n"); mu::console() << _T("\n"); mu::console() << _T("-----------------------------------------------------------\n"); @@ -437,6 +438,9 @@ void CalcBulk() static void Calc() { mu::Parser parser; + parser.SetDecSep(','); + parser.SetArgSep(';'); + parser.SetThousandsSep('.'); // Add some variables value_type vVarVal[] = { 1, 2 }; // Values of the parser variables @@ -474,6 +478,15 @@ static void Calc() // Define the variable factory parser.SetVarFactory(AddVariable, &parser); + // You can extract the bytecode of a parsed functions and save it for later use. +// parser.SetExpr(_T("sin(a)+strfun2(sVar1, 1 , 2)")); +// parser.Eval(); +// ParserByteCode bytecode1(parser.GetByteCode()); + +// parser.SetExpr(_T("10*cos(a)")); +// parser.Eval(); +// ParserByteCode bytecode2(parser.GetByteCode()); + for (;;) { try @@ -491,7 +504,21 @@ static void Calc() if (!sLine.length()) continue; - parser.SetExpr(sLine); + if (sLine == _T("restore1")) + { +// parser.SetByteCode(bytecode1); +// bytecode1.AsciiDump(); + } + else if (sLine == _T("restore2")) + { +// parser.SetByteCode(bytecode2); +// bytecode2.AsciiDump(); + } + else + { + parser.SetExpr(sLine); + } + mu::console() << std::setprecision(12); // There are multiple ways to retrieve the result... diff --git a/samples/example2/example2.c b/samples/example2/example2.c index 42e4564..c408ac7 100644 --- a/samples/example2/example2.c +++ b/samples/example2/example2.c @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2023 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -406,7 +407,7 @@ static void Calc(void) mupDefinePostfixOprt(hParser, _T("m"), Milli, 0); // Define infix operator [optional] - mupDefineInfixOprt(hParser, _T("!"), Not, 0); + mupDefineInfixOprt(hParser, _T("!"), Not, 0, true); // Define functions [optional] // mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function diff --git a/samples/example3/example3.cpp b/samples/example3/example3.cpp index 86a2ae2..e569249 100644 --- a/samples/example3/example3.cpp +++ b/samples/example3/example3.cpp @@ -1,11 +1,11 @@ /* - _____ __ _____________ _______ ______ ___________ - / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| - \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/muParser.cpp b/src/muParser.cpp index 0ebef2a..c5ac721 100644 --- a/src/muParser.cpp +++ b/src/muParser.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -33,6 +33,8 @@ #include #include #include +#include + using namespace std; @@ -54,10 +56,34 @@ namespace mu */ int Parser::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) { +#if defined(__APPLE__) + // 2023-12-23 Issue #136: This code breaks localization! + // + // I decided to not give a shit about localization being + // broken on Macs's because APPLE does not give a shit about the + // stringstream being broken either. They have the resources to fix their + // compiler, i do not have the resources to work around their failures. + + // fix for #123; std::Stringstream is broken on Mac; use std::stod instead + try + { + std::size_t charsProcessed; + value_type fVal = static_cast(std::stod(string_type(a_szExpr), &charsProcessed)); + if (charsProcessed == 0) + return 0; + + *a_iPos += (int)charsProcessed; + *a_fVal = fVal; + return 1; + } + catch (...) + { + return 0; + } +#else 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 @@ -68,6 +94,7 @@ namespace mu *a_iPos += (int)iEnd; *a_fVal = fVal; return 1; +#endif } diff --git a/src/muParserBase.cpp b/src/muParserBase.cpp index b0a443d..5ffbb49 100644 --- a/src/muParserBase.cpp +++ b/src/muParserBase.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + 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: @@ -261,19 +261,43 @@ namespace mu m_pTokenReader->ReInit(); } - //--------------------------------------------------------------------------- + void ParserBase::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/) {} - //--------------------------------------------------------------------------- - /** \brief Returns the bytecode of the current expression. + + /** \brief Returns a copy of the bytecode of the current expression. */ const ParserByteCode& ParserBase::GetByteCode() const { + // If a variable factory is defined the bytecode may contain references to implicitely + // created variables. +// if (m_pTokenReader->HasVarCreator()) +// Error(ecBYTECODE_IMPORT_EXPORT_DISABLED); + return m_vRPN; } - //--------------------------------------------------------------------------- + + /** \brief Restore a previously saved bytecode. */ + void ParserBase::SetByteCode(const ParserByteCode& a_ByteCode) + { + // If a variable factory is defined the bytecode may contain references to dynamically + // created variables. +// if (m_pTokenReader->HasVarCreator()) +// Error(ecBYTECODE_IMPORT_EXPORT_DISABLED); + + m_vRPN = a_ByteCode; + + // restore expression environment + string_type expr; + std::tie(expr, m_vStringBuf) = a_ByteCode.RestoreEnvironment(); + m_pTokenReader->SetFormula(expr); + + m_pParseFormula = &ParserBase::ParseCmdCode; + } + + /** \brief Returns the version of muparser. \param eInfo A flag indicating whether the full version info should be returned or not. @@ -774,6 +798,7 @@ namespace mu 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); } } @@ -1218,6 +1243,7 @@ namespace mu 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; @@ -1530,12 +1556,14 @@ namespace mu if (m_vRPN.GetSize() == 2) { + m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf); m_pParseFormula = &ParserBase::ParseCmdCodeShort; m_vStackBuffer[1] = (this->*m_pParseFormula)(); return m_vStackBuffer[1]; } else { + m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf); m_pParseFormula = &ParserBase::ParseCmdCode; return (this->*m_pParseFormula)(); } diff --git a/src/muParserBytecode.cpp b/src/muParserBytecode.cpp index 54427b9..1bc61c3 100644 --- a/src/muParserBytecode.cpp +++ b/src/muParserBytecode.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -49,7 +49,9 @@ namespace mu { /** \brief Bytecode default constructor. */ ParserByteCode::ParserByteCode() - :m_iStackPos(0) + : m_iStackPos(0) + , m_stringBuffer() + , m_expr() , m_iMaxStackSize(0) , m_vRPN() , m_bEnableOptimizer(true) @@ -98,6 +100,9 @@ namespace mu m_vRPN = a_ByteCode.m_vRPN; m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; + + m_stringBuffer = a_ByteCode.m_stringBuffer; + m_expr = a_ByteCode.m_expr; } @@ -545,7 +550,7 @@ namespace mu /** \brief Dump bytecode (for debugging only!). */ - void ParserByteCode::AsciiDump() + void ParserByteCode::AsciiDump() const { if (!m_vRPN.size()) { @@ -595,7 +600,7 @@ namespace mu 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("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("=\"") << m_stringBuffer[m_vRPN[i].Fun.idx] << ("\"]"); mu::console() << _T("[ADDR: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pRawFun) << _T("]"); mu::console() << _T("[USERDATA: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pUserData) << _T("]"); mu::console() << _T("\n"); diff --git a/src/muParserCallback.cpp b/src/muParserCallback.cpp index 6e78816..8f2265b 100644 --- a/src/muParserCallback.cpp +++ b/src/muParserCallback.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + 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: @@ -643,6 +643,16 @@ namespace mu , 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(a_pFun), a_pUserData}) @@ -699,6 +709,16 @@ namespace mu {} + ParserCallback::ParserCallback(strfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{ reinterpret_cast(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 */ diff --git a/src/muParserDLL.cpp b/src/muParserDLL.cpp index 846f65e..5730f71 100644 --- a/src/muParserDLL.cpp +++ b/src/muParserDLL.cpp @@ -1,1276 +1,1272 @@ -/* - - _____ __ _____________ _______ ______ ___________ - / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ - | 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. -*/ - -#if defined(MUPARSER_DLL) - -#if defined(_WIN32) - #define WIN32_LEAN_AND_MEAN - #define _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_DEPRECATE - - #include -#endif - -#include - -#include "muParserDLL.h" -#include "muParser.h" -#include "muParserInt.h" -#include "muParserError.h" - -#if _UNICODE - #include -#endif - -#if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable : 26812) -#endif - -#define MU_TRY \ - try \ - { - -#define MU_CATCH \ - } \ - catch (muError_t &e) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = e; \ - pTag->bError = true; \ - if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } \ - catch (...) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ - pTag->bError = true; \ - if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } - -/** \file - \brief This file contains the implementation of the DLL interface of muparser. -*/ - -typedef mu::ParserBase::exception_type muError_t; -typedef mu::ParserBase muParser_t; -int g_nBulkSize; - - -class ParserTag -{ -public: - ParserTag(int nType) - : pParser((nType == muBASETYPE_FLOAT) - ? (mu::ParserBase*)new mu::Parser() - : (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : nullptr) - , exc() - , errHandler(nullptr) - , bError(false) - , m_nParserType(nType) - {} - - ~ParserTag() - { - delete pParser; - } - - mu::ParserBase* pParser; - mu::ParserBase::exception_type exc; - muErrorHandler_t errHandler; - bool bError; - -private: - ParserTag(const ParserTag& ref); - ParserTag& operator=(const ParserTag& ref); - - int m_nParserType; -}; - -static muChar_t s_tmpOutBuf[2048]; - -template -constexpr std::size_t count_of(const T& array) -{ - return (sizeof(array) / sizeof(array[0])); -} - -//--------------------------------------------------------------------------- -// -// -// unexported functions -// -// -//--------------------------------------------------------------------------- - - -inline muParser_t* AsParser(muParserHandle_t a_hParser) -{ - return static_cast(a_hParser)->pParser; -} - - -inline ParserTag* AsParserTag(muParserHandle_t a_hParser) -{ - return static_cast(a_hParser); -} - - -#if defined(_WIN32) - -BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - - return TRUE; -} - -#endif - -//--------------------------------------------------------------------------- -// -// -// exported functions -// -// -//--------------------------------------------------------------------------- - -API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->SetVarFactory(a_pFactory, pUserData); - MU_CATCH -} - - -/** \brief Create a new Parser instance and return its handle. */ -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) -{ - switch (nBaseType) - { - case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); - case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); - default: return nullptr; - } -} - - -/** \brief Release the parser instance related with a parser handle. */ -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) -{ - MU_TRY - ParserTag* p = static_cast(a_hParser); - delete p; - MU_CATCH -} - - -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str()); -#else -// wsprintf(s_tmpOutBuf, _T("%s"), p->GetVersion().c_str()); - swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetVersion().c_str()); -#endif - - return s_tmpOutBuf; - MU_CATCH - return _T(""); -} - - -/** \brief Evaluate the expression. */ -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - return p->Eval(); - MU_CATCH - return 0; -} - - -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) -{ - MU_TRY - if (nNum == nullptr) - throw std::runtime_error("Argument is null!"); - - muParser_t* const p(AsParser(a_hParser)); - return p->Eval(*nNum); - MU_CATCH - return 0; -} - - -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->Eval(a_res, nSize); - MU_CATCH -} - - -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetExpr(a_szExpr); - MU_CATCH -} - - -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->RemoveVar(a_szName); - MU_CATCH -} - - -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. -*/ -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearVar(); - MU_CATCH -} - - -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. -*/ -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearConst(); - MU_CATCH -} - - -/** \brief Clear all user defined operators. - \param a_hParser Handle to the parser instance. -*/ -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearOprt(); - MU_CATCH -} - - -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearFun(); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun0_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData0_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData1_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData2_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData3_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData4_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData5_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData6_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData7_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData8_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData9_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData10_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData0_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData1_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData2_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData3_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData4_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData5_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData6_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData7_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData8_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData9_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData10_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun4_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun5_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData1_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData2_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData3_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData4_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData5_t a_pFun, void* a_pUserData) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); - MU_CATCH -} - - -API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineMultFunUserData(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFunUserData_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); - MU_CATCH -} - - -API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); - MU_CATCH -} - - -API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineConst(a_szName, a_fVal); - MU_CATCH -} - - -API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineStrConst(a_szName, a_szVal); - MU_CATCH -} - - -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str()); -#else -// wsprintf(s_tmpOutBuf, _T("%s"), p->GetExpr().c_str()); - swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetExpr().c_str()); -#endif - - return s_tmpOutBuf; - MU_CATCH - - return _T(""); -} - - -API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); - MU_CATCH -} - - -API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); - MU_CATCH -} - -// Define character sets for identifiers -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineNameChars(a_szCharset); -} - - -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprtChars(a_szCharset); -} - - -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprtChars(a_szCharset); -} - - -/** \brief Get the number of variables defined in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar -*/ -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - - -/** \brief Return a variable that is used in an expression. - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - \throw nothrow - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. -*/ -API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) -{ - // A static buffer is needed for the name since i can't return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - - if (a_iVar >= VarMap.size()) - { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), count_of(szName)); -#else - wcsncpy(szName, item->first.c_str(), count_of(szName)); -#endif - - szName[count_of(szName) - 1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - MU_CATCH - - * a_szName = 0; - *a_pVar = 0; -} - - -/** \brief Get the number of variables used in the expression currently set in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar - */ -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - - -/** \brief Return a variable that is used in an expression. - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. - - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - \throw nothrow -*/ -API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) -{ - // A static buffer is needed for the name since i can't return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - - if (a_iVar >= VarMap.size()) - { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), count_of(szName)); -#else - wcsncpy(szName, item->first.c_str(), count_of(szName)); -#endif - - szName[count_of(szName) - 1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - MU_CATCH - - * a_szName = 0; - *a_pVar = 0; -} - - -/** \brief Return the number of constants defined in a parser. */ -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - return (int)ValMap.size(); - MU_CATCH - - return 0; // never reached -} - - -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetArgSep(cArgSep); - MU_CATCH -} - - -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ResetLocale(); - MU_CATCH -} - - -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetDecSep(cDecSep); - MU_CATCH -} - - -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetThousandsSep(cThousandsSep); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Retrieve name and value of a single parser constant. - \param a_hParser [in] a valid parser handle - \param a_iVar [in] Index of the constant to query - \param a_pszName [out] pointer to a null terminated string with the constant name - \param [out] The constant value - */ -API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_fVal) -{ - // A static buffer is needed for the name since i can't return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - - if (a_iVar >= ValMap.size()) - { - *a_pszName = 0; - *a_fVal = 0; - return; - } - - mu::valmap_type::const_iterator item; - item = ValMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), count_of(szName)); -#else - wcsncpy(szName, item->first.c_str(), count_of(szName)); -#endif - - szName[count_of(szName) - 1] = 0; - - *a_pszName = &szName[0]; - *a_fVal = item->second; - return; - - MU_CATCH - - * a_pszName = 0; - *a_fVal = 0; -} - - -/** \brief Add a custom value recognition function. */ -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t a_pFun) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->AddValIdent(a_pFun); - MU_CATCH -} - - -/** \brief Query if an error occurred. - - After querying the internal error bit will be reset. So a consecutive call - will return false. -*/ -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) -{ - bool bError(AsParserTag(a_hParser)->bError); - AsParserTag(a_hParser)->bError = false; - return bError; -} - - -/** \brief Reset the internal error flag. */ -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) -{ - AsParserTag(a_hParser)->bError = false; -} - - -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) -{ - AsParserTag(a_hParser)->errHandler = a_pHandler; -} - - -/** \brief Return the message associated with the last error. */ -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) -{ - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t* pMsg = p->exc.GetMsg().c_str(); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pMsg); -#else - //wsprintf(s_tmpOutBuf, _T("%s"), pMsg); - swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pMsg); -#endif - - return s_tmpOutBuf; -} - - -/** \brief Return the message associated with the last error. */ -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) -{ - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t* pToken = p->exc.GetToken().c_str(); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pToken); -#else - //wsprintf(s_tmpOutBuf, _T("%s"), pToken); - swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pToken); -#endif - - return s_tmpOutBuf; -} - - -/** \brief Return the code associated with the last error. -*/ -API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) -{ - return AsParserTag(a_hParser)->exc.GetCode(); -} - - -/** \brief Return the position associated with the last error. */ -API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) -{ - return (int)AsParserTag(a_hParser)->exc.GetPos(); -} - - -API_EXPORT(muFloat_t*) mupCreateVar() -{ - return new muFloat_t(0); -} - - -API_EXPORT(void) mupReleaseVar(muFloat_t* ptr) -{ - delete ptr; -} - -#if defined(_MSC_VER) - #pragma warning(pop) -#endif - -#endif // MUPARSER_DLL +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 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. +*/ + +#if defined(MUPARSER_DLL) + +#if defined(_WIN32) + #define WIN32_LEAN_AND_MEAN + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_DEPRECATE + + #include +#endif + +#include + +#include "muParserDLL.h" +#include "muParser.h" +#include "muParserInt.h" +#include "muParserError.h" + +#if _UNICODE + #include +#endif + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +#define MU_TRY \ + try \ + { + +#define MU_CATCH \ + } \ + catch (muError_t &e) \ + { \ + ParserTag *pTag = static_cast(a_hParser); \ + pTag->exc = e; \ + pTag->bError = true; \ + if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } \ + catch (...) \ + { \ + ParserTag *pTag = static_cast(a_hParser); \ + pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ + pTag->bError = true; \ + if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } + +/** \file + \brief This file contains the implementation of the DLL interface of muparser. +*/ + +typedef mu::ParserBase::exception_type muError_t; +typedef mu::ParserBase muParser_t; +int g_nBulkSize; + + +class ParserTag +{ +public: + ParserTag(int nType) + : pParser((nType == muBASETYPE_FLOAT) + ? (mu::ParserBase*)new mu::Parser() + : (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : nullptr) + , exc() + , errHandler(nullptr) + , bError(false) + , m_nParserType(nType) + {} + + ~ParserTag() + { + delete pParser; + } + + mu::ParserBase* pParser; + mu::ParserBase::exception_type exc; + muErrorHandler_t errHandler; + bool bError; + +private: + ParserTag(const ParserTag& ref); + ParserTag& operator=(const ParserTag& ref); + + int m_nParserType; +}; + +static muChar_t s_tmpOutBuf[2048]; + +template +constexpr std::size_t count_of(const T& array) +{ + return (sizeof(array) / sizeof(array[0])); +} + +//--------------------------------------------------------------------------- +// +// +// unexported functions +// +// +//--------------------------------------------------------------------------- + + +inline muParser_t* AsParser(muParserHandle_t a_hParser) +{ + return static_cast(a_hParser)->pParser; +} + + +inline ParserTag* AsParserTag(muParserHandle_t a_hParser) +{ + return static_cast(a_hParser); +} + + +#if defined(_WIN32) + +BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +#endif + +//--------------------------------------------------------------------------- +// +// +// exported functions +// +// +//--------------------------------------------------------------------------- + +API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->SetVarFactory(a_pFactory, pUserData); + MU_CATCH +} + + +/** \brief Create a new Parser instance and return its handle. */ +API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) +{ + switch (nBaseType) + { + case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); + case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); + default: return nullptr; + } +} + + +/** \brief Release the parser instance related with a parser handle. */ +API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) +{ + MU_TRY + ParserTag* p = static_cast(a_hParser); + delete p; + MU_CATCH +} + + +API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", p->GetVersion().c_str()); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetVersion().c_str()); +#endif + + return s_tmpOutBuf; + MU_CATCH + return _T(""); +} + + +/** \brief Evaluate the expression. */ +API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(); + MU_CATCH + return 0; +} + + +API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) +{ + MU_TRY + if (nNum == nullptr) + throw std::runtime_error("Argument is null!"); + + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(*nNum); + MU_CATCH + return 0; +} + + +API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->Eval(a_res, nSize); + MU_CATCH +} + + +API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetExpr(a_szExpr); + MU_CATCH +} + + +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->RemoveVar(a_szName); + MU_CATCH +} + + +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearVar(); + MU_CATCH +} + + +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearConst(); + MU_CATCH +} + + +/** \brief Clear all user defined operators. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearOprt(); + MU_CATCH +} + + +API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearFun(); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun0_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData0_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData1_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData2_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData3_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData4_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData5_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData6_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData7_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData8_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData9_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData10_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData0_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData1_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData2_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData3_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData4_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData5_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData6_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData7_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData8_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData9_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData10_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun4_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun5_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData1_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData2_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData3_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData4_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData5_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineMultFunUserData(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFunUserData_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + + +API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineConst(a_szName, a_fVal); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineStrConst(a_szName, a_szVal); + MU_CATCH +} + + +API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", p->GetExpr().c_str()); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetExpr().c_str()); +#endif + + return s_tmpOutBuf; + MU_CATCH + + return _T(""); +} + + +API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + MU_CATCH +} + +// Signature changed to fix #125 (https://github.com/beltoforion/muparser/issues/125) +API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, int a_iPrec, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprt(a_szName, a_pOprt, a_iPrec, a_bAllowOpt != 0); + MU_CATCH +} + +// Define character sets for identifiers +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineNameChars(a_szCharset); +} + + +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprtChars(a_szCharset); +} + + +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprtChars(a_szCharset); +} + + +/** \brief Get the number of variables defined in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar +*/ +API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + + +/** \brief Return a variable that is used in an expression. + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. +*/ +API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + MU_CATCH + + * a_szName = 0; + *a_pVar = 0; +} + + +/** \brief Get the number of variables used in the expression currently set in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar + */ +API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + + +/** \brief Return a variable that is used in an expression. + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. + + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow +*/ +API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + MU_CATCH + + * a_szName = 0; + *a_pVar = 0; +} + + +/** \brief Return the number of constants defined in a parser. */ +API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + return (int)ValMap.size(); + MU_CATCH + + return 0; // never reached +} + + +API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetArgSep(cArgSep); + MU_CATCH +} + + +API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ResetLocale(); + MU_CATCH +} + + +API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetDecSep(cDecSep); + MU_CATCH +} + + +API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetThousandsSep(cThousandsSep); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Retrieve name and value of a single parser constant. + \param a_hParser [in] a valid parser handle + \param a_iVar [in] Index of the constant to query + \param a_pszName [out] pointer to a null terminated string with the constant name + \param [out] The constant value + */ +API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_fVal) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + + if (a_iVar >= ValMap.size()) + { + *a_pszName = 0; + *a_fVal = 0; + return; + } + + mu::valmap_type::const_iterator item; + item = ValMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_pszName = &szName[0]; + *a_fVal = item->second; + return; + + MU_CATCH + + * a_pszName = 0; + *a_fVal = 0; +} + + +/** \brief Add a custom value recognition function. */ +API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t a_pFun) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->AddValIdent(a_pFun); + MU_CATCH +} + + +/** \brief Query if an error occurred. + + After querying the internal error bit will be reset. So a consecutive call + will return false. +*/ +API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) +{ + bool bError(AsParserTag(a_hParser)->bError); + AsParserTag(a_hParser)->bError = false; + return bError; +} + + +/** \brief Reset the internal error flag. */ +API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) +{ + AsParserTag(a_hParser)->bError = false; +} + + +API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) +{ + AsParserTag(a_hParser)->errHandler = a_pHandler; +} + + +/** \brief Return the message associated with the last error. */ +API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t* pMsg = p->exc.GetMsg().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", pMsg); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pMsg); +#endif + + return s_tmpOutBuf; +} + + +/** \brief Return the message associated with the last error. */ +API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t* pToken = p->exc.GetToken().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", pToken); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pToken); +#endif + + return s_tmpOutBuf; +} + + +/** \brief Return the code associated with the last error. +*/ +API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) +{ + return AsParserTag(a_hParser)->exc.GetCode(); +} + + +/** \brief Return the position associated with the last error. */ +API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) +{ + return (int)AsParserTag(a_hParser)->exc.GetPos(); +} + + +API_EXPORT(muFloat_t*) mupCreateVar() +{ + return new muFloat_t(0); +} + + +API_EXPORT(void) mupReleaseVar(muFloat_t* ptr) +{ + delete ptr; +} + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif // MUPARSER_DLL diff --git a/src/muParserError.cpp b/src/muParserError.cpp index 960e48a..4312dc6 100644 --- a/src/muParserError.cpp +++ b/src/muParserError.cpp @@ -1,335 +1,336 @@ -/* - - _____ __ _____________ _______ ______ ___________ - / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ - | 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 - -#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 +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 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 "muParserError.h" +#include + +#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!"); + m_vErrMsg[ecBYTECODE_IMPORT_EXPORT_DISABLED] = _T("Bytecode cannot be imported or exported when parser is using a variable factory!"); + + 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/src/muParserInt.cpp b/src/muParserInt.cpp index 76189e9..33a1db8 100644 --- a/src/muParserInt.cpp +++ b/src/muParserInt.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -51,8 +51,8 @@ namespace mu 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::BitAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } + value_type ParserInt::BitOr(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); } @@ -252,10 +252,11 @@ namespace mu DefineInfixOprt(_T("-"), UnaryMinus); DefineInfixOprt(_T("!"), Not); - DefineOprt(_T("&"), LogAnd, prLOGIC); - DefineOprt(_T("|"), LogOr, prLOGIC); - DefineOprt(_T("&&"), And, prLOGIC); - DefineOprt(_T("||"), Or, prLOGIC); + DefineOprt(_T("&"), BitAnd, prBAND); + DefineOprt(_T("|"), BitOr, prBOR); + + DefineOprt(_T("&&"), And, prLAND); + DefineOprt(_T("||"), Or, prLOR); DefineOprt(_T("<"), Less, prCMP); DefineOprt(_T(">"), Greater, prCMP); diff --git a/src/muParserTest.cpp b/src/muParserTest.cpp index a86224b..705cea5 100644 --- a/src/muParserTest.cpp +++ b/src/muParserTest.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2023 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -63,6 +63,7 @@ namespace mu AddTest(&ParserTester::TestStrArg); AddTest(&ParserTester::TestBulkMode); AddTest(&ParserTester::TestOptimizer); + AddTest(&ParserTester::TestLocalization); ParserTester::c_iCount = 0; } @@ -232,6 +233,7 @@ namespace mu 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); @@ -313,12 +315,17 @@ namespace mu iStat += EqnTest(_T("1 && 0"), 0, true); iStat += EqnTest(_T("(aa)"), 1, true); iStat += EqnTest(_T("(ab)"), 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); + // test precedence of logic operators (should be like c++) + iStat += EqnTest(_T("0 && 0 || 1"), 1, true); + iStat += EqnTest(_T("0 && 1 || 0"), 0, true); + iStat += EqnTest(_T("1 && 0 || 0"), 0, true); + iStat += EqnTest(_T("1 && 1 || 0"), 1, true); + iStat += EqnTest(_T("1 && 0 + 1"), 1, true); + iStat += EqnTest(_T("1 && 1 - 1"), 0, true); // Assignment operator iStat += EqnTest(_T("a = b"), 2, true); @@ -444,93 +451,93 @@ namespace mu // 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) + 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(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(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, 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) + 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; + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; return iStat; } @@ -900,6 +907,7 @@ namespace mu 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); + iStat += EqnTest(_T("1n"), 1e-9, true); // can postfix operators "m" und "meg" be told apart properly? iStat += EqnTest(_T("2*3000meg+2"), 2 * 3e9 + 2, true); @@ -1227,14 +1235,27 @@ namespace mu return iStat; } + int ParserTester::TestLocalization() + { + int iStat = 0; + mu::console() << _T("testing localization..."); + + iStat += EqnTestLocalized(_T("1,2"), 1.2, true); + + 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; @@ -1297,6 +1318,7 @@ namespace mu 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(); @@ -1328,7 +1350,7 @@ namespace mu } //--------------------------------------------------------------------------- - /** \brief Evaluate a tet expression. + /** \brief Evaluate a test expression. \return 1 in case of a failure, 0 otherwise. */ @@ -1382,6 +1404,53 @@ namespace mu return 0; } + //--------------------------------------------------------------------------- + /** \brief Evaluate a test expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTestLocalized(const string_type& a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + + try + { + Parser p; + value_type var[2] = { 1, 2 }; + + // variable + p.SetDecSep(','); + p.SetArgSep(';'); + p.SetThousandsSep('.'); + + p.DefineVar(_T("a"), &var[0]); + p.DefineVar(_T("b"), &var[1]); + p.SetExpr(a_str); + + auto result = p.Eval(); + + if (fabs(result - a_fRes) > 0.0000000001) + throw std::runtime_error("incorrect result (first 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. @@ -1458,6 +1527,7 @@ namespace mu 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); @@ -1483,6 +1553,7 @@ namespace mu p1->DefinePostfixOprt(_T("{m}"), Milli); p1->DefinePostfixOprt(_T("{M}"), Mega); p1->DefinePostfixOprt(_T("m"), Milli); + p1->DefinePostfixOprt(_T("n"), [](double value){return value * 1E-9;}); p1->DefinePostfixOprt(_T("meg"), Mega); p1->DefinePostfixOprt(_T("#"), times3); p1->DefinePostfixOprt(_T("'"), sqr); @@ -1541,17 +1612,7 @@ namespace mu // 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::has_infinity) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - { - bCloseEnough &= (fabs(fVal[i]) != numeric_limits::infinity()); - } + bCloseEnough &= std::isfinite(fVal[i]); } iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; diff --git a/src/muParserTokenReader.cpp b/src/muParserTokenReader.cpp index 312a0c5..34c8800 100644 --- a/src/muParserTokenReader.cpp +++ b/src/muParserTokenReader.cpp @@ -5,7 +5,7 @@ | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |__|_| /____/| __(____ /__| /____ >\___ >__| \/ |__| \/ \/ \/ - Copyright (C) 2004 - 2021 Ingo Berg + Copyright (C) 2004 - 2022 Ingo Berg Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: