Build internal muparser more simply
[alexxy/gromacs.git] / src / external / muparser / samples / example2 / example2.c
1 /*
2
3          _____  __ _____________ _______  ______ ___________
4         /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
5    |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
6    |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
7                  \/      |__|       \/           \/     \/
8    Copyright (C) 2004 - 2020 Ingo Berg
9
10         Redistribution and use in source and binary forms, with or without modification, are permitted
11         provided that the following conditions are met:
12
13           * Redistributions of source code must retain the above copyright notice, this list of
14                 conditions and the following disclaimer.
15           * Redistributions in binary form must reproduce the above copyright notice, this list of
16                 conditions and the following disclaimer in the documentation and/or other materials provided
17                 with the distribution.
18
19         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20         IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22         CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23         DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24         DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25         IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26         OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <wchar.h>
34 #include <inttypes.h>
35
36 #include "muParserDLL.h"
37
38 #define PARSER_CONST_PI  3.141592653589793238462643
39 #define PARSER_CONST_E   2.718281828459045235360287
40 #define PARSER_MAXVARS          10
41
42 #ifndef _UNICODE
43         #define _T(x) x
44         #define myprintf printf
45         #define mystrlen strlen
46         #define myfgets fgets
47         #define mystrcmp strcmp
48 #else
49         #define _T(x) L ##x
50         #define myprintf wprintf
51         #define mystrlen wcslen
52         #define myfgets fgetws
53         #define mystrcmp wcscmp
54 #endif
55
56 static void CalcBulk(void);
57
58 //---------------------------------------------------------------------------
59 // Callbacks for postfix operators
60 static muFloat_t Mega(muFloat_t a_fVal)
61 {
62         return a_fVal * 1.0e6;
63 }
64
65 static muFloat_t Milli(muFloat_t a_fVal)
66 {
67         return a_fVal / 1.0e3;
68 }
69
70 static muFloat_t ZeroArg(void)
71 {
72         myprintf(_T("i'm a function without arguments.\n"));
73         return 123;
74 }
75
76 static muFloat_t BulkTest(int nBulkIdx, int nThreadIdx, muFloat_t v1)
77 {
78         myprintf(_T("%d,%2.2f\n"), nBulkIdx, v1);
79         return v1 / ((muFloat_t)nBulkIdx + 1);
80 }
81
82 //---------------------------------------------------------------------------
83 // Callbacks for infix operators
84 static muFloat_t Not(muFloat_t v) { return v == 0; }
85
86 //---------------------------------------------------------------------------
87 // Function callbacks
88 static muFloat_t Rnd(muFloat_t v) { return v * rand() / (muFloat_t)(RAND_MAX + 1.0); }
89
90 static muFloat_t Sum(const muFloat_t* a_afArg, int a_iArgc)
91 {
92         muFloat_t fRes = 0;
93         int i = 0;
94
95         for (i = 0; i < a_iArgc; ++i)
96                 fRes += a_afArg[i];
97
98         return fRes;
99 }
100
101 //---------------------------------------------------------------------------
102 // Binarty operator callbacks
103 static muFloat_t Add(muFloat_t v1, muFloat_t v2)
104 {
105         return v1 + v2;
106 }
107
108 static muFloat_t Mul(muFloat_t v1, muFloat_t v2)
109 {
110         return v1 * v2;
111 }
112
113 //---------------------------------------------------------------------------
114 // Factory function for creating new parser variables
115 // This could as well be a function performing database queries.
116 static muFloat_t* AddVariable(const muChar_t* a_szName, void* pUserData)
117 {
118         static muFloat_t afValBuf[PARSER_MAXVARS];  // I don't want dynamic allocation here
119         static int iVal = 0;                                            // so i used this buffer
120
121         myprintf(_T("Generating new variable \"%s\" (slots left: %d; context pointer: %") _T(PRIxPTR) _T(")\n"), a_szName, PARSER_MAXVARS - iVal, (intptr_t)pUserData);
122
123         afValBuf[iVal] = 0;
124         if (iVal >= PARSER_MAXVARS - 1)
125         {
126                 myprintf(_T("Variable buffer overflow."));
127                 return NULL;
128         }
129
130         return &afValBuf[iVal++];
131 }
132
133 //---------------------------------------------------------------------------
134 static void Intro(muParserHandle_t hParser)
135 {
136         myprintf(_T("                 __________                                       \n"));
137         myprintf(_T("    _____   __ __\\______   \\_____  _______  ______  ____ _______\n"));
138         myprintf(_T("   /     \\ |  |  \\|     ___/\\__  \\ \\_  __ \\/  ___/_/ __ \\\\_  __ \\ \n"));
139         myprintf(_T("  |  Y Y  \\|  |  /|    |     / __ \\_|  | \\/\\___ \\ \\  ___/ |  | \\/ \n"));
140         myprintf(_T("  |__|_|  /|____/ |____|    (____  /|__|  /____  > \\___  >|__|    \n"));
141         myprintf(_T("        \\/                       \\/            \\/      \\/         \n"));
142         myprintf(_T("  Version %s (DLL)\n"), mupGetVersion(hParser));
143 #ifdef _UNICODE
144         myprintf(_T("  Sample build with UNICODE support\n"));
145 #else
146         myprintf(_T("  Sample build with ASCII support\n"));
147 #endif
148         myprintf(_T("  (C) 2004 - 2020 Ingo Berg\n"));
149         myprintf(_T("---------------------------------------\n"));
150         myprintf(_T("Commands:\n"));
151         myprintf(_T("  list var     - list parser variables\n"));
152         myprintf(_T("  list exprvar - list expression variables\n"));
153         myprintf(_T("  list const   - list all numeric parser constants\n"));
154         myprintf(_T("  locale de    - switch to german locale\n"));
155         myprintf(_T("  locale en    - switch to english locale\n"));
156         myprintf(_T("  locale reset - reset locale\n"));
157         myprintf(_T("  test bulk    - test bulk mode\n"));
158         myprintf(_T("  quit         - exits the parser\n\n"));
159         myprintf(_T("---------------------------------------\n"));
160         myprintf(_T("Constants:\n"));
161         myprintf(_T("  \"_e\"   2.718281828459045235360287\n"));
162         myprintf(_T("  \"_pi\"  3.141592653589793238462643\n"));
163         myprintf(_T("---------------------------------------\n"));
164         myprintf(_T("Please enter an expression:\n"));
165 }
166
167 //---------------------------------------------------------------------------
168 // Callback function for parser errors
169 static void OnError(muParserHandle_t hParser)
170 {
171         myprintf(_T("\nError:\n"));
172         myprintf(_T("------\n"));
173         myprintf(_T("Message:  \"%s\"\n"), mupGetErrorMsg(hParser));
174         myprintf(_T("Token:    \"%s\"\n"), mupGetErrorToken(hParser));
175         myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
176         myprintf(_T("Errc:     %d\n"), mupGetErrorCode(hParser));
177 }
178
179 //---------------------------------------------------------------------------
180 static void ListVar(muParserHandle_t a_hParser)
181 {
182         int iNumVar = mupGetVarNum(a_hParser);
183         int i = 0;
184
185         if (iNumVar == 0)
186         {
187                 myprintf(_T("No variables defined\n"));
188                 return;
189         }
190
191         myprintf(_T("\nExpression variables:\n"));
192         myprintf(_T("---------------------\n"));
193         myprintf(_T("Number: %d\n"), iNumVar);
194
195         for (i = 0; i < iNumVar; ++i)
196         {
197                 const muChar_t* szName = 0;
198                 muFloat_t* pVar = 0;
199
200                 mupGetVar(a_hParser, i, &szName, &pVar);
201                 myprintf(_T("Name: %s    Address: [%") _T(PRIxPTR) _T("]\n"), szName, (uintptr_t)pVar);
202         }
203 }
204
205 //---------------------------------------------------------------------------
206 static void ListExprVar(muParserHandle_t a_hParser)
207 {
208         muInt_t iNumVar = mupGetExprVarNum(a_hParser),
209                 i = 0;
210
211         if (iNumVar == 0)
212         {
213                 myprintf(_T("Expression dos not contain variables\n"));
214                 return;
215         }
216
217         myprintf(_T("\nExpression variables:\n"));
218         myprintf(_T("---------------------\n"));
219         myprintf(_T("Expression: %s\n"), mupGetExpr(a_hParser));
220         myprintf(_T("Number: %d\n"), iNumVar);
221
222         for (i = 0; i < iNumVar; ++i)
223         {
224                 const muChar_t* szName = 0;
225                 muFloat_t* pVar = 0;
226
227                 mupGetExprVar(a_hParser, i, &szName, &pVar);
228                 myprintf(_T("Name: %s   Address: [%") _T(PRIxPTR) _T("]\n"), szName, (intptr_t)pVar);
229         }
230 }
231
232 //---------------------------------------------------------------------------
233 static void ListConst(muParserHandle_t a_hParser)
234 {
235         muInt_t iNumVar = mupGetConstNum(a_hParser),
236                 i = 0;
237
238         if (iNumVar == 0)
239         {
240                 myprintf(_T("No constants defined\n"));
241                 return;
242         }
243
244         myprintf(_T("\nParser constants:\n"));
245         myprintf(_T("---------------------\n"));
246         myprintf(_T("Number: %d"), iNumVar);
247
248         for (i = 0; i < iNumVar; ++i)
249         {
250                 const muChar_t* szName = 0;
251                 muFloat_t fVal = 0;
252
253                 mupGetConst(a_hParser, i, &szName, &fVal);
254                 myprintf(_T("  %s = %f\n"), szName, fVal);
255         }
256 }
257
258 //---------------------------------------------------------------------------
259 /** \brief Check for external keywords.
260 */
261 static int CheckKeywords(const muChar_t* a_szLine, muParserHandle_t a_hParser)
262 {
263         if (!mystrcmp(a_szLine, _T("quit")))
264         {
265                 return -1;
266         }
267         else if (!mystrcmp(a_szLine, _T("list var")))
268         {
269                 ListVar(a_hParser);
270                 return 1;
271         }
272         else if (!mystrcmp(a_szLine, _T("list exprvar")))
273         {
274                 ListExprVar(a_hParser);
275                 return 1;
276         }
277         else if (!mystrcmp(a_szLine, _T("list const")))
278         {
279                 ListConst(a_hParser);
280                 return 1;
281         }
282         else if (!mystrcmp(a_szLine, _T("locale de")))
283         {
284                 myprintf(_T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"));
285                 mupSetArgSep(a_hParser, ';');
286                 mupSetDecSep(a_hParser, ',');
287                 mupSetThousandsSep(a_hParser, '.');
288                 return 1;
289         }
290         else if (!mystrcmp(a_szLine, _T("locale en")))
291         {
292                 myprintf(_T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"));
293                 mupSetArgSep(a_hParser, ',');
294                 mupSetDecSep(a_hParser, '.');
295                 mupSetThousandsSep(a_hParser, 0);
296                 return 1;
297         }
298         else if (!mystrcmp(a_szLine, _T("locale reset")))
299         {
300                 myprintf(_T("Resetting locale\n"));
301                 mupResetLocale(a_hParser);
302                 return 1;
303         }
304         else if (!mystrcmp(a_szLine, _T("test bulk")))
305         {
306                 myprintf(_T("Testing bulk mode\n"));
307                 CalcBulk();
308                 return 1;
309         }
310
311         return 0;
312 }
313
314 //---------------------------------------------------------------------------
315 static void CalcBulk(void)
316 {
317         int nBulkSize = 200, i;
318         muFloat_t* x = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
319         muFloat_t* y = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
320         muFloat_t* r = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
321
322         muParserHandle_t hParser = mupCreate(muBASETYPE_FLOAT);              // initialize the parser
323
324         for (i = 0; i < nBulkSize; ++i)
325         {
326                 x[i] = i;
327                 y[i] = i;
328                 r[i] = 0;
329         }
330
331         mupDefineVar(hParser, _T("x"), x);
332         mupDefineVar(hParser, _T("y"), y);
333         mupDefineBulkFun1(hParser, _T("bulktest"), BulkTest);
334         mupSetExpr(hParser, _T("bulktest(x+y)"));
335         mupEvalBulk(hParser, r, nBulkSize);
336         if (mupError(hParser))
337         {
338                 myprintf(_T("\nError:\n"));
339                 myprintf(_T("------\n"));
340                 myprintf(_T("Message:  %s\n"), mupGetErrorMsg(hParser));
341                 myprintf(_T("Token:    %s\n"), mupGetErrorToken(hParser));
342                 myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
343                 myprintf(_T("Errc:     %d\n"), mupGetErrorCode(hParser));
344                 return;
345         }
346
347         for (i = 0; i < nBulkSize; ++i)
348         {
349                 myprintf(_T("%d: bulkfun(%2.2f + %2.2f) = %2.2f\n"), i, x[i], y[i], r[i]);
350                 x[i] = i;
351                 y[i] = (muFloat_t)i / 10;
352         }
353
354         free(x);
355         free(y);
356         free(r);
357 }
358
359 //---------------------------------------------------------------------------
360 static void Calc(void)
361 {
362         muChar_t szLine[100];
363         muFloat_t fVal = 0,
364                 afVarVal[] = { 1, 2 }; // Values of the parser variables
365         muParserHandle_t hParser;
366
367         hParser = mupCreate(muBASETYPE_FLOAT);              // initialize the parser
368         Intro(hParser);
369
370         // Set an error handler [optional]
371         // the only function that does not take a parser instance handle
372         mupSetErrorHandler(hParser, OnError);
373
374         //#define GERMAN_LOCALS
375 #ifdef GERMAN_LOCALS
376         mupSetArgSep(hParser, ';');
377         mupSetDecSep(hParser, ',');
378         mupSetThousandsSep(hParser, '.');
379 #else
380         mupSetArgSep(hParser, ',');
381         mupSetDecSep(hParser, '.');
382 #endif
383
384         // Set a variable factory
385         mupSetVarFactory(hParser, AddVariable, NULL);
386
387         // Define parser variables and bind them to C++ variables [optional]
388         mupDefineConst(hParser, _T("const1"), 1);
389         mupDefineConst(hParser, _T("const2"), 2);
390         mupDefineStrConst(hParser, _T("strBuf"), _T("Hallo welt"));
391
392         // Define parser variables and bind them to C++ variables [optional]
393         mupDefineVar(hParser, _T("a"), &afVarVal[0]);
394         mupDefineVar(hParser, _T("b"), &afVarVal[1]);
395
396         // Define postfix operators [optional]
397         mupDefinePostfixOprt(hParser, _T("M"), Mega, 0);
398         mupDefinePostfixOprt(hParser, _T("m"), Milli, 0);
399
400         // Define infix operator [optional]
401         mupDefineInfixOprt(hParser, _T("!"), Not, 0);
402
403         // Define functions [optional]
404         //  mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function 
405         mupDefineFun0(hParser, _T("zero"), ZeroArg, 0);
406         mupDefineFun1(hParser, _T("rnd"), Rnd, 0);             // Add an unoptimizeable function
407         mupDefineFun1(hParser, _T("rnd2"), Rnd, 1);
408         mupDefineMultFun(hParser, _T("_sum"), Sum, 0);  // "sum" is already a default function
409
410         // Define binary operators [optional]
411         mupDefineOprt(hParser, _T("add"), Add, 0, muOPRT_ASCT_LEFT, 0);
412         mupDefineOprt(hParser, _T("mul"), Mul, 1, muOPRT_ASCT_LEFT, 0);
413
414         while (myfgets(szLine, 99, stdin))
415         {
416                 szLine[mystrlen(szLine) - 1] = 0; // overwrite the newline
417
418                 switch (CheckKeywords(szLine, hParser))
419                 {
420                 case  0:  break;       // no keyword found; parse the line
421                 case  1:  continue;    // A Keyword was found do not parse the line
422                 case -1:  return;      // abort the application
423                 }
424
425                 mupSetExpr(hParser, szLine);
426
427                 fVal = mupEval(hParser);
428
429
430                 // Without an Error handler function 
431                 // you must use this for error treatment:
432                 //if (mupError(hParser))
433                 //{
434                 //  printf("\nError:\n");
435                 //  printf("------\n");
436                 //  printf("Message:  %s\n", mupGetErrorMsg(hParser) );
437                 //  printf("Token:    %s\n", mupGetErrorToken(hParser) );
438                 //  printf("Position: %s\n", mupGetErrorPos(hParser) );
439                 //  printf("Errc:     %d\n", mupGetErrorCode(hParser) );
440                 //  continue;
441                 //}
442
443                 if (!mupError(hParser))
444                         myprintf(_T("%f\n"), fVal);
445
446         } // while 
447
448         // finally free the parser resources
449         mupRelease(hParser);
450 }
451
452 //---------------------------------------------------------------------------
453 int main(int argc, char* argv[])
454 {
455         // The next line is just for shutting up the compiler warning
456         // about unused variables without getting another warning about not
457         // being able to use type lists in function declarations.
458         myprintf(_T("Executing \"%s\" (argc=%d)\n"), argv[0], argc);
459         Calc();
460         printf(_T("done..."));
461 }