Skip to content

Instantly share code, notes, and snippets.

@karno
Created March 23, 2010 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karno/341192 to your computer and use it in GitHub Desktop.
Save karno/341192 to your computer and use it in GitHub Desktop.
//Arithmetic Operation Block
#include "litbas.h"
#include "arith_i.h"
BOOL g_ArithmeticError = FALSE;
BOOL g_NoPrintError = FALSE;
//arithession root
double Arith(const char *arith)
{
G_ERR_Arith = FALSE;
g_ArithmeticError = FALSE;
g_NoPrintError = FALSE;
double retval = 0;
char *buffer;
buffer = (char*)calloc(strlen(arith) + 1,sizeof(char));
assert(buffer);
strcpy(buffer,arith);
StrRmvSpacesTabs(buffer);
transArith(buffer);
retval = arithRoot(buffer);
free(buffer);
if(g_ArithmeticError)
{
G_ERR_Arith = TRUE;
return 0;
}
else
{
return retval;
}
}
void transArith(char *arith)
{
StrToUpper(arith);
char *p = NULL;
if(p = strstr(arith, "MOD"))
StrReplChr(arith, p - arith, 3, '%');
if(p = strstr(arith, "AND"))
StrReplChr(arith, p - arith, 3, '&');
if(p = strstr(arith, "XOR"))
StrReplChr(arith, p - arith, 3, ARITH_XOR);
if(p = strstr(arith, "OR"))
StrReplChr(arith, p - arith, 2, '|');
if(p = strstr(arith, "NOT"))
StrReplChr(arith, p - arith, 2, '!');
if(p = strstr(arith, "<="))
StrReplChr(arith, p - arith, 2, ARITH_LT_OR_EQ);
if(p = strstr(arith, "=<"))
StrReplChr(arith, p - arith, 2, ARITH_LT_OR_EQ);
if(p = strstr(arith, ">="))
StrReplChr(arith, p - arith, 2, ARITH_MT_OR_EQ);
if(p = strstr(arith, "=>"))
StrReplChr(arith, p - arith, 2, ARITH_MT_OR_EQ);
if(p = strstr(arith, "<>"))
StrReplChr(arith, p - arith, 2, ARITH_NEQ);
}
BOOL BracketsExists(const char *arith)
{
const char *p;
for(p = arith; *p; p++)
{
if(*p == '(' || *p == ')')
return TRUE;
}
return FALSE;
}
int GetBracketInnerStr(const char *arith, char *dest)
{
const char *p, *startpoint;
int len = 0,brctcnt = 0;
BOOL endflag = FALSE;
for(p = arith; *p; p++)
{
if(*p == '(')
{
if(brctcnt == 0)
startpoint = p + 1;
brctcnt++;
}
else if(*p == ')')
{
brctcnt--;
if(brctcnt == 0)
{
endflag = TRUE;
break;
}
}
if(brctcnt != 0)
len++;
}
if(!endflag)
{
g_ArithmeticError = TRUE;
return 0;
}
else
{
memcpy(dest, startpoint, len * sizeof(char));
*(dest + len - 1) = '\0';
return startpoint - arith;
}
}
double arithRoot(const char *arith)
{
char *buffer = (char *)calloc(strlen(arith) + 1,sizeof(char));
assert(buffer);
strcpy(buffer, arith);
double value = 0;
if(BracketsExists(buffer))
{
int startpoint = 0;
int blen = 0,diff = 0;
double replValue = 0;
char *replbuf = (char *)calloc(
(strlen(arith) + 1) > ARITH_INTERNAL_MAXLEN ? (strlen(arith) + 1) : ARITH_INTERNAL_MAXLEN,
sizeof(char));
assert(replbuf);
while(BracketsExists(buffer))
{
startpoint = GetBracketInnerStr(buffer, replbuf);
replValue = arithRoot(replbuf);
if(g_ArithmeticError)
return 0;
blen = strlen(replbuf);
sprintf(replbuf, "%lf", replValue);
diff = strlen(replbuf) - blen;
if(diff > 0)
buffer = (char *)realloc(buffer,(strlen(buffer) + diff + 1) * sizeof(char));
StrReplace(buffer, startpoint - 1, blen + 2, replbuf);
}
free(replbuf);
}
char *bufptr = buffer;
value = arith1(&bufptr);
free(buffer);
return value;
}
double arith1(char **arith)
{
if(g_ArithmeticError) return 0;
//AND,OR,XOR
double curval = arith2(arith);
while(**arith)
{
switch((unsigned char)*(*arith)++)
{
case '&':
curval = (unsigned int)curval & (unsigned int)arith2(arith);
break;
case '|':
curval = (unsigned int)curval | (unsigned int)arith2(arith);
break;
case ARITH_XOR:
curval = (unsigned int)curval ^ (unsigned int)arith2(arith);
break;
case '!':
curval = !arith2(arith);
break;
default:
//end of arithession err
g_ArithmeticError = TRUE;
return 0;
}
}
return curval;
}
double arith2(char **arith)
{
if(g_ArithmeticError) return 0;
//<,>,<=,>=,=
double curval = arith3(arith);
while(**arith)
{
switch((unsigned char)*(*arith)++)
{
case '>':
curval = (curval > arith3(arith));
break;
case '<':
curval = (curval < arith3(arith));
break;
case ARITH_MT_OR_EQ:
curval = (curval >= arith3(arith));
break;
case ARITH_LT_OR_EQ:
curval = (curval <= arith3(arith));
break;
case '=':
curval = (curval == arith3(arith));
break;
case ARITH_NEQ:
curval = (curval != arith3(arith));
break;
default:
(*arith)--;
return curval;
}
}
return curval;
}
double arith3(char **arith)
{
if(g_ArithmeticError) return 0;
//+,-
double curval = arith4(arith);
while(**arith)
{
switch((unsigned char)*(*arith)++)
{
case '+':
curval += arith4(arith);
break;
case '-':
curval -= arith4(arith);
break;
default:
(*arith)--;
return curval;
}
}
return curval;
}
double arith4(char **arith)
{
if(g_ArithmeticError) return 0;
//*,/
double curval = arith5(arith);
while(**arith)
{
switch((unsigned char)*(*arith)++)
{
case '*':
curval *= arith5(arith);
break;
case '/':
curval /= arith5(arith);
break;
case '%':
curval = (int)curval % (int)arith5(arith);
break;
default:
(*arith)--;
return curval;
}
}
return curval;
}
double arith5(char **arith)
{
if(g_ArithmeticError) return 0;
//^(power)
double curval = getValue(arith);
while(**arith)
{
switch((unsigned char)*(*arith)++)
{
case '^':
curval = pow(curval,getValue(arith));
break;
default:
(*arith)--;
return curval;
}
}
return curval;
}
double getValue(char **arith)
{
char *buf = NULL;
double val = 0;
if(strlen(*arith) == 0)
return 0;
if(**arith >= '0' && **arith <= '9')
{
//mathematics opr
val = strtod(*arith, &buf);
*arith = buf;
}
else
{
buf = (char *)calloc(sizeof(char),(strlen(*arith) + 1));
int c = 0;
while(
(**arith >= 'A' && **arith <= 'Z') ||
(**arith >= '0' && **arith <= '9') ||
(**arith == '(' || **arith == ')') )
{
buf[c++] = **arith;
(*arith)++;
}
if(**arith == '$')
{
//character variable
g_ArithmeticError = TRUE;
g_NoPrintError = TRUE;
PrintError("Type mismatch");
return 0;
}
if(buf[strlen(buf) - 1] == ')')
{
val = 0;
}
else
{
val = LookupNumVar(buf);
}
free(buf);
}
return val;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment