home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 5
/
DATAFILE_PDCD5.iso
/
utilities
/
s1
/
sss
/
!SSS
/
c
/
eval
< prev
next >
Wrap
Text File
|
1991-07-30
|
6KB
|
225 lines
/* Parser for SSS */
/* Tue,30 Jul 1991 */
/* Copyright C.T.Stretch 1991 */
#include "ssshdr.h"
#include <signal.h>
#include <setjmp.h>
#include <float.h>
#define CHK(c) if(*nextc++!=c) longjmp(env,2)
#define DO(f) CHK('(');val=f(rexp(0));CHK(')');break
#define R(a,b) CHK('[');a=iexp(0);CHK(',');b=iexp(0);CHK(']')
#define DR R(x0,y0);R(x1,y1)
static jmp_buf env;
static double sx,sxx;
static int nx,x0,y0,x1,y1;
int vx,vy;
double value;
char *expr;
BOOL perr;
static char *nextc;
static double rexp(int);
static int iexp(int);
static double cell(int x,int y)
{ entry *cb;
fixed=0;
if(x<0 || x>=ncols || y<0 || y>=nrows)
{ errno=1;
return 1;
}
cb=sheet[x+NCOLS*y];
if(!cb||cb->t<FINT||cb->a||cb->p)
{ errno=1;
return 1;
}
return cb->v;
}
static double cmax()
{ entry *cb;
int x,y;
double best=-DBL_MAX;
fixed=0;
if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
{ errno=1;
return 0;
}
for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
{ cb=sheet[x+NCOLS*y];
if(cb&&cb->t>=FINT&&!(cb->a||cb->p))
{ if(cb->v>best) best=cb->v;
}
}
if(best==-DBL_MAX) {errno=1;return 0;}
return best;
}
static double cmin()
{ entry *cb;
int x,y;
double best=DBL_MAX;
fixed=0;
if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
{ errno=1;
return 0;
}
for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
{ cb=sheet[x+NCOLS*y];
if(cb&&cb->t>=FINT&&!(cb->a||cb->p))
{ if(cb->v<best) best=cb->v;
}
}
if(best==DBL_MAX) {errno=1;return 0;}
return best;
}
static void countup()
{ entry *cb;
int x,y;
fixed=0;
nx=0;sx=0;sxx=0;
if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
{ errno=1;
return ;
}
for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
{ cb=sheet[x+NCOLS*y];
if(cb&&cb->t>=FINT&&!(cb->p||cb->a))
{ nx++;sx+=cb->v;sxx+=cb->v*cb->v;
}
}
return ;
}
static int ibexp()
{ int val;
switch(*nextc)
{ case '(':nextc++;
val=iexp(0);
CHK(')');
break;
case '+':nextc++;
val=iexp(0);
break;
case '-':nextc++;
val=-iexp(0);
break;
case 'x':nextc++;val=vx;break;
case 'y':nextc++;val=vy;break;
default:if(isdigit(*nextc)) val=(int)strtol(nextc,&nextc,10);
else longjmp(env,2);
}
return val;
}
static int iexp(int n)
{ int a=ibexp();
for(;;) switch(*nextc)
{ case '+':if(n>=1) return a;nextc++;a+=iexp(1);break;
case '-':if(n>=1) return a;nextc++;a-=iexp(1);break;
case '*':if(n>=2) return a;nextc++;a*=iexp(2);break;
case '/':if(n>=2) return a;nextc++;a/=iexp(2);break;
case ' ':nextc++;break;
default :return a;
}
}
static double rbexp()
{ double val;
int i;
switch(*nextc)
{ case '(':nextc++;
val=rexp(0);
CHK(')');
break;
case '[':nextc++;
i=iexp(0);
CHK(',');
val=cell(i,iexp(0));
CHK(']');
break;
case '+':nextc++;
val=rexp(0);
break;
case '-':nextc++;
val=-rexp(0);
break;
case '.':val=strtod(nextc,&nextc);break;
default :if(isdigit(*nextc)) { val=strtod(nextc,&nextc);break;}
switch((int)strtol(nextc,&nextc,36))
{ case 33:val=vx;break;
case 34:val=vy;break;
case 36959:DO(sin);
case 16444:DO(cos);
case 37967:DO(tan);
case 28096:DO(log);
case 19357:DO(exp);
case 1341065:DO(sqrt);
case 1034:CHK('(');val=rexp(0);CHK(')');val=val*val;break;
case 578685:DO(ceil);
case 26206011:DO(floor);
case 46509097:CHK('(');val=floor(rexp(0)+0.5);CHK(')');break;
case 503519:DO(asin);
case 483004:DO(acos);
case 504527:DO(atan);
case 18162974:CHK('(');val=rexp(0);;CHK(',');
val=atan2(val,rexp(0));
CHK('(');break;
case 1330541:DO(sinh);
case 592001:DO(cosh);
case 1366829:DO(tanh);
case 37390:DR;countup();val=sx;break;
case 21314873:DR;countup();val=nx;break;
case 13384:DO(fabs);
case 1044959:DR;countup();val=sx/nx;break;
case 37309:DR;countup();
val=sqrt((nx*sxx-sx*sx)/(nx*(nx-1)));break;
case 33421:DR;countup();
val=sqrt(sxx-sx*sx/nx);break;
case 918:val=4*atan(1);break;
case 14:val=exp(1);break;
case 28905:DR;val=cmax();break;
case 29183:DR;val=cmin();break;
default:longjmp(env,2);
}
break;
}
return val;
}
static double rexp(int n)
{ double a=rbexp();
for(;;) switch(*nextc)
{ case '+':if(n>=1) return a;nextc++;a+=rexp(1);break;
case '-':if(n>=1) return a;nextc++;a-=rexp(1);break;
case '*':if(n>=2) return a;nextc++;a*=rexp(2);break;
case '/':if(n>=2) return a;nextc++;a/=rexp(2);break;
case '^':if(n>=3) return a;nextc++;a=pow(a,rexp(4));break;
case ' ':nextc++;break;
default :return a;
}
}
static void badfpe(int snag)
{ if(snag==SIGFPE) longjmp(env,1);
}
void eval()
{ int e;
nextc=expr;
errno=0;
fixed=1;
if(e=setjmp(env))
{ if(e==1) { errno=1;perr=0;} else perr=1;
fixed=0;return;
}
signal(SIGFPE,badfpe);
value=rexp(0);
perr=*nextc;
signal(SIGFPE,SIG_DFL);
}