mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-13 21:43:16 +08:00
443 lines
13 KiB
C
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..."));
|
||
|
}
|