mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
This commit is contained in:
284
Library/ccalc-0.5.1/lexer.c
Normal file
284
Library/ccalc-0.5.1/lexer.c
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
Universal lexical analiser implementation
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include "lexer.h"
|
||||
|
||||
//#define MY_DEBUG 1
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
/* Uppercase translation table for the Win1251 charset */
|
||||
const char Win1251UpcaseTbl[] =
|
||||
"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
|
||||
"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
|
||||
" !\042#$%&'()*+,-./0123456789:;<=>?"
|
||||
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
|
||||
"`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177"
|
||||
"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
|
||||
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
|
||||
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
|
||||
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
|
||||
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
||||
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
|
||||
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
||||
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
|
||||
|
||||
char Win1251RusLetters[] =
|
||||
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
||||
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
|
||||
"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
|
||||
"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377";
|
||||
|
||||
|
||||
hqCharType Win1251NameTbl[256];
|
||||
int win1251nametbl_initialized = 0;
|
||||
|
||||
int FindSymbol( SymbolRec **SymTable, const char *str, int *nchars );
|
||||
|
||||
// initializations
|
||||
|
||||
void InitCharTypeTable( hqCharType *CharTypeTable, int CharTypes )
|
||||
{
|
||||
int ch;
|
||||
#ifdef MY_DEBUG
|
||||
printf( "CharTypeTable = 0x%X; CharTypes = %d\n", (unsigned)CharTypeTable,
|
||||
CharTypes );
|
||||
#endif
|
||||
memset( CharTypeTable, CH_UNKNOWN, 256 * sizeof(hqCharType) );
|
||||
|
||||
CharTypeTable[0] = CH_FINAL;
|
||||
|
||||
if (CharTypes & CH_SEPARAT) {
|
||||
CharTypeTable[' '] = CH_SEPARAT;
|
||||
CharTypeTable[9] = CH_SEPARAT;
|
||||
CharTypeTable[13] = CH_SEPARAT;
|
||||
CharTypeTable[10] = CH_SEPARAT;
|
||||
}
|
||||
|
||||
if (CharTypes & CH_QUOTE) {
|
||||
CharTypeTable['\''] = CH_QUOTE;
|
||||
}
|
||||
|
||||
if (CharTypes & CH_LETTER) {
|
||||
for (ch='A'; ch<='Z'; ch++)
|
||||
CharTypeTable[ch] = CH_LETTER;
|
||||
for (ch='a'; ch<='z'; ch++)
|
||||
CharTypeTable[ch] = CH_LETTER;
|
||||
CharTypeTable['_'] = CH_LETTER;
|
||||
}
|
||||
|
||||
if (CharTypes & CH_DIGIT) {
|
||||
for (ch='0'; ch<='9'; ch++)
|
||||
CharTypeTable[ch] = CH_DIGIT;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeTableAddChars( hqCharType *CharTypeTable, char *Symbols,
|
||||
hqCharType CharType )
|
||||
{
|
||||
while (*Symbols)
|
||||
CharTypeTable[ (uchar) *Symbols++] = CharType;
|
||||
}
|
||||
|
||||
void UpcaseWin1251Str( char *Str )
|
||||
{
|
||||
while (( *Str = Win1251UpcaseTbl[ (uchar) *Str ] ))
|
||||
++Str;
|
||||
}
|
||||
|
||||
|
||||
// hqLexer implementation
|
||||
|
||||
#define CHARTYPEPP lexer->CharTypeTable[ (uchar) *++(lexer->SS) ]
|
||||
#define CHARTYPE lexer->CharTypeTable[ (uchar) *lexer->SS ]
|
||||
|
||||
int Lexer_SetParseString( hqLexer *lexer, const char *str )
|
||||
{
|
||||
lexer->PrevTokenType = TOK_NONE;
|
||||
if ( !str || !*str )
|
||||
return 0;
|
||||
|
||||
lexer->SS = str;
|
||||
lexer->CharType = CHARTYPE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
hqTokenType Lexer_GetNextToken( hqLexer *lexer )
|
||||
{
|
||||
hqTokenType result = TOK_ERROR;
|
||||
|
||||
next_token:
|
||||
|
||||
while ( lexer->CharType == CH_SEPARAT )
|
||||
lexer->CharType = CHARTYPEPP;
|
||||
|
||||
switch ( lexer->CharType ) {
|
||||
case CH_FINAL:
|
||||
result = TOK_FINAL;
|
||||
break;
|
||||
case CH_LETTER:
|
||||
lexer->Name = lexer->SS;
|
||||
do {
|
||||
lexer->CharType = CHARTYPEPP;
|
||||
} while (lexer->CharType <= CH_DIGIT);
|
||||
lexer->NameLen = lexer->SS - lexer->Name;
|
||||
result = TOK_NAME;
|
||||
break;
|
||||
case CH_DIGIT: {
|
||||
char *NewSS, ch = *lexer->SS, nch = *(lexer->SS+1);
|
||||
int intreaded = 0;
|
||||
// Readind hex number
|
||||
if ( ch == '0' && nch == 'x' ) {
|
||||
lexer->IntValue = strtol( lexer->SS, &NewSS, 16 );
|
||||
intreaded = 1;
|
||||
}
|
||||
// Readind oct number
|
||||
if ( ch == '0' && nch >= '0' && nch <= '9' ) {
|
||||
lexer->IntValue = strtol( lexer->SS, &NewSS, 8 );
|
||||
intreaded = 1;
|
||||
}
|
||||
|
||||
if (intreaded == 1) {
|
||||
if ( lexer->SS != NewSS ) {
|
||||
lexer->SS = NewSS;
|
||||
if (lexer->NoIntegers) {
|
||||
lexer->ExtValue = lexer->IntValue;
|
||||
result = TOK_FLOAT;
|
||||
} else
|
||||
result = TOK_INT;
|
||||
lexer->CharType = CHARTYPE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Readind dec number
|
||||
lexer->ExtValue = strtod( lexer->SS, &NewSS );
|
||||
if ( lexer->SS != NewSS ) {;
|
||||
lexer->SS = NewSS;
|
||||
if ( !lexer->NoIntegers
|
||||
&& lexer->ExtValue<=INT_MAX
|
||||
&& lexer->ExtValue>=INT_MAX
|
||||
&& (double)( lexer->IntValue = (uchar) lexer->ExtValue )
|
||||
== lexer->ExtValue ) {
|
||||
result = TOK_INT;
|
||||
} else
|
||||
result = TOK_FLOAT;
|
||||
lexer->CharType = CHARTYPE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CH_SYMBOL: {
|
||||
int nchars;
|
||||
int i = FindSymbol( lexer->SymTable, lexer->SS, &nchars );
|
||||
if (i >= 0) {
|
||||
lexer->SS += nchars;
|
||||
if (i == lexer->cssn) {
|
||||
char comend = *lexer->ComEnd;
|
||||
char comendpp = *(lexer->ComEnd+1);
|
||||
while ( *lexer->SS ) {
|
||||
if ( *lexer->SS == comend
|
||||
&&
|
||||
( comendpp == '\0' || *(lexer->SS+1) == comendpp )
|
||||
) {
|
||||
++lexer->SS;
|
||||
if (comendpp != '\0')
|
||||
++lexer->SS;
|
||||
lexer->CharType = CHARTYPE;
|
||||
goto next_token;
|
||||
}
|
||||
++lexer->SS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
lexer->CharType = CHARTYPE;
|
||||
lexer->IntValue = i;
|
||||
result = TOK_SYMBOL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CH_QUOTE:
|
||||
lexer->Name = ++(lexer->SS);
|
||||
while ( lexer->CharTypeTable[ (uchar)*lexer->SS ] != CH_QUOTE
|
||||
&& *(lexer->SS) != '\0' )
|
||||
++lexer->SS;
|
||||
if ( CHARTYPE == CH_QUOTE ) {
|
||||
lexer->NameLen = lexer->SS - lexer->Name;
|
||||
++lexer->SS;
|
||||
lexer->CharType = CHARTYPE;
|
||||
result = TOK_STRING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return lexer->PrevTokenType = result;
|
||||
}
|
||||
|
||||
const char* Lexer_GetCurrentPos( hqLexer *lexer )
|
||||
{
|
||||
return lexer->SS;
|
||||
}
|
||||
|
||||
// misc functions
|
||||
|
||||
void PrepareSymTable( SymbolRec **SymTable, char *symbols )
|
||||
{
|
||||
int i = 0, nchars = 1;
|
||||
memset( SymTable, 0, 256 * sizeof(void*) );
|
||||
while (*symbols) {
|
||||
if (*symbols=='\033') {
|
||||
nchars = *++symbols;
|
||||
++symbols;
|
||||
} else {
|
||||
SymbolRec **RecList = SymTable + *symbols;
|
||||
SymbolRec *Rec = *RecList;
|
||||
int count = 0;
|
||||
while ( Rec ) {
|
||||
++count;
|
||||
if ( Rec->More )
|
||||
++Rec;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ( Rec ) {
|
||||
*RecList = (SymbolRec*)
|
||||
realloc( *RecList, (count+1)*sizeof(SymbolRec) );
|
||||
Rec = *RecList + count;
|
||||
(Rec-1)->More = 1;
|
||||
} else {
|
||||
*RecList = (SymbolRec*) malloc( sizeof(SymbolRec) );
|
||||
Rec = *RecList;
|
||||
}
|
||||
strncpy( Rec->Sym, symbols, 4 );
|
||||
Rec->Len = (char) nchars;
|
||||
Rec->Index = (char) i;
|
||||
Rec->More = 0;
|
||||
symbols += nchars;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FindSymbol( SymbolRec **SymTable, const char *str, int *nchars )
|
||||
{
|
||||
SymbolRec *Rec = SymTable[ (int)*str ];
|
||||
while ( Rec ) {
|
||||
if ( (Rec->Len == 1 && Rec->Sym[0] == str[0])
|
||||
||
|
||||
(Rec->Len == 2 && Rec->Sym[0] == str[0] && Rec->Sym[1] == str[1])
|
||||
||
|
||||
(Rec->Len == 3 && Rec->Sym[0] == str[0] && Rec->Sym[1] == str[1]
|
||||
&& Rec->Sym[2] == str[2])
|
||||
) {
|
||||
*nchars = Rec->Len;
|
||||
return Rec->Index;
|
||||
}
|
||||
Rec = ( Rec->More ) ? Rec + 1 : NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
79
Library/ccalc-0.5.1/lexer.h
Normal file
79
Library/ccalc-0.5.1/lexer.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Universal lexical analiser by hq_software
|
||||
*/
|
||||
|
||||
#ifndef __LEXER_HPP__
|
||||
#define __LEXER_HPP__
|
||||
|
||||
#include "pack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
typedef enum {
|
||||
CH_LETTER = 0x01, CH_DIGIT = 0x02, CH_SEPARAT = 0x04,
|
||||
CH_SYMBOL = 0x08, CH_QUOTE = 0x10,
|
||||
CH_UNKNOWN= 0x7E, CH_FINAL = 0x7F
|
||||
} hqCharType;
|
||||
|
||||
typedef enum {
|
||||
TOK_ERROR, TOK_NONE, TOK_FINAL, TOK_INT, TOK_FLOAT, TOK_SYMBOL,
|
||||
TOK_NAME, TOK_STRING
|
||||
} hqTokenType;
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct {
|
||||
char Sym[4];
|
||||
char Len;
|
||||
char Index;
|
||||
char More;
|
||||
} SymbolRec;
|
||||
|
||||
typedef struct {
|
||||
// input params
|
||||
const char *SS;
|
||||
hqCharType *CharTypeTable;
|
||||
SymbolRec **SymTable;
|
||||
int NoIntegers;
|
||||
int cssn; // Comment Start Symbol Number. -1 if none
|
||||
char *ComEnd; // End of comment
|
||||
// output params
|
||||
const char *Name;
|
||||
size_t NameLen;
|
||||
double ExtValue;
|
||||
int IntValue;
|
||||
hqTokenType PrevTokenType;
|
||||
hqCharType CharType;
|
||||
} hqLexer;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* Main "API" */
|
||||
|
||||
int Lexer_SetParseString( hqLexer *lexer, const char *str );
|
||||
hqTokenType Lexer_GetNextToken( hqLexer *lexer );
|
||||
const char* Lexer_GetCurrentPos( hqLexer *lexer );
|
||||
|
||||
/* Misc */
|
||||
|
||||
void UpcaseWin1251Str( char *Str );
|
||||
void InitCharTypeTable( hqCharType *CharTypeTable, int CharTypes );
|
||||
|
||||
void TypeTableAddChars( hqCharType *CharTypeTable, char *Symbols,
|
||||
hqCharType CharType );
|
||||
|
||||
void PrepareSymTable( SymbolRec **SymTable, char *symbols );
|
||||
|
||||
//int IsEngWin1251RusName( char *Str );
|
||||
|
||||
extern char const Win1251UpcaseTbl[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LEXER_HPP__ */
|
679
Library/ccalc-0.5.1/mparser.c
Normal file
679
Library/ccalc-0.5.1/mparser.c
Normal file
@ -0,0 +1,679 @@
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mparser.h"
|
||||
|
||||
//#define MY_DEBUG 1
|
||||
|
||||
#ifndef M_E
|
||||
# define M_E 2.7182818284590452354
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
const double DblErR = -1.68736462823243E308;
|
||||
const double DblNiN = -1.68376462823243E308;
|
||||
|
||||
#if (defined(__WIN32) || defined(__WIN32__)) && defined(RUSSIAN)
|
||||
|
||||
char eBrackets [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eSyntax [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eInternal [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eExtraOp [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eInfinity [] = "#<23><><EFBFBD>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eInvArg [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eUnknFunc [] = "# %s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eExtrnFunc[] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eLogicErr [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eCalcErr [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eUnexpEnd [] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eExpVarRet[] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> return!";
|
||||
char eExpAssign[] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eValSizErr[] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!";
|
||||
char eInvPrmCnt[] = "#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||||
|
||||
#else
|
||||
|
||||
char eBrackets [] = "#Brackets not match!";
|
||||
char eSyntax [] = "#Syntax error!";
|
||||
char eInternal [] = "#Internal error!";
|
||||
char eExtraOp [] = "#Extra operation!";
|
||||
char eInfinity [] = "#Infinity somewhere!";
|
||||
char eInvArg [] = "#Invalid argument!";
|
||||
char eUnknFunc [] = "# %s - Unknown function/variable!";
|
||||
char eExtrnFunc[] = "#External function error!";
|
||||
char eLogicErr [] = "#Logical expression error!";
|
||||
char eCalcErr [] = "#Calculation error!";
|
||||
char eUnexpEnd [] = "#Unexpected end of script!";
|
||||
char eExpVarRet[] = "#Variable name or return expected!";
|
||||
char eExpAssign[] = "#Assignment expected!";
|
||||
char eValSizErr[] = "#Value too big for operation!";
|
||||
char eInvPrmCnt[] = "#Invalid parameters count for function call!";
|
||||
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
static double _neg_(double);
|
||||
static double _frac_(double);
|
||||
static double _trunc_(double);
|
||||
static double _sgn_(double);
|
||||
static double _neg_(double);
|
||||
static double _floor_(double);
|
||||
static double _ceil_(double);
|
||||
static char* _round_( int paramcnt, double *args, hqStrMap *strparams, double *result );
|
||||
|
||||
const Operation BrOp = { OP_OBR };
|
||||
const Operation NegOp = { OP_FUNC_ONEARG, (void*)&_neg_, 0, NULL };
|
||||
|
||||
const char OpPriorities[OP_FUNC_MULTIARG+1] = {
|
||||
5, 5, 5, 2, 2, 2, 2, 2, -1, -1, 0,
|
||||
3, 3, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 2, 2, 2, 1, 2, 0, 2,
|
||||
-1, 6, 6 };
|
||||
|
||||
char MathSymbols[] =
|
||||
"\033\002" "<<" ">>" "**" "<>" ">=" "<=" "&&" "||" "/*" ":="
|
||||
"\033\001" "(+-*/%$^~&|=><?:),;";
|
||||
|
||||
char StdSymbols[] = "+-/*^~()<>%$,?:=&|;";
|
||||
|
||||
hqCharType MathCharTypeTable[256];
|
||||
int initializations_performed = 0;
|
||||
|
||||
char func_names[] =
|
||||
"ATAN\000COS\000SIN\000TAN\000ABS\000"
|
||||
"EXP\000LN\000LG\000SQRT\000FRAC\000"
|
||||
"TRUNC\000FLOOR\000CEIL\000ROUND\000ASIN\000"
|
||||
"ACOS\000SGN\000NEG\000E\000PI\000";
|
||||
|
||||
/* Indexes of some functions in func_names[] array */
|
||||
#define FUNC_ROUND 13
|
||||
#define FUNC_E 18
|
||||
#define FUNC_PI 19
|
||||
|
||||
static char* CalcToObr( hqMathParser *parser );
|
||||
static char* Calc( hqMathParser *parser );
|
||||
static char* MathParser_ParseScript( hqMathParser* parser, double *result );
|
||||
static char* MathParser_ParseFormula( hqMathParser* parser, double *result );
|
||||
|
||||
double (*func_addresses[]) () = {
|
||||
&atan, &cos, &sin, &tan, &fabs,
|
||||
&exp, &log, &log10, &sqrt, &_frac_,
|
||||
&_trunc_, &_floor_, _ceil_, (double(*)(double)) &_round_, &asin,
|
||||
&acos, &_sgn_, &_neg_, NULL, NULL };
|
||||
|
||||
hqStrMap *IntFunctions;
|
||||
|
||||
SymbolRec *MathSymTable[256];
|
||||
|
||||
char errbuf[256];
|
||||
|
||||
// hqMathParser implementation
|
||||
|
||||
hqMathParser* MathParser_Create( char *MoreLetters )
|
||||
{
|
||||
hqMathParser *parser = calloc( 1, sizeof(hqMathParser) );
|
||||
if (!initializations_performed) {
|
||||
// init character tables
|
||||
InitCharTypeTable( MathCharTypeTable,
|
||||
CH_LETTER | CH_DIGIT | CH_SEPARAT | CH_QUOTE );
|
||||
TypeTableAddChars( MathCharTypeTable, StdSymbols, CH_SYMBOL );
|
||||
if (MoreLetters)
|
||||
TypeTableAddChars( MathCharTypeTable, MoreLetters, CH_LETTER );
|
||||
// init function maps
|
||||
PrepareSymTable( MathSymTable, MathSymbols );
|
||||
IntFunctions = Strmap_CreateFromChain( sizeof(void*),
|
||||
(char*)func_names,
|
||||
func_addresses );
|
||||
initializations_performed = 1;
|
||||
}
|
||||
parser->Lexer.NoIntegers = 1;
|
||||
parser->Lexer.SymTable = MathSymTable;
|
||||
parser->Lexer.CharTypeTable = MathCharTypeTable;
|
||||
parser->Lexer.cssn = 8;
|
||||
parser->Lexer.ComEnd = "*/";
|
||||
return parser;
|
||||
}
|
||||
|
||||
void MathParser_Destroy( hqMathParser* parser )
|
||||
{
|
||||
free( parser );
|
||||
}
|
||||
|
||||
static char* PrepareFormula( hqMathParser* parser )
|
||||
{
|
||||
int BrCnt = 0;
|
||||
const char *SS = parser->Lexer.SS;
|
||||
|
||||
// Brackets Matching
|
||||
while ( (!parser->script && *SS) || (parser->script && *SS != ';') ) {
|
||||
if (*SS=='(')
|
||||
++BrCnt;
|
||||
else if (*SS==')' && --BrCnt<0)
|
||||
goto brkerr;
|
||||
++SS;
|
||||
}
|
||||
if (BrCnt != 0)
|
||||
brkerr: return eBrackets;
|
||||
|
||||
parser->OpTop = 0;
|
||||
parser->ValTop = -1;
|
||||
parser->OpStack[0].OperType = OP_OBR;
|
||||
parser->ObrDist = 2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* MathParser_Parse( hqMathParser* parser, const char *Formula, double *result )
|
||||
{
|
||||
if (!Formula || !*Formula) {
|
||||
*result = 0.0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parser->script = *Formula == '#' && *(Formula+1) == '!'
|
||||
&& MathCharTypeTable[ (uchar)*(Formula+2) ] == CH_SEPARAT;
|
||||
|
||||
if ( parser->script )
|
||||
Formula += 3;
|
||||
|
||||
Lexer_SetParseString( &parser->Lexer, Formula );
|
||||
|
||||
return ( parser->script )
|
||||
?
|
||||
MathParser_ParseScript( parser, result )
|
||||
:
|
||||
MathParser_ParseFormula( parser, result );
|
||||
}
|
||||
|
||||
static char* MathParser_ParseFormula( hqMathParser* parser, double *result )
|
||||
{
|
||||
char *ErrorMsg;
|
||||
hqTokenType ToTi;
|
||||
|
||||
if ( (ErrorMsg = PrepareFormula( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
|
||||
ToTi = Lexer_GetNextToken( &parser->Lexer );
|
||||
for (;;) {
|
||||
--parser->ObrDist;
|
||||
switch (ToTi) {
|
||||
case TOK_ERROR:
|
||||
return eSyntax;
|
||||
case TOK_FINAL:
|
||||
formulaend: if ( (ErrorMsg = CalcToObr( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
goto getout;
|
||||
case TOK_FLOAT:
|
||||
parser->ValStack[++parser->ValTop] = parser->Lexer.ExtValue;
|
||||
break;
|
||||
case TOK_SYMBOL:
|
||||
switch ( parser->Lexer.IntValue ) {
|
||||
case OP_OBR: // (
|
||||
parser->OpStack[++parser->OpTop] = BrOp;
|
||||
parser->ObrDist = 2;
|
||||
break;
|
||||
case OP_CBR: // )
|
||||
if ( (ErrorMsg = CalcToObr( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
break;
|
||||
case OP_COMMA: { // ,
|
||||
Operation *pOp;
|
||||
if ( (ErrorMsg = CalcToObr( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
if ( (pOp = &parser->OpStack[parser->OpTop])->OperType
|
||||
== OP_FUNC_MULTIARG ) {
|
||||
parser->OpStack[++parser->OpTop] = BrOp;
|
||||
parser->ObrDist = 2;
|
||||
} else
|
||||
return eSyntax;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Operation Op;
|
||||
Op.OperType = (OperType_t) parser->Lexer.IntValue;
|
||||
switch (Op.OperType) {
|
||||
case OP_FORMULAEND:
|
||||
if (parser->script)
|
||||
goto formulaend;
|
||||
else
|
||||
return eSyntax;
|
||||
case OP_ADD:
|
||||
if (parser->ObrDist >= 1)
|
||||
goto next_tok;
|
||||
break;
|
||||
case OP_SUB:
|
||||
if (parser->ObrDist >= 1) {
|
||||
parser->OpStack[++parser->OpTop] = NegOp;
|
||||
goto next_tok;
|
||||
}
|
||||
break;
|
||||
case OP_LOGIC:
|
||||
case OP_LOGIC_SEP:
|
||||
parser->ObrDist = 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while ( OpPriorities[ Op.OperType ]
|
||||
<=
|
||||
OpPriorities[ parser->OpStack[parser->OpTop].OperType ] ) {
|
||||
if ( (ErrorMsg = Calc( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
}
|
||||
parser->OpStack[++parser->OpTop] = Op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TOK_NAME: {
|
||||
Operation Op;
|
||||
double *value, dblval;
|
||||
void **func;
|
||||
int funcnum, /*i,*/ namelen = parser->Lexer.NameLen;
|
||||
|
||||
// const char *SS = parser->Lexer.Name;
|
||||
// for (i = namelen; i>0; --i)
|
||||
// *SS++ = Win1251UpcaseTbl[ (int) (uchar) *SS ];
|
||||
|
||||
funcnum = StrMap_LenIndexOf( IntFunctions,
|
||||
parser->Lexer.Name,
|
||||
parser->Lexer.NameLen,
|
||||
(void**) &func );
|
||||
if ( funcnum >= 0 ) {
|
||||
Op.Func = *func;
|
||||
switch ( funcnum ) {
|
||||
case FUNC_E:
|
||||
parser->ValStack[++parser->ValTop] = M_E;
|
||||
break;
|
||||
case FUNC_PI:
|
||||
parser->ValStack[++parser->ValTop] = M_PI;
|
||||
break;
|
||||
case FUNC_ROUND:
|
||||
Op.OperType = OP_FUNC_MULTIARG;
|
||||
Op.PrevValTop = parser->ValTop;
|
||||
Op.StrParams = NULL;
|
||||
parser->OpStack[++parser->OpTop] = Op;
|
||||
break;
|
||||
default:// Internal function
|
||||
Op.OperType = OP_FUNC_ONEARG;
|
||||
parser->OpStack[++parser->OpTop] = Op;
|
||||
}
|
||||
} else if (parser->Parameters
|
||||
&&
|
||||
StrMap_LenIndexOf( parser->Parameters,
|
||||
parser->Lexer.Name,
|
||||
parser->Lexer.NameLen,
|
||||
(void**) &value ) >= 0
|
||||
) {
|
||||
if (*value==DblErR) {
|
||||
return eInternal;
|
||||
} else
|
||||
parser->ValStack[++parser->ValTop] = *value;
|
||||
} else if (parser->ExtFunctions
|
||||
&&
|
||||
StrMap_LenIndexOf( parser->ExtFunctions,
|
||||
parser->Lexer.Name,
|
||||
parser->Lexer.NameLen,
|
||||
(void**) &func ) >= 0
|
||||
) {
|
||||
Op.Func = *func;
|
||||
Op.OperType = OP_FUNC_MULTIARG;
|
||||
Op.PrevValTop = parser->ValTop;
|
||||
Op.StrParams = NULL;
|
||||
parser->OpStack[++parser->OpTop] = Op;
|
||||
} else if (parser->VarParams
|
||||
&&
|
||||
StrMap_LenIndexOf( parser->VarParams,
|
||||
parser->Lexer.Name,
|
||||
parser->Lexer.NameLen,
|
||||
(void**) &value ) >= 0
|
||||
) {
|
||||
if (*value==DblErR) {
|
||||
return eInternal;
|
||||
} else
|
||||
parser->ValStack[++parser->ValTop] = *value;
|
||||
} else if (parser->MoreParams
|
||||
&&
|
||||
(*parser->MoreParams)( parser->Lexer.Name,
|
||||
parser->Lexer.NameLen,
|
||||
&dblval,
|
||||
parser->ParamFuncParam )
|
||||
) {
|
||||
parser->ValStack[++parser->ValTop] = dblval;
|
||||
} else {
|
||||
char buf[256];
|
||||
strncpy( buf, parser->Lexer.Name, parser->Lexer.NameLen );
|
||||
buf[ parser->Lexer.NameLen ] = '\0';
|
||||
sprintf( errbuf, eUnknFunc, buf );
|
||||
return errbuf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TOK_STRING: {
|
||||
Operation *pOp;
|
||||
if (parser->OpTop < 1)
|
||||
return eSyntax;
|
||||
if ( (pOp = &parser->OpStack[parser->OpTop-1])->OperType
|
||||
== OP_FUNC_MULTIARG ) {
|
||||
if (!pOp->StrParams)
|
||||
pOp->StrParams = Strmap_Create( 0, 0 );
|
||||
StrMap_AddStrLen( pOp->StrParams,
|
||||
parser->Lexer.Name,
|
||||
parser->Lexer.NameLen, NULL );
|
||||
parser->ValStack[++parser->ValTop] = DblNiN;
|
||||
} else
|
||||
return eSyntax;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return eSyntax;
|
||||
}
|
||||
next_tok:
|
||||
ToTi = Lexer_GetNextToken( &parser->Lexer );
|
||||
} // forever
|
||||
|
||||
getout:
|
||||
if (parser->OpTop != -1 || parser->ValTop != 0)
|
||||
return eInternal;
|
||||
|
||||
*result = parser->ValStack[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char* MathParser_ParseScript( hqMathParser* parser, double *result )
|
||||
{
|
||||
char *ErrorMsg = NULL;
|
||||
hqTokenType ToTi;
|
||||
int expectvar = 1, was_return = 0;
|
||||
const char *varname = NULL;
|
||||
int varnamelen = 0;
|
||||
|
||||
parser->VarParams = Strmap_Create( sizeof(double), 0 );
|
||||
|
||||
ToTi = Lexer_GetNextToken( &parser->Lexer );
|
||||
for (;;) {
|
||||
switch (ToTi) {
|
||||
case TOK_FINAL:
|
||||
ErrorMsg = eUnexpEnd;
|
||||
goto getout;
|
||||
case TOK_NAME: {
|
||||
if (!expectvar) {
|
||||
ErrorMsg = eExpVarRet;
|
||||
goto getout;
|
||||
} else {
|
||||
// int i;
|
||||
// const char *SS = parser->Lexer.Name;
|
||||
|
||||
varnamelen = parser->Lexer.NameLen;
|
||||
|
||||
// for (i = varnamelen; i>0; --i)
|
||||
// *SS++ = Win1251UpcaseTbl[ (int) (uchar) *SS ];
|
||||
}
|
||||
varname = parser->Lexer.Name;
|
||||
|
||||
was_return = strncmp( varname, "RETURN", varnamelen ) == 0;
|
||||
if ( was_return ) {
|
||||
ErrorMsg = MathParser_ParseFormula( parser, result );
|
||||
goto getout;
|
||||
}
|
||||
expectvar = 0;
|
||||
break;
|
||||
}
|
||||
case TOK_SYMBOL: {
|
||||
double *value;
|
||||
|
||||
if ( parser->Lexer.IntValue != OP_ASSIGN || expectvar ) {
|
||||
ErrorMsg = eExpAssign;
|
||||
goto getout;
|
||||
}
|
||||
ErrorMsg = MathParser_ParseFormula( parser, result );
|
||||
if (ErrorMsg)
|
||||
goto getout;
|
||||
|
||||
if ( StrMap_LenIndexOf( parser->VarParams,
|
||||
varname, varnamelen,
|
||||
(void**) &value ) >= 0 )
|
||||
*value = *result;
|
||||
else
|
||||
StrMap_AddStrLen( parser->VarParams, varname, varnamelen,
|
||||
result );
|
||||
expectvar = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ErrorMsg = eSyntax;
|
||||
goto getout;
|
||||
}
|
||||
ToTi = Lexer_GetNextToken( &parser->Lexer );
|
||||
} // forever
|
||||
|
||||
getout:
|
||||
StrMap_Destroy( parser->VarParams );
|
||||
parser->VarParams = NULL;
|
||||
return ErrorMsg;
|
||||
}
|
||||
|
||||
static char* Calc( hqMathParser *parser )
|
||||
{
|
||||
double Res, ValR;
|
||||
Operation Op = parser->OpStack[parser->OpTop--];
|
||||
|
||||
// multi-argument external or internal fucntion
|
||||
if ( Op.OperType == OP_FUNC_MULTIARG ) {
|
||||
int paramcnt = parser->ValTop - Op.PrevValTop;
|
||||
char *ErrorMsg;
|
||||
#ifdef MY_DEBUG
|
||||
printf( "ValTop = %d, OpTop = %d, PrevValTop = %d\n",
|
||||
parser->ValTop, parser->OpTop, Op.PrevValTop );
|
||||
#endif
|
||||
parser->ValTop = Op.PrevValTop;
|
||||
ErrorMsg = (*(MultiArgFunc)Op.Func)( paramcnt,
|
||||
&parser->ValStack[parser->ValTop+1],
|
||||
Op.StrParams, &Res );
|
||||
if (ErrorMsg)
|
||||
return ErrorMsg;
|
||||
if (Op.StrParams)
|
||||
StrMap_Destroy( Op.StrParams );
|
||||
parser->ValStack[++parser->ValTop] = Res;
|
||||
#ifdef MY_DEBUG
|
||||
printf("ValTop = %d, OpTop = %d\n", parser->ValTop, parser->OpTop );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Op.OperType==OP_LOGIC)
|
||||
return NULL;
|
||||
|
||||
// get right arg
|
||||
if (parser->ValTop<0)
|
||||
return eExtraOp;
|
||||
ValR = parser->ValStack[parser->ValTop--];
|
||||
|
||||
// one arg operations
|
||||
if (Op.OperType==OP_NOT) {
|
||||
if (ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = ~((int) ValR);
|
||||
else
|
||||
return eValSizErr;
|
||||
} else if (Op.OperType==OP_FUNC_ONEARG) {
|
||||
Res = (*(OneArgFunc)Op.Func)( ValR );
|
||||
} else {
|
||||
// get left arg
|
||||
double ValL;
|
||||
if (parser->ValTop<0)
|
||||
return eExtraOp;
|
||||
ValL = parser->ValStack[parser->ValTop--];
|
||||
switch (Op.OperType) {
|
||||
// Binary
|
||||
case OP_SHL:
|
||||
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = (int) ValL << (int) ValR;
|
||||
else
|
||||
return eValSizErr;
|
||||
break;
|
||||
case OP_SHR:
|
||||
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = (int) ValL >> (int) ValR;
|
||||
else
|
||||
return eValSizErr;
|
||||
break;
|
||||
case OP_POW:
|
||||
Res = pow( ValL, ValR ); break;
|
||||
// Logical
|
||||
case OP_LOGIC_NEQ:
|
||||
Res = ValL != ValR; break;
|
||||
case OP_LOGIC_GEQ:
|
||||
Res = ValL >= ValR; break;
|
||||
case OP_LOGIC_LEQ:
|
||||
Res = ValL <= ValR; break;
|
||||
case OP_LOGIC_AND:
|
||||
Res = ValL && ValR; break;
|
||||
case OP_LOGIC_OR:
|
||||
Res = ValL || ValR; break;
|
||||
// Arithmetic
|
||||
case OP_ADD:
|
||||
Res = ValL + ValR; break;
|
||||
case OP_SUB:
|
||||
Res = ValL - ValR; break;
|
||||
case OP_MUL:
|
||||
Res = ValL * ValR; break;
|
||||
case OP_DIV:
|
||||
if (ValR == 0.0)
|
||||
return eInfinity;
|
||||
Res = ValL / ValR;
|
||||
break;
|
||||
case OP_MOD:
|
||||
Res = fmod(ValL, ValR); break;
|
||||
case OP_UNK:
|
||||
if (ValL<=0)
|
||||
Res = 0.0;
|
||||
else if (ValR==0.0)
|
||||
return eInfinity;
|
||||
else
|
||||
Res = ceil(ValL / ValR);
|
||||
break;
|
||||
// Bitwise
|
||||
case OP_XOR:
|
||||
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = (int) ValL ^ (int) ValR;
|
||||
else
|
||||
return eValSizErr;
|
||||
break;
|
||||
case OP_AND:
|
||||
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = (int) ValL & (int) ValR;
|
||||
else
|
||||
return eValSizErr;
|
||||
break;
|
||||
case OP_OR:
|
||||
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
|
||||
Res = (int) ValL | (int) ValR;
|
||||
else
|
||||
return eValSizErr;
|
||||
break;
|
||||
// Logical
|
||||
case OP_EQU:
|
||||
Res = ValL == ValR; break;
|
||||
case OP_GREATER:
|
||||
Res = ValL > ValR; break;
|
||||
case OP_LESS:
|
||||
Res = ValL < ValR; break;
|
||||
case OP_LOGIC_SEP: {
|
||||
// needs three arguments
|
||||
double ValLL;
|
||||
if (parser->OpTop < 0
|
||||
|| parser->OpStack[parser->OpTop--].OperType != OP_LOGIC)
|
||||
return eLogicErr;
|
||||
ValLL = parser->ValStack[ parser->ValTop-- ];
|
||||
Res = ValLL ? ValL : ValR;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return eInternal;
|
||||
}
|
||||
}
|
||||
parser->ValStack[++parser->ValTop] = Res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char* CalcToObr( hqMathParser *parser )
|
||||
{
|
||||
while ( parser->OpStack[parser->OpTop].OperType != OP_OBR ) {
|
||||
char *ErrorMsg;
|
||||
if ( (ErrorMsg = Calc( parser )) != NULL )
|
||||
return ErrorMsg;
|
||||
}
|
||||
--parser->OpTop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* misc functions */
|
||||
|
||||
static double _frac_( double x )
|
||||
{
|
||||
double y;
|
||||
return modf(x, &y);
|
||||
}
|
||||
|
||||
static double _trunc_( double x )
|
||||
{
|
||||
return (x >= 0.0) ? floor(x) : ceil(x);
|
||||
}
|
||||
|
||||
static double _sgn_( double x )
|
||||
{
|
||||
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
static double _neg_( double x )
|
||||
{
|
||||
return -x;
|
||||
}
|
||||
|
||||
static double _floor_( double x )
|
||||
{
|
||||
return floor(x);
|
||||
}
|
||||
|
||||
static double _ceil_( double x )
|
||||
{
|
||||
return ceil(x);
|
||||
}
|
||||
|
||||
/* "Advanced" round function; second argument - sharpness */
|
||||
static char* _round_( int paramcnt, double *args, hqStrMap *strparams, double *result )
|
||||
{
|
||||
int i, sharpness;
|
||||
double x, coef;
|
||||
|
||||
if (paramcnt == 1)
|
||||
sharpness = 0;
|
||||
else if (paramcnt == 2)
|
||||
sharpness = (int) args[1];
|
||||
else
|
||||
return eInvPrmCnt;
|
||||
|
||||
x = args[0];
|
||||
if (sharpness < 0) {
|
||||
coef = 0.1;
|
||||
sharpness = -sharpness;
|
||||
} else
|
||||
coef = 10;
|
||||
|
||||
for (i = 0; i < sharpness; i++)
|
||||
x *= coef;
|
||||
|
||||
x = (x + ( (x >= 0) ? 0.5 : -0.5 ) );
|
||||
if (x >= 0.0)
|
||||
x = floor(x);
|
||||
else
|
||||
x = ceil(x);
|
||||
|
||||
for (i = 0; i < sharpness; i++)
|
||||
x /= coef;
|
||||
|
||||
*result = x;
|
||||
|
||||
return NULL;
|
||||
}
|
80
Library/ccalc-0.5.1/mparser.h
Normal file
80
Library/ccalc-0.5.1/mparser.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Math parser for CCalc library.
|
||||
*/
|
||||
#include "strmap.h"
|
||||
#include "lexer.h"
|
||||
#include "pack.h"
|
||||
|
||||
//#define RUSSIAN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_STACK_SIZE 32
|
||||
|
||||
extern const double DblErR;
|
||||
extern const double DblNiN;
|
||||
|
||||
typedef enum {
|
||||
// Binary
|
||||
OP_SHL, OP_SHR, OP_POW,
|
||||
OP_LOGIC_NEQ, OP_LOGIC_GEQ, OP_LOGIC_LEQ,
|
||||
OP_LOGIC_AND, OP_LOGIC_OR, // Logical
|
||||
OP_COMSTART, OP_ASSIGN, // For internal needs
|
||||
OP_OBR, // Special
|
||||
OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_UNK, // Arithmetic
|
||||
OP_XOR, OP_NOT, OP_AND, OP_OR, // Bitwise
|
||||
OP_EQU, OP_GREATER, OP_LESS,
|
||||
OP_LOGIC, OP_LOGIC_SEP, OP_CBR, OP_COMMA, // Logical
|
||||
OP_FORMULAEND, // For script
|
||||
OP_FUNC_ONEARG, OP_FUNC_MULTIARG // Special
|
||||
} OperType_t;
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
double value;
|
||||
} Parameter;
|
||||
|
||||
typedef double (*OneArgFunc) ( double arg );
|
||||
typedef char* (*MultiArgFunc) ( int paramcnt, double *args,
|
||||
hqStrMap *strparams, double *result );
|
||||
typedef int (*PrmSrchFunc) ( const char *str, int len, double *value,
|
||||
void *param );
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct {
|
||||
OperType_t OperType;
|
||||
void *Func;
|
||||
char PrevValTop;
|
||||
hqStrMap *StrParams;
|
||||
} Operation;
|
||||
|
||||
typedef struct {
|
||||
/* public */
|
||||
hqStrMap *Parameters; // List of numeric veriables
|
||||
hqStrMap *ExtFunctions; // List of multi-argument external functions
|
||||
PrmSrchFunc MoreParams; // Function for calculating unhandled parameters
|
||||
void *ParamFuncParam; // Parameter given to this function
|
||||
/* private */
|
||||
Operation OpStack[MAX_STACK_SIZE];
|
||||
double ValStack[MAX_STACK_SIZE];
|
||||
int OpTop, ValTop;
|
||||
int ObrDist;
|
||||
hqLexer Lexer;
|
||||
int script;
|
||||
hqStrMap *VarParams;
|
||||
} hqMathParser;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* API */
|
||||
|
||||
hqMathParser* MathParser_Create( char *MoreLetters );
|
||||
void MathParser_Destroy( hqMathParser* parser );
|
||||
char* MathParser_Parse( hqMathParser* parser, const char *Formula, double *result );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
23
Library/ccalc-0.5.1/pack.h
Normal file
23
Library/ccalc-0.5.1/pack.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* Definitions for packing structures */
|
||||
#ifndef __PACK_H__
|
||||
#define __PACK_H__
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
|
||||
# define PACK_START #pragma option -a1
|
||||
#elif (defined(__GNUC__) && (__GNUC__ <= 2) && (__GNUC_MINOR__ < 95)) \
|
||||
|| (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
|
||||
# define PACK_START #pragma pack(1)
|
||||
#else
|
||||
# define PACK_START #pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
|
||||
# define PACK_STOP #pragma option -a.
|
||||
#elif (defined(__GNUC__) && (__GNUC__ <= 2) && (__GNUC_MINOR__ < 95)) \
|
||||
|| (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
|
||||
# define PACK_STOP #pragma pack()
|
||||
#else
|
||||
# define PACK_STOP #pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif /* __PACK_H__ */
|
129
Library/ccalc-0.5.1/strmap.c
Normal file
129
Library/ccalc-0.5.1/strmap.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "strmap.h"
|
||||
|
||||
hqStrMap* create_instance( int extrabytes, int dup )
|
||||
{
|
||||
hqStrMap* strmap = calloc( 1, sizeof(hqStrMap) );
|
||||
strmap->FDoDuplicate = dup;
|
||||
strmap->FExtraLen = extrabytes;
|
||||
strmap->FRecordLen = sizeof(char*) + sizeof(int) + extrabytes;
|
||||
strmap->FList = NULL;
|
||||
return strmap;
|
||||
}
|
||||
|
||||
hqStrMap* Strmap_Create( int extrabytes, int dup )
|
||||
{
|
||||
return create_instance( extrabytes, dup );
|
||||
}
|
||||
|
||||
void Strmap_FillFromChain( hqStrMap* strmap, char *strchain, void *data )
|
||||
{
|
||||
while ( *strchain ) {
|
||||
size_t len = strlen( strchain );
|
||||
StrMap_AddStrLen( strmap, strchain, len, data );
|
||||
strchain += len+1;
|
||||
data = (char*)data + strmap->FExtraLen;
|
||||
}
|
||||
}
|
||||
|
||||
hqStrMap* Strmap_CreateFromChain( int extrabytes, char *strchain, void *data )
|
||||
{
|
||||
hqStrMap* strmap = create_instance( extrabytes, 0 );
|
||||
Strmap_FillFromChain( strmap, strchain, data );
|
||||
StrMap_ShrinkMem( strmap );
|
||||
return strmap;
|
||||
}
|
||||
|
||||
void StrMap_Destroy( hqStrMap* strmap )
|
||||
{
|
||||
if ( strmap->FDoDuplicate )
|
||||
StrMap_TrimClear( strmap, 0 );
|
||||
if ( strmap->FList )
|
||||
free( strmap->FList );
|
||||
|
||||
free(strmap);
|
||||
}
|
||||
|
||||
void StrMap_AddString( hqStrMap* strmap, const char *str, void *data )
|
||||
{
|
||||
StrMap_AddStrLen( strmap, str, strlen(str), data );
|
||||
}
|
||||
|
||||
void StrMap_AddStrLen( hqStrMap* strmap, const char *str, size_t len, void *data )
|
||||
{
|
||||
const char *Rec;
|
||||
if ( strmap->FCount >= strmap->FCapacity ) {
|
||||
int delta = (strmap->FCapacity > 64) ? strmap->FCapacity / 4 : 16;
|
||||
StrMap_SetCapacity( strmap, strmap->FCapacity + delta );
|
||||
}
|
||||
Rec = strmap->FList + strmap->FCount * strmap->FRecordLen;
|
||||
*(const char**)Rec = str;
|
||||
*(int*)(Rec + sizeof(char*)) = len;
|
||||
if (data) {
|
||||
void *recdata = (void*)(Rec + sizeof(char*) + sizeof(int));
|
||||
memcpy( recdata, data, strmap->FExtraLen );
|
||||
}
|
||||
++ strmap->FCount;
|
||||
}
|
||||
|
||||
void StrMap_ShrinkMem( hqStrMap* strmap )
|
||||
{
|
||||
StrMap_SetCapacity( strmap, strmap->FCount );
|
||||
}
|
||||
|
||||
void StrMap_Trim( hqStrMap* strmap, int NewCount )
|
||||
{
|
||||
strmap->FCount = NewCount;
|
||||
}
|
||||
|
||||
void StrMap_TrimClear( hqStrMap* strmap, int NewCount )
|
||||
{
|
||||
int i;
|
||||
char *Rec = strmap->FList + NewCount * strmap->FRecordLen;
|
||||
for (i=NewCount; i < strmap->FCount; i++) {
|
||||
free( *(char**)Rec );
|
||||
Rec += strmap->FRecordLen;
|
||||
}
|
||||
strmap->FCount = NewCount;
|
||||
}
|
||||
|
||||
void StrMap_SetCapacity( hqStrMap* strmap, int NewCapacity )
|
||||
{
|
||||
strmap->FCapacity = NewCapacity;
|
||||
if ( strmap->FCount > strmap->FCapacity )
|
||||
strmap->FCount = strmap->FCapacity;
|
||||
strmap->FList = (char*) realloc( strmap->FList,
|
||||
strmap->FCapacity * strmap->FRecordLen );
|
||||
}
|
||||
|
||||
int StrMap_IndexOf( hqStrMap* strmap, const char *str, void **data )
|
||||
{
|
||||
return StrMap_LenIndexOf( strmap, str, strlen(str), data );
|
||||
}
|
||||
|
||||
int StrMap_LenIndexOf( hqStrMap* strmap, const char *str, size_t len, void **data )
|
||||
{
|
||||
int i;
|
||||
char *Rec = strmap->FList;
|
||||
for (i=0; i<strmap->FCount; i++) {
|
||||
int recLen = *(int*)(Rec + sizeof(char*));
|
||||
if (recLen==len && strncmp( str, *(char**)Rec, recLen )==0 ) {
|
||||
*data = (Rec + sizeof(char*) + sizeof(int));
|
||||
return i;
|
||||
}
|
||||
Rec += strmap->FRecordLen;
|
||||
}
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* StrMap_GetString( hqStrMap* strmap, int index, int *len, void **data )
|
||||
{
|
||||
char *Rec = strmap->FList + index * strmap->FRecordLen;
|
||||
*len = *(int*)(Rec + sizeof(char*));
|
||||
if (data!=NULL && strmap->FExtraLen>0)
|
||||
*data = (Rec + sizeof(char*) + sizeof(int));
|
||||
return *(char**)Rec;
|
||||
}
|
||||
|
37
Library/ccalc-0.5.1/strmap.h
Normal file
37
Library/ccalc-0.5.1/strmap.h
Normal file
@ -0,0 +1,37 @@
|
||||
#include "pack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct {
|
||||
int FCount, FCapacity;
|
||||
int FExtraLen, FRecordLen;
|
||||
int FDoDuplicate;
|
||||
char *FList;
|
||||
} hqStrMap;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* API */
|
||||
|
||||
hqStrMap* Strmap_Create( int extrabytes, int dup );
|
||||
hqStrMap* Strmap_CreateFromChain( int extrabytes, char *strchain, void *data );
|
||||
void StrMap_Destroy( hqStrMap* strmap );
|
||||
|
||||
void StrMap_AddString( hqStrMap* strmap, const char *str, void *data );
|
||||
void StrMap_AddStrLen( hqStrMap* strmap, const char *str, size_t len, void *data );
|
||||
void StrMap_ShrinkMem( hqStrMap* strmap );
|
||||
void StrMap_Trim( hqStrMap* strmap, int NewCount );
|
||||
void StrMap_TrimClear( hqStrMap* strmap, int NewCount );
|
||||
void StrMap_SetCapacity( hqStrMap* strmap, int NewCapacity );
|
||||
int StrMap_IndexOf( hqStrMap* strmap, const char *str, void **data );
|
||||
int StrMap_LenIndexOf( hqStrMap* strmap, const char *str, size_t len, void **data );
|
||||
char* StrMap_GetString( hqStrMap* strmap, int index, int *len, void **data );
|
||||
void Strmap_FillFromChain( hqStrMap* strmap, char *strchain, void *data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
6
Library/ccalc-0.5.1/wininit.c
Normal file
6
Library/ccalc-0.5.1/wininit.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <windows.h>
|
||||
|
||||
extern int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user