#include "stdafx.h"
#include "resource.h"
#include <stdarg.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <dos.h>
#include <math.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <float.h>
#include <mmsystem.h>
#include <assert.h>
#include <commctrl.h>
#include <commdlg.h>
#include <windows.h>
#include "calculator.h"
calculator::calculator(void) {
base=10;
precision=2;
variables=0;
vnull=1;
}
calculator::~calculator(void) {
long *pLong;
variable *v;
int count=0;
if (vnull==1) {
pLong=this->variablelist;
while (count++<this->variables) {
v=(variable *)*pLong;
delete v;
pLong++;
}
}
// Free up the variable list...
}
void calculator::DeBone(void) {
char *sptr,*cptr;
char *newstr;
short pcount;
calculator *c;
sptr=&cstring[0];
pcount=0;
while (*sptr!=0) {
if (*sptr=='(') {
if (pcount==0) cptr=sptr+1;
pcount++;
}
if (*sptr==')') {
pcount--;
if (pcount==0) {
strncpy(workstring,cptr,sptr-cptr);
workstring[sptr-cptr]=0;
c=new calculator();
c->precision=this->precision;
c->base=this->base;
c->vnull=0;
c->variables=this->variables;
c->variablelist=this->variablelist;
newstr=c->calculate(workstring,1);
CutString(((cptr-1)-&cstring[0]),(sptr-cptr)+2);
InsertString(((cptr-1)-&cstring[0]),newstr);
delete c;
sptr=&cstring[0];
}
}
sptr++;
}
}
void calculator::CutString(long pos, long len) {
strcpy(&cstring[pos],&cstring[pos+len]);
}
void calculator::InsertString(long pos, char *str) {
char hold[255];
hold[0]=0;
strcpy(hold,&cstring[pos]);
cstring[pos]=0;
strcat(cstring,str);
strcat(cstring,hold);
}
long calculator::GetOps(long pos, double *op1, double *op2) {
char *sptr,*basesptr;
char hold[255];
char *holdptr;
*op1=0;
*op2=0;
sptr=&cstring[0];
while (sptr>&cstring[0] && (isalnum(*sptr) || *sptr=='.' || *sptr==127 || *sptr=='!'/*CHANGE*/)) sptr--;
basesptr=sptr;
holdptr=&hold[0];
for (;;) {
if (isalnum(*sptr) || *sptr=='.' || *sptr==127 || *sptr=='!'/*CHANGE*/) {
*holdptr=*sptr;
holdptr++;
sptr++;
}
else break;
}
*holdptr=0;
*op1=GetOp(hold);
hold[0]=0;
holdptr=&hold[0];
for (;;) {
if (isalnum(*sptr) || *sptr=='.' || *sptr==0 || *sptr==127 || *sptr=='!'/*CHANGE*/) break;
sptr++;
}
while (*sptr!=0) {
if (isalnum(*sptr) || *sptr=='.' || *sptr==127 || *sptr=='!'/*CHANGE*/) {
*holdptr=*sptr;
holdptr++;
sptr++;
}
else break;
}
*holdptr=0;
*op2=GetOp(hold);
return (sptr-basesptr);
}
#define PI (3.1415926535)
char tstring[256];
double calculator::GetOp(char *data) {
char *dptr;
char compliment;
variable *v;
if (strlen(data)==0) return 0;
// Degrees and radians? Should I? So I would type sin(rad(45)) to do it correctly?
dptr=data;
compliment=0;
if (*dptr=='!') {
dptr++;
compliment=1;
}
v=this->Check(dptr);
if (v!=NULL) {
v->Get(tstring);
return GetOp(tstring);
}
if (*(dptr+(strlen(dptr)-1))=='b') {
*(dptr+(strlen(dptr)-1))=0;
return (float)StringToBinary(dptr);
}
if (strnicmp(dptr,"0x",2)==0) {
dptr+=2;
return (float)StringToHex(dptr);
}
// Go through any of our pre-defined variables, and we can get a calculator class out of
// it.
// NOTE: We have an issue with the complement!
if (strnicmp(dptr,"rad",3)==0) {
dptr+=3;
return (atof(dptr)*(PI/180));
}
if (strnicmp(dptr,"deg",3)==0) {
dptr+=3;
return (atof(dptr)*(180/PI));
}
if (strnicmp(dptr,"sin",3)==0) {
dptr+=3;
return sin(GetOp(dptr));
}
if (strnicmp(dptr,"cos",3)==0) {
dptr+=3;
return cos(atof(dptr));
}
if (strnicmp(dptr,"tan",3)==0) {
dptr+=3;
return tan(atof(dptr));
}
if (strnicmp(dptr,"atan",4)==0) {
dptr+=4;
return atan(atof(dptr));
}
if (strnicmp(dptr,"asin",4)==0) {
dptr+=4;
return asin(atof(dptr));
}
if (strnicmp(dptr,"acos",4)==0) {
dptr+=4;
return acos(atof(dptr));
}
if (strnicmp(dptr,"sqrt",4)==0) {
dptr+=4;
return sqrt(atof(dptr));
}
if (*dptr==127/*CHANGE*/) {
dptr++;
if (compliment==1) {
if (atof(dptr)==0) return 1;
else return 0;
}
return -atof(dptr);
}
if (compliment==1) {
if (atof(dptr)==0) return 1;
else return 0;
}
return atof(dptr);
}
void calculator::Calc(void) {
char *sptr;
char hold[255];
double op1,op2,result;
long len;
sptr=&cstring[0];
while (*sptr!=0) {
switch (*sptr) {
case '+':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1+op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '-':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1-op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '*':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1*op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '/':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1/op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '^':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=pow(op1,op2);
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '&':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1&(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '%':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1%(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '|':
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1|(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
case '<':
sptr++;
if (*sptr=='<') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1<<(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
else if (*sptr=='=') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1<=(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
else {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1<op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
break;
case '>':
sptr++;
if (*sptr=='>') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1>>(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
else if (*sptr=='=') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1>=(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
else {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=op1>op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
break;
case '=':
sptr++;
if (*sptr=='=') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1==(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
break;
case '!':
sptr++;
if (*sptr=='=') {
len=GetOps(sptr-&cstring[0],&op1,&op2);
result=(long)op1!=(long)op2;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
}
else sptr--;
// Otherwise, don't eliminate it, right?
break;
case '~':
long temp;
len=GetOps(sptr-&cstring[0],&op1,&op2);
temp=(long)op1;
temp^=(long)op2;
result=(float)temp;
MakeFloat(hold,result);
CutString(0,len);
InsertString(0,hold);
sptr=&cstring[0];
break;
}
sptr++;
}
}
char *calculator::calculate(char *string) {
char *sptr;
result=CALC_OK;
strcpy(cstring,string);
strcat(cstring,"+0");
DeBone();
Calc();
sptr=&cstring[0];
while (*sptr!=0) {
if (*sptr==127/*CHANGE*/) *sptr='-';
sptr++;
}
switch (base) {
case 16:
double fResult;
long lResult;
char string[255];
fResult=atof(cstring);
lResult=(long)fResult;
sprintf(string,"%.2x",lResult);
strupr(string);
if (strlen(string)%2!=0) sprintf(cstring,"0x0%s",string);
else sprintf(cstring,"0x%s",string);
break;
case 2:
fResult=atof(cstring);
lResult=(long)fResult;
LongToBinary(lResult,cstring);
break;
}
return &cstring[0];
}
char *calculator::calculate(char *string, char flag) {
result=CALC_OK;
strcpy(cstring,string);
strcat(cstring,"+0");
DeBone();
Calc();
return &cstring[0];
}
void calculator::MakeFloat(char *string, double number) {
switch (precision) {
case 0:
if (number>=0) sprintf(string,"%.0f",number);
else sprintf(string,"%c%.0f",127,fabs(number));
break;
case 1:
if (number>=0) sprintf(string,"%.1f",number);
else sprintf(string,"%c%.1f",127,fabs(number));
break;
case 2:
if (number>=0) sprintf(string,"%.2f",number);
else sprintf(string,"%c%.2f",127,fabs(number));
//FUNK
break;
case 3:
if (number>=0) sprintf(string,"%.3f",number);
else sprintf(string,"%c%.3f",127,fabs(number));
break;
case 4:
if (number>=0) sprintf(string,"%.4f",number);
else sprintf(string,"%c%.4f",127,fabs(number));
break;
case 5:
if (number>=0) sprintf(string,"%.5f",number);
else sprintf(string,"%c%.5f",127,fabs(number));
break;
case 6:
if (number>=0) sprintf(string,"%.6f",number);
else sprintf(string,"%c%.6f",127,fabs(number));
break;
case 7:
if (number>=0) sprintf(string,"%.7f",number);
else sprintf(string,"%c%.7f",127,fabs(number));
break;
case 8:
if (number>=0) sprintf(string,"%.8f",number);
else sprintf(string,"%c%.8f",127,fabs(number));
break;
case 9:
if (number>=0) sprintf(string,"%.9f",number);
else sprintf(string,"%c%.9f",127,fabs(number));
break;
case 10:
if (number>=0) sprintf(string,"%.10f",number);
else sprintf(string,"%c%.10f",127,fabs(number));
break;
}
}
unsigned int calculator::StringToHex(char *str) {
unsigned int i, j = 0;
strupr(str);
while (str && *str && isxdigit(*str)) {
i = *str++ - '0';
if (9<i) i-=7;
j<<=4;
j|=(i&0x0f);
}
return(j);
}
unsigned int calculator::StringToBinary(char *str) {
unsigned int result=0;
unsigned int multi=1;
char *pstr;
pstr=str+(strlen(str)-1);
while (pstr>=str) {
if (*pstr=='1') {
result|=multi;
multi<<=1;
}
else if (*pstr=='0') {
multi<<=1;
}
pstr--;
}
return result;
}
BOOL calculator::SetBase(int rbase) {
if (rbase!=10 && rbase!=16 && rbase!=2) return FALSE;
this->base=rbase;
return TRUE;
}
BOOL calculator::SetPrecision(int nPrecision) {
if (nPrecision<0) return FALSE;
if (nPrecision>10) return FALSE;
precision=nPrecision;
return TRUE;
}
void calculator::LongToBinary(long lNumber, char *pString) {
char *pStr;
pStr=pString;
*pStr='0';
if (lNumber&0x00000001) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000002) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000004) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000008) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000010) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000020) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000040) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000080) *pStr='1';
pStr++;
if (lNumber&0xFFFFFF00) {
*pStr='0';
if (lNumber&0x00000100) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000200) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000400) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00000800) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00001000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00002000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00004000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00008000) *pStr='1';
pStr++;
}
if (lNumber&0xFFFF0000) {
*pStr='0';
if (lNumber&0x00010000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00020000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00040000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00080000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00100000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00200000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00400000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x00800000) *pStr='1';
pStr++;
}
if (lNumber&0xFF000000) {
*pStr='0';
if (lNumber&0x01000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x02000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x04000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x08000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x10000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x20000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x40000000) *pStr='1';
pStr++;
*pStr='0';
if (lNumber&0x80000000) *pStr='1';
pStr++;
}
*pStr=0;
strrev(pString);
strcat(pString,"b");
}
int calculator::GetBase(void) {
return base;
}
int calculator::GetPrecision(void) {
return precision;
}
#define VTYPE_CHAR 0
#define VTYPE_SHORT 1
#define VTYPE_INT 2
#define VTYPE_LONG 3
#define VTYPE_FLOAT 4
#define VTYPE_DOUBLE 5
#define VTYPE_STRING 6
void calculator::InsertVariable(variable *v) {
long *ptr;
if (this->variables==0) {
this->variablelist=(long*)malloc(4);
ptr=this->variablelist;
this->variables=1;
}
else {
this->variables++;
this->variablelist=(long*)realloc(this->variablelist,this->variables*4);
ptr=(this->variablelist+(this->variables-1));
}
*ptr=(long)v;
}
BOOL calculator::RemoveVariable(char *name) {
variable *v,*vv;
long *pLong;
int count=0;
v=this->Check(name);
if (v==NULL) return CALC_NOTFOUND;
pLong=this->variablelist;
while (count++<this->variables) {
vv=(variable *)*pLong;
if (vv==v) break;
pLong++;
}
while (count++<this->variables) {
*pLong=*(pLong+1);
pLong++;
}
this->variables--;
this->variablelist=(long*)realloc(this->variablelist,this->variables*4);
delete v;
return CALC_OK;
}
variable *calculator::Check(char *string) {
long *pLong;
variable *v;
int count=0;
pLong=this->variablelist;
while (count++<this->variables) {
v=(variable *)*pLong;
if (strcmp(v->m_pName,string)==0) return v;
pLong++;
}
return NULL;
}
BOOL calculator::AddVariable_char(char *name, char *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_CHAR);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_short(char *name, short *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_SHORT);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_int(char *name, int *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_INT);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_long(char *name, long *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_LONG);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_float(char *name, float *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_FLOAT);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_double(char *name, double *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_DOUBLE);
InsertVariable(v);
return CALC_OK;
}
BOOL calculator::AddVariable_string(char *name, char *ptr) {
variable *v;
v=this->Check(name);
if (v!=NULL) return CALC_ALREADYEXISTS;
v=new variable(name,ptr,VTYPE_STRING);
InsertVariable(v);
return CALC_OK;
}
variable::variable(char *name, void *ptr, int type) {
this->m_pName=(char*)malloc(strlen(name)+1);
strcpy(this->m_pName,name);
this->m_pPointer=ptr;
this->m_nType=type;
}
variable::~variable() {
free(this->m_pName);
}
void variable::Get(char *where) {
switch (this->m_nType) {
case VTYPE_CHAR:
sprintf(where,"%d",*(char*)this->m_pPointer);
break;
case VTYPE_SHORT:
sprintf(where,"%d",*(short*)this->m_pPointer);
break;
case VTYPE_INT:
sprintf(where,"%d",*(int*)this->m_pPointer);
break;
case VTYPE_LONG:
sprintf(where,"%d",*(long*)this->m_pPointer);
break;
case VTYPE_FLOAT:
sprintf(where,"%.10f",*(float*)this->m_pPointer);
break;
case VTYPE_DOUBLE:
sprintf(where,"%.10f",*(double*)this->m_pPointer);
break;
case VTYPE_STRING:
strncpy(where,(char*)this->m_pPointer,255);
break;
}
}
|