home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
calculat
/
eval.zip
/
EVAL.C
next >
Wrap
Text File
|
1987-11-30
|
6KB
|
361 lines
/*
* evalf.c
*
*
*
*
* command line calculator using (double) math
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PRI0 0
#define PRI1 1
#define PRI2 2
#define PRIMAX 3
#define END 0
#define VALUE 400
int yytoken;
double yyfval;
int oppri;
int basepri;
char *ttextp;
unsigned oss;
unsigned osp;
/*
* eval
*
*
*
*/
double eval(eqntextp)
char *eqntextp;
{
double evalf(int);
int get_token();
basepri=0;
ttextp=eqntextp;
get_token(); /* get pipeline started */
return( evalf(0) );
}
/*
* evalf
*
*
*
* at entrance current token is start of first operand in flat to be executed
*/
double evalf(exitpri)
int exitpri;
{
double get_value();
double evalf(int);
int get_token();
double operate(double, int, double);
double accum;
double op2;
int operator;
int pri;
accum=get_value();
while( 1 ) {
if( yytoken==VALUE ) {
fprintf(stderr, "Got value when expecting operator");
exit(1); }
operator=yytoken; /* operator is current token */
pri=oppri; /* operator priority is value of token */
if( pri <= exitpri )
break; /* done flat */
get_token();
op2=evalf(pri);
accum=operate(accum, operator, op2); }
return(accum);
}
/*
* get_value
*
*
*
* at entrance current token is start of value
*/
double get_value()
{
double get_value();
int get_token();
double retval;
if( yytoken=='-' ) { /* unary minus */
get_token();
retval= -get_value(); }
else {
/* --------- should have VALUE at this point */
if( yytoken != VALUE ) {
fprintf(stderr, "Expecting value got '%c'", yytoken);
exit(1); }
retval=yyfval;
get_token(); }
return( retval );
}
/*
* operate
*
*
*
*/
double operate( value1, operator, value2 )
double value1;
int operator;
double value2;
{
double retval;
switch( operator ) {
case '+' : /* add */
retval=value1+value2;
break;
case '-' : /* subtract */
retval=value1-value2;
break;
case '*' : /* multiply */
retval=value1*value2;
break;
case '/' : /* divide */
retval=value1/value2;
break;
default : /* unknown */
fprintf(stderr, "Operate: unknown operator '%c' encountered in operate\n", operator);
exit(1);
break;
} /* end switch */
return(retval);
}
/*
* get_token
*
*
*
*/
get_token()
{
while(1) { /* handle base priority shifts caused by parenthesis */
if( *ttextp=='(' ) {
basepri+=(PRIMAX+1);
ttextp++; }
else if( *ttextp==')' ) {
basepri-=(PRIMAX+1);
if( basepri<0 ) {
fputs("Unmatched ')'", stderr);
exit(1); }
ttextp++; }
else
break; }
if( isalpha(*ttextp) ) { /* identifier */
char buf[40];
char *bufp=buf;
char *bufendp=buf+39;
char *p;
while( isalpha(*ttextp) && bufp<bufendp )
*bufp++=*ttextp++;
*bufp='\0';
if( !(bufp<bufendp) ) {
fprintf(stderr, "identifier too long: '%s'", buf);
exit(1); }
if( (p=getenv(strupr(buf))) == NULL ) {
fprintf(stderr, "variable '%s' not found in environment", buf);
exit(1); }
yytoken=VALUE;
if( p[atod2(&yyfval, p)]!='\0' ) {
fprintf(stderr, "Environment variable '%s' has non-numeric contents '%s'", buf, p);
exit(1); }}
else if( isdigit(*ttextp) || *ttextp=='.' ) {
yytoken=VALUE;
ttextp+=atod2(&yyfval, ttextp); }
else {
yytoken=*ttextp++;
switch( yytoken ) {
case '+' : oppri=basepri+PRI1;
break;
case '-' : oppri=basepri+PRI1;
break;
case '*' : oppri=basepri+PRI2;
break;
case '/' : oppri=basepri+PRI2;
break;
case '\0': oppri=PRI0;
if( basepri > 0 ) {
fputs("Unmatched '('", stderr);
exit(1); }
yytoken=END;
break;
default : fprintf(stderr, "Unknown operator '%c'\n", yytoken);
exit(1);
break;
}}
return(0);
}
/*
* atod2
*
*
*
*/
int atod2(dp, st)
double *dp;
char *st;
{
int negative=0;
double d=0;
char *p=st;
if( *p=='-' ) { /* [-]nnnnn.nnnnE-nnn */
negative=1;
p++; }
else if( *p=='+' )
p++;
while( isdigit(*p) ) { /* -[nnnnn].nnnnE-nnn */
d*=10;
d+=(*p-'0');
p++; }
if( *p=='.' ) { /* -nnnnn[.]nnnnE-nnn */
double shifter=0.1;
p++;
while( isdigit(*p) ) { /* -nnnnn.[nnnn]E-nnn */
d+=(shifter*(*p-'0'));
shifter/=10;
p++; }}
if( negative ) /* [-]nnnnn.nnnnE-nnn */
d=-d;
if( *p=='e' || *p=='E' ) { /* -nnnnn.nnnn[E]-nnn */
int exp=0;
double expm;
p++;
negative=0;
if( *p=='-' ) { /* -nnnnn.nnnnE[-]nnn */
negative=1;
p++; }
else if( *p=='+' )
p++;
while( isdigit(*p) ) { /* -nnnnn.nnnnE-[nnn] */
exp*=10;
exp+=(*p-'0');
p++; }
expm=pow(10.0, exp+0.0);
if( negative ) /* -nnnnn.nnnnE[-]nnn */
expm=-expm;
d*=expm; }
*dp=d;
return(p-st);
}
/*
* main
*
*
*
*/
main(argc, argv)
int argc;
char *argv[];
{
double eval(char *);
char *inline;
char *p;
double rval;
if( argc!=2 ) {
fputs("usage : eval [formula] /* zg 87/11/27 */\n\n", stderr);
fputs(" eg: C>eval a=1+2*3/4\n", stderr);
fputs(" a=2.5\n", stderr);
fputs(" C>eval (a+2)*2\n", stderr);
fputs(" 9\n", stderr);
exit(1); }
inline=argv[1];
if( (p=strchr(inline, '=')) == NULL )
printf("%lg", eval(inline));
else {
char buf[40];
char *tp;
*p='\0';
for(tp=inline; isalpha(*tp); tp++);
if( *tp != '\0' || tp == inline) {
fprintf(stderr, "identifiers must be [a-zA-Z]+\n");
exit(1); }
rval=eval(p+1);
printf("%s=%lg", inline, rval );
*buf=sprintf(buf, " set %.10s=%lg\r", inline, rval);
int2e(buf); }
return(0);
}