-   
- /* 
-   Name: StrCalc.c 
-   Copyright: Exinferis Inc.- 1999-2006 
-   URL: http://www.inexinferis.co.nr 
-   Author: Karman 
-   Date: 12/05/05 15:13 
-   Version: 0.95 
-   Description: Calculadora de Strings... 
-   
-   Operandos: 
-     Enteros, Reales y () 
-   Operaciones Permitidas: 
-     Matemáticas: 
-       + - / * % ^ 
-     Funciones: 
-       asin(x) - ArcoSeno 
-       acos(x) - ArcoCoseno 
-       atan(x) - ArcoTangente 
-       abs(x)  - Absoluto (+) 
-       sin(x)  - Seno 
-       sinh(x) - Seno hiperbólico 
-       cos(x)  - Coseno 
-       cosh(x) - Coseno hiperbólico 
-       tan(x)  - Tangente 
-       tanh(x) - Tangente hiperbólica 
-       ln(x)   - Logaritmo natural 
-       log(x)  - Logaritmo base 10 
-       e(x)    - e a la n 
-       rand(x) - Número aleatorio 
-       rnd(x)  - Redondeo 
-       int(x)  - Truncado a entero 
-   
-   Example: 
-   
-     Calculate("2^5/(2*8)+9^(1/2)-(ln(e(1)))*(cos(90)-sin(90))"); 
- */ 
- #include "strcalc.h" 
-   
- //Modo radianes (rad=1) modo normal (rad=0) 
- char rad=0; 
- char *fstart=0,*errpos=0; 
-   
- //Funciones válidas 
- FUNC func[]={ 
-   {"asin(",'a'},{"acos(",'b'},{"atan(",'d'},{"abs(",'j'},{"sin(",'s'}, 
-   {"sinh(",'f'},{"cos(",'c'},{"cosh(",'g'},{"tan(",'t'},{"tanh(",'h'}, 
-   {"ln(",'n'},{"log(",'l'},{"e(",'e'},{"rand(",'r'},{"rnd(",'u'},{"int(",'i'} 
- }; 
-   
- //******************************************************** 
- // Devuelve la posición del error... (si hubo alguno) 
- //******************************************************** 
- unsigned char GetFunctionErrorPos(void){ 
-   return (unsigned char)(errpos-fstart); 
- } 
- //******************************************************** 
- // Devuelve el error... (si hubo alguno) 
- //******************************************************** 
- char *GetFunctionError(void){ 
-   return errpos; 
- } 
- //******************************************************** 
- // Libera lista en caso de error... 
- //******************************************************** 
- void freelist(PCALCS prim){ 
-   PCALCS tmp; 
-   while(prim){ 
-     tmp=prim;prim=prim->sig;free(tmp); 
-   } 
- } 
- //******************************************************** 
- // Calcula lista de operaciones-operandos... 
- //******************************************************** 
- double CalcOp(PCALCS pcy){ 
-   double res=0;PCALCS tpcy; 
-   while(pcy){ 
-     switch(pcy->op){ 
-       case '=':res=pcy->val;break; 
-       case '^':res=pow(res,pcy->val);break; 
-       case '%':res=fmod(res,pcy->val);break; 
-       case '*':res=res*pcy->val;break; 
-       case '/':res=res/pcy->val;break; 
-       case '+':res=res+pcy->val;break; 
-       case '-':res=res-pcy->val;break; 
-       //Arc trig. functions 
-       case 'a': 
-         if(rad)res=asin(pcy->val); 
-         else res=(asin(pcy->val)*180)/M_PI; 
-       break; 
-       case 'b': 
-         if(rad)res=acos(pcy->val); 
-         else res=(acos(pcy->val)*180)/M_PI; 
-       break; 
-       case 'd': 
-         if(rad)res=atan(pcy->val); 
-         else res=(atan(pcy->val)*180)/M_PI; 
-       break; 
-       //Trig. Functions 
-       case 's': 
-         if(rad)res=sin(pcy->val); 
-         else res=sin((pcy->val*M_PI)/180); 
-       break; 
-       case 'c': 
-         if(rad)res=cos(pcy->val); 
-         else res=cos((pcy->val*M_PI)/180); 
-       break; 
-       case 't': 
-         if(rad)res=tan(pcy->val); 
-         else res=tan((pcy->val*M_PI)/180); 
-       break; 
-       //Hip. Functions 
-       case 'f':res=sinh(pcy->val);break; 
-       case 'g':res=cosh(pcy->val);break; 
-       case 'h':res=tanh(pcy->val);break; 
-       //Other functions 
-       case 'n':res=log(pcy->val);break; 
-       case 'l':res=log10(pcy->val);break; 
-       case 'e':res=exp(pcy->val);break; 
-       case 'j':res=fabs(pcy->val);break; 
-       case 'r':res=fmod(rand(),pcy->val);break; 
-       case 'i':modf(pcy->val,&res);break; 
-       case 'u':res=ceill(pcy->val);break; 
-       default:res=0; 
-     } 
-     tpcy=pcy;pcy=pcy->sig;free(tpcy); 
-   } 
-   return res; 
- } 
- //******************************************************** 
- // Obtiene el número del String... 
- //******************************************************** 
- double GetNum(char **txt){ 
-   double tmp=0;unsigned char des=0; 
-   while((**txt)&&(isdigit(**txt)||((**txt)=='.')||((**txt)==' '))){ 
-     //Controlamos espacios en blanco... 
-     if(**txt==' '){ 
-       while(**txt==' ')(*txt)++; 
-       continue; 
-     } 
-     if((**txt)=='.') 
-       if(des){ 
-         errpos=*txt; 
-         return 0; 
-       }else{ 
-         des=1; 
-         (*txt)++; 
-         continue; 
-       } 
-     if(des) 
-       tmp=tmp+((*((*txt)++)-0x30)/pow(10,des++)); 
-     else  
-       tmp=(tmp*10)+(*((*txt)++)-0x30); 
-   } 
-   if(des&&tmp==0){ 
-     errpos=*txt; 
-     return 0; 
-   } 
-   else return tmp; 
- } 
- //******************************************************** 
- // Genera lista de Operadores-Operandos y administra 
- // resultados... (recursivo) 
- //******************************************************** 
- static double Calc(char **py,char lop,double lval){ 
-   char *pyt,*opy,cp,trig,tmp[256]; 
-   unsigned char av,flen,nfunc=sizeof(func)/sizeof(func[0]); 
-   PCALCS prim=NULL,tp=NULL,atp=NULL,tq,tt; 
-   while(**py){ 
-     //Controlamos espacios en blanco... 
-     while(**py==' ')*py++; 
-     //Nuevo elemento... 
-     if(tp)atp=tp; 
-     tp=(PCALCS)malloc(sizeof(CALCS)); 
-     if(!prim)prim=tp;else tq->sig=tp; 
-     tq=tp;tp->sig=NULL;   
-     //Operación? 
-     if(lval){//Argumento enviado... 
-       tp->val=lval;tp->op='=';lval=0;continue; 
-     } 
-     //primer operación... 
-     if(isoper(**py))//Es una operación? 
-       switch(**py){ 
-         //Suma Resta prioridad 3... 
-         case '+':case '-': 
-           switch(lop){ 
-             case '*':case '^':case '%': 
-               atp->sig=NULL;free(tp); 
-               return CalcOp(prim); 
-             case '+': 
-               tp->op=*(*py)++; 
-             break; 
-             default: 
-               goto OnError;//Error... 
-           } 
-         break; 
-         //Multiplicación Divición prioridad 2... 
-         case '*':case '/': 
-           switch(lop){ 
-             case '^':case '%': 
-               atp->sig=NULL;free(tp); 
-               return CalcOp(prim); 
-             case '*':tp->op=*(*py)++;break; 
-             case '+': 
-               atp->val=Calc(&(*py),'*',atp->val); 
-               atp->sig=NULL;free(tp);tp=NULL;tq=atp; 
-               if(errpos!=fstart) 
-                 goto OnError;//Error... 
-             continue; 
-             default: 
-               goto OnError;//Error... 
-           } 
-         break; 
-         //Modulo prioridad 1... 
-         case '%': 
-           switch(lop){ 
-             case '^': 
-               atp->sig=NULL;free(tp); 
-               return CalcOp(prim); 
-             case '%':tp->op=*(*py)++;break; 
-             case '+':case '*': 
-               atp->val=Calc(&(*py),'%',atp->val); 
-               atp->sig=NULL;free(tp);tp=NULL;tq=atp; 
-               if(errpos!=fstart) 
-                 goto OnError;//Error... 
-             continue; 
-             default: 
-               goto OnError;//Error... 
-           } 
-         break; 
-         //Potencia prioridad 0... 
-         case '^': 
-           switch(lop){ 
-             case '^':tp->op=*(*py)++;break; 
-             case '+':case '*':case '%': 
-               atp->val=Calc(&(*py),'^',atp->val); 
-               atp->sig=NULL;free(tp);tp=NULL;tq=atp; 
-               if(errpos!=fstart) 
-                 goto OnError;//Error... 
-             continue; 
-             default: 
-               goto OnError;//Error... 
-           } 
-         break; 
-         default: 
-           goto OnError;//Error... 
-       } 
-     else //Restantes opciones... 
-       tp->op='='; 
-     //Obtenemos argumento... 
-     if(isdigit(**py)||((**py)=='.')){ 
-       tp->val=GetNum(&(*py)); 
-       if(errpos!=fstart) 
-         goto OnError;//Error...     
-     }else{ 
-       trig=0; 
-       //Parentesis... 
-       if(**py=='(')goto CalcCont; 
-       //Funciones... 
-       for(av=0;av<nfunc;av++){ 
-         flen=strlen(func[av].fname); 
-         if(!strncmp(*py,func[av].fname,flen)){ 
-           (*py)+=flen-1;trig=func[av].func; 
-           goto CalcCont; 
-         } 
-       } 
-       //Tratamos Error... 
-       goto OnError;//Error... 
- CalcCont://Calculamos contenido de "()" 
-       pyt=tmp;cp=1;(*py)++;opy=*py; 
-       while(**py){ 
-         if(**py=='(')++cp; 
-         if(**py==')')--cp; 
-         if(!cp)break; 
-         *(pyt++)=*(*py)++; 
-       } 
-       if(cp) 
-         goto OnError;//Error... 
-       *pyt=0;(*py)++;pyt=tmp; 
-       tp->val=Calc(&pyt,'+',0); 
-       if(errpos!=fstart){ 
-         *py=opy; 
-         goto OnError;//Error... 
-       } 
-       //Resolvemos funciones... 
-       if(trig){ 
-         tt=(PCALCS)malloc(sizeof(CALCS)); 
-         tt->sig=NULL; 
-         tt->op=trig;  
-         tt->val=tp->val; 
-         tp->val=CalcOp(tt); 
-       } 
-     } 
-   } 
-   return CalcOp(prim); 
-   OnError://Error... 
-     errpos=*py; 
-     freelist(prim); 
-   return 0; 
- } 
- //******************************************************** 
- // Verifica String y llama a la función de cálculo... 
- //******************************************************** 
- double Calculate(char *arg){ 
-   fstart=errpos=arg; 
-   if(strlen(arg)>256){//256 caracteres Máximo... 
-     errpos=arg+256; 
-     return 0; 
-   } 
-   return Calc(&arg,'+',0); 
- } 
-   
-