fish-shell/muparser/samples/example2/example2.c
Kurtis Rader d247c121a2 Check-in MuParser source
First step in fixing issue #3157 is to check-in the source code and hook
it into our build system.

The inclusion of the MuParser source adds the MIT License to those that
apply to fish. Update our documentation to reflect that fact.

The MuParser documentation is at
http://beltoforion.de/article.php?a=muparser.  The source was downloaded
from https://github.com/beltoforion/muparser/releases. It is also hosted
on Github, https://github.com/beltoforion/muparser/. I did not download
it from Github because that source contained just a couple of cleanup
changes which don't affect its behavior.
2017-08-23 14:43:45 -07:00

443 lines
13 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include "muParserDLL.h"
#define PARSER_CONST_PI 3.141592653589793238462643
#define PARSER_CONST_E 2.718281828459045235360287
#define PARSER_MAXVARS 10
#ifndef _UNICODE
#define _T(x) x
#define myprintf printf
#define mystrlen strlen
#define myfgets fgets
#define mystrcmp strcmp
#else
#define _T(x) L ##x
#define myprintf wprintf
#define mystrlen wcslen
#define myfgets fgetws
#define mystrcmp wcscmp
#endif
extern void CalcBulk();
//---------------------------------------------------------------------------
// Callbacks for postfix operators
muFloat_t Mega(muFloat_t a_fVal)
{
return a_fVal * 1.0e6;
}
muFloat_t Milli(muFloat_t a_fVal)
{
return a_fVal / 1.0e3;
}
muFloat_t ZeroArg()
{
myprintf(_T("i'm a function without arguments.\n"));
return 123;
}
muFloat_t BulkTest(int nBulkIdx, int nThreadIdx, muFloat_t v1)
{
(void*)&nThreadIdx; // STFU compiler warning...
myprintf(_T("%d,%2.2f\n"), nBulkIdx, v1);
return v1 / (nBulkIdx + 1);
}
//---------------------------------------------------------------------------
// Callbacks for infix operators
muFloat_t Not(muFloat_t v) { return v == 0; }
//---------------------------------------------------------------------------
// Function callbacks
muFloat_t Rnd(muFloat_t v) { return v * rand() / (muFloat_t)(RAND_MAX + 1.0); }
muFloat_t SampleQuery(const muChar_t *szMsg)
{
if (szMsg)
{
myprintf(_T("%s\n"), szMsg);
}
return 999;
}
muFloat_t Sum(const muFloat_t *a_afArg, int a_iArgc)
{
muFloat_t fRes = 0;
int i = 0;
for (i = 0; i < a_iArgc; ++i)
fRes += a_afArg[i];
return fRes;
}
//---------------------------------------------------------------------------
// Binarty operator callbacks
muFloat_t Add(muFloat_t v1, muFloat_t v2)
{
return v1 + v2;
}
muFloat_t Mul(muFloat_t v1, muFloat_t v2)
{
return v1*v2;
}
//---------------------------------------------------------------------------
// Factory function for creating new parser variables
// This could as well be a function performing database queries.
muFloat_t* AddVariable(const muChar_t* a_szName, void *pUserData)
{
static muFloat_t afValBuf[PARSER_MAXVARS]; // I don't want dynamic allocation here
static int iVal = 0; // so i used this buffer
myprintf(_T("Generating new variable \"%s\" (slots left: %d; context pointer: 0x%x)\n"), a_szName, PARSER_MAXVARS - iVal, (int)pUserData);
afValBuf[iVal] = 0;
if (iVal >= PARSER_MAXVARS - 1)
{
myprintf(_T("Variable buffer overflow."));
return NULL;
}
return &afValBuf[iVal++];
}
//---------------------------------------------------------------------------
void Intro(muParserHandle_t hParser)
{
myprintf(_T(" __________ \n"));
myprintf(_T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n"));
myprintf(_T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n"));
myprintf(_T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"));
myprintf(_T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"));
myprintf(_T(" \\/ \\/ \\/ \\/ \n"));
myprintf(_T(" Version %s (DLL)\n"), mupGetVersion(hParser));
#ifdef _UNICODE
myprintf(_T(" Sample build with UNICODE support\n"));
#else
myprintf(_T(" Sample build with ASCII support\n"));
#endif
myprintf(_T(" (C) 2015 Ingo Berg\n"));
myprintf(_T("---------------------------------------\n"));
myprintf(_T("Commands:\n"));
myprintf(_T(" list var - list parser variables\n"));
myprintf(_T(" list exprvar - list expression variables\n"));
myprintf(_T(" list const - list all numeric parser constants\n"));
myprintf(_T(" locale de - switch to german locale\n"));
myprintf(_T(" locale en - switch to english locale\n"));
myprintf(_T(" locale reset - reset locale\n"));
myprintf(_T(" test bulk - test bulk mode\n"));
myprintf(_T(" quit - exits the parser\n\n"));
myprintf(_T("---------------------------------------\n"));
myprintf(_T("Constants:\n"));
myprintf(_T(" \"_e\" 2.718281828459045235360287\n"));
myprintf(_T(" \"_pi\" 3.141592653589793238462643\n"));
myprintf(_T("---------------------------------------\n"));
myprintf(_T("Please enter an expression:\n"));
}
//---------------------------------------------------------------------------
// Callback function for parser errors
void OnError(muParserHandle_t hParser)
{
myprintf(_T("\nError:\n"));
myprintf(_T("------\n"));
myprintf(_T("Message: \"%s\"\n"), mupGetErrorMsg(hParser));
myprintf(_T("Token: \"%s\"\n"), mupGetErrorToken(hParser));
myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
}
//---------------------------------------------------------------------------
void ListVar(muParserHandle_t a_hParser)
{
int iNumVar = mupGetVarNum(a_hParser);
int i = 0;
if (iNumVar == 0)
{
myprintf(_T("No variables defined\n"));
return;
}
myprintf(_T("\nExpression variables:\n"));
myprintf(_T("---------------------\n"));
myprintf(_T("Number: %d\n"), iNumVar);
for (i = 0; i < iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t* pVar = 0;
mupGetVar(a_hParser, i, &szName, &pVar);
myprintf(_T("Name: %s Address: [0x%x]\n"), szName, (long long)pVar);
}
}
//---------------------------------------------------------------------------
void ListExprVar(muParserHandle_t a_hParser)
{
muInt_t iNumVar = mupGetExprVarNum(a_hParser),
i = 0;
if (iNumVar == 0)
{
myprintf(_T("Expression dos not contain variables\n"));
return;
}
myprintf(_T("\nExpression variables:\n"));
myprintf(_T("---------------------\n"));
myprintf(_T("Expression: %s\n"), mupGetExpr(a_hParser));
myprintf(_T("Number: %d\n"), iNumVar);
for (i = 0; i < iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t* pVar = 0;
mupGetExprVar(a_hParser, i, &szName, &pVar);
myprintf(_T("Name: %s Address: [0x%x]\n"), szName, (long long)pVar);
}
}
//---------------------------------------------------------------------------
void ListConst(muParserHandle_t a_hParser)
{
muInt_t iNumVar = mupGetConstNum(a_hParser),
i = 0;
if (iNumVar == 0)
{
myprintf(_T("No constants defined\n"));
return;
}
myprintf(_T("\nParser constants:\n"));
myprintf(_T("---------------------\n"));
myprintf(_T("Number: %d"), iNumVar);
for (i = 0; i < iNumVar; ++i)
{
const muChar_t* szName = 0;
muFloat_t fVal = 0;
mupGetConst(a_hParser, i, &szName, &fVal);
myprintf(_T(" %s = %f\n"), szName, fVal);
}
}
//---------------------------------------------------------------------------
/** \brief Check for external keywords.
*/
int CheckKeywords(const muChar_t *a_szLine, muParserHandle_t a_hParser)
{
if (!mystrcmp(a_szLine, _T("quit")))
{
return -1;
}
else if (!mystrcmp(a_szLine, _T("list var")))
{
ListVar(a_hParser);
return 1;
}
else if (!mystrcmp(a_szLine, _T("list exprvar")))
{
ListExprVar(a_hParser);
return 1;
}
else if (!mystrcmp(a_szLine, _T("list const")))
{
ListConst(a_hParser);
return 1;
}
else if (!mystrcmp(a_szLine, _T("locale de")))
{
myprintf(_T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"));
mupSetArgSep(a_hParser, ';');
mupSetDecSep(a_hParser, ',');
mupSetThousandsSep(a_hParser, '.');
return 1;
}
else if (!mystrcmp(a_szLine, _T("locale en")))
{
myprintf(_T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"));
mupSetArgSep(a_hParser, ',');
mupSetDecSep(a_hParser, '.');
mupSetThousandsSep(a_hParser, 0);
return 1;
}
else if (!mystrcmp(a_szLine, _T("locale reset")))
{
myprintf(_T("Resetting locale\n"));
mupResetLocale(a_hParser);
return 1;
}
else if (!mystrcmp(a_szLine, _T("test bulk")))
{
myprintf(_T("Testing bulk mode\n"));
CalcBulk();
return 1;
}
return 0;
}
//---------------------------------------------------------------------------
void CalcBulk()
{
int nBulkSize = 200, i;
muFloat_t *x = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
muFloat_t *y = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
muFloat_t *r = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
muParserHandle_t hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
for (i = 0; i < nBulkSize; ++i)
{
x[i] = i;
y[i] = i;
r[i] = 0;
}
mupDefineVar(hParser, _T("x"), x);
mupDefineVar(hParser, _T("y"), y);
mupDefineBulkFun1(hParser, _T("bulktest"), BulkTest);
mupSetExpr(hParser, _T("bulktest(x+y)"));
mupEvalBulk(hParser, r, nBulkSize);
if (mupError(hParser))
{
myprintf(_T("\nError:\n"));
myprintf(_T("------\n"));
myprintf(_T("Message: %s\n"), mupGetErrorMsg(hParser));
myprintf(_T("Token: %s\n"), mupGetErrorToken(hParser));
myprintf(_T("Position: %d\n"), mupGetErrorPos(hParser));
myprintf(_T("Errc: %d\n"), mupGetErrorCode(hParser));
return;
}
for (i = 0; i < nBulkSize; ++i)
{
myprintf(_T("%d: bulkfun(%2.2f + %2.2f) = %2.2f\n"), i, x[i], y[i], r[i]);
x[i] = i;
y[i] = (muFloat_t)i / 10;
}
free(x);
free(y);
free(r);
}
//---------------------------------------------------------------------------
void Calc()
{
muChar_t szLine[100];
muFloat_t fVal = 0,
afVarVal[] = { 1, 2 }; // Values of the parser variables
muParserHandle_t hParser;
hParser = mupCreate(muBASETYPE_FLOAT); // initialize the parser
Intro(hParser);
// Set an error handler [optional]
// the only function that does not take a parser instance handle
mupSetErrorHandler(hParser, OnError);
//#define GERMAN_LOCALS
#ifdef GERMAN_LOCALS
mupSetArgSep(hParser, ';');
mupSetDecSep(hParser, ',');
mupSetThousandsSep(hParser, '.');
#else
mupSetArgSep(hParser, ',');
mupSetDecSep(hParser, '.');
#endif
// Set a variable factory
mupSetVarFactory(hParser, AddVariable, NULL);
// Define parser variables and bind them to C++ variables [optional]
mupDefineConst(hParser, _T("const1"), 1);
mupDefineConst(hParser, _T("const2"), 2);
mupDefineStrConst(hParser, _T("strBuf"), _T("Hallo welt"));
// Define parser variables and bind them to C++ variables [optional]
mupDefineVar(hParser, _T("a"), &afVarVal[0]);
mupDefineVar(hParser, _T("b"), &afVarVal[1]);
// Define postfix operators [optional]
mupDefinePostfixOprt(hParser, _T("M"), Mega, 0);
mupDefinePostfixOprt(hParser, _T("m"), Milli, 0);
// Define infix operator [optional]
mupDefineInfixOprt(hParser, _T("!"), Not, 0);
// Define functions [optional]
// mupDefineStrFun(hParser, "query", SampleQuery, 0); // Add an unoptimizeable function
mupDefineFun0(hParser, _T("zero"), ZeroArg, 0);
mupDefineFun1(hParser, _T("rnd"), Rnd, 0); // Add an unoptimizeable function
mupDefineFun1(hParser, _T("rnd2"), Rnd, 1);
mupDefineMultFun(hParser, _T("_sum"), Sum, 0); // "sum" is already a default function
// Define binary operators [optional]
mupDefineOprt(hParser, _T("add"), Add, 0, muOPRT_ASCT_LEFT, 0);
mupDefineOprt(hParser, _T("mul"), Mul, 1, muOPRT_ASCT_LEFT, 0);
while (myfgets(szLine, 99, stdin))
{
szLine[mystrlen(szLine) - 1] = 0; // overwrite the newline
switch (CheckKeywords(szLine, hParser))
{
case 0: break; // no keyword found; parse the line
case 1: continue; // A Keyword was found do not parse the line
case -1: return; // abort the application
}
mupSetExpr(hParser, szLine);
fVal = mupEval(hParser);
// Without an Error handler function
// you must use this for error treatment:
//if (mupError(hParser))
//{
// printf("\nError:\n");
// printf("------\n");
// printf("Message: %s\n", mupGetErrorMsg(hParser) );
// printf("Token: %s\n", mupGetErrorToken(hParser) );
// printf("Position: %s\n", mupGetErrorPos(hParser) );
// printf("Errc: %d\n", mupGetErrorCode(hParser) );
// continue;
//}
if (!mupError(hParser))
myprintf(_T("%f\n"), fVal);
} // while
// finalle free the parser ressources
mupRelease(hParser);
}
//---------------------------------------------------------------------------
int main(int argc, char *argv[])
{
// The next line is just for shutting up the compiler warning
// about unused variables without getting another warning about not
// beeing able to use type lists in function declarations.
myprintf(_T("Executing \"%s\" (argc=%d)\n"), argv[0], argc);
Calc();
printf(_T("done..."));
}