home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / calculat / eval.zip / EVAL.C next >
Text File  |  1987-11-30  |  6KB  |  361 lines

  1. /*
  2.  * evalf.c
  3.  *
  4.  *
  5.  *
  6.  *
  7.  * command line calculator using (double) math
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <math.h>
  15.  
  16.  
  17. #define PRI0   0
  18. #define PRI1   1
  19. #define PRI2   2
  20. #define PRIMAX 3
  21.  
  22. #define END     0
  23. #define VALUE 400
  24.  
  25. int yytoken;
  26. double yyfval;
  27. int oppri;
  28. int basepri;
  29. char *ttextp;
  30.  
  31. unsigned oss;
  32. unsigned osp;
  33.  
  34. /*
  35.  * eval
  36.  *
  37.  *
  38.  *
  39.  */
  40.  
  41. double eval(eqntextp)
  42. char *eqntextp;
  43. {
  44. double evalf(int);
  45. int get_token();
  46.  
  47. basepri=0;
  48. ttextp=eqntextp;
  49. get_token();             /* get pipeline started */
  50. return( evalf(0) );
  51. }
  52.  
  53. /*
  54.  * evalf
  55.  *
  56.  *
  57.  *
  58.  * at entrance current token is start of first operand in flat to be executed
  59.  */
  60.  
  61. double evalf(exitpri)
  62. int exitpri;
  63. {
  64. double get_value();
  65. double evalf(int);
  66. int get_token();
  67. double operate(double, int, double);
  68.  
  69. double accum;
  70. double op2;
  71. int operator;
  72. int pri;
  73.  
  74. accum=get_value();
  75.  
  76. while( 1 ) {
  77.  
  78.     if( yytoken==VALUE ) {
  79.     fprintf(stderr, "Got value when expecting operator");
  80.     exit(1); }
  81.     operator=yytoken;                /* operator is current token */
  82.  
  83.     pri=oppri;                      /* operator priority is value of token */
  84.     if( pri <= exitpri )
  85.        break;                        /* done flat */
  86.  
  87.     get_token();
  88.     op2=evalf(pri);
  89.     accum=operate(accum, operator, op2); }
  90.  
  91. return(accum);
  92. }
  93.  
  94. /*
  95.  * get_value
  96.  *
  97.  *
  98.  *
  99.  * at entrance current token is start of value
  100.  */
  101.  
  102. double get_value()
  103. {
  104. double get_value();
  105. int get_token();
  106.  
  107. double retval;
  108.  
  109. if( yytoken=='-' ) {      /* unary minus */
  110.     get_token();
  111.     retval= -get_value(); }
  112. else {
  113.     /* --------- should have VALUE at this point */
  114.     if( yytoken != VALUE ) {
  115.     fprintf(stderr, "Expecting value got '%c'", yytoken);
  116.     exit(1); }
  117.     retval=yyfval;
  118.     get_token(); }
  119.  
  120. return( retval );
  121. }
  122.  
  123. /*
  124.  * operate
  125.  *
  126.  *
  127.  *
  128.  */
  129.  
  130. double operate( value1, operator, value2 )
  131. double value1;
  132. int operator;
  133. double value2;
  134. {
  135. double retval;
  136.  
  137. switch( operator ) {
  138.     case '+' : /* add */
  139.            retval=value1+value2;
  140.            break;
  141.  
  142.     case '-' : /* subtract */
  143.            retval=value1-value2;
  144.            break;
  145.  
  146.     case '*' : /* multiply */
  147.            retval=value1*value2;
  148.            break;
  149.  
  150.     case '/' : /* divide */
  151.            retval=value1/value2;
  152.            break;
  153.  
  154.     default  : /* unknown */
  155.            fprintf(stderr, "Operate: unknown operator '%c' encountered in operate\n", operator);
  156.            exit(1);
  157.            break;
  158.  
  159. } /* end switch */
  160.  
  161. return(retval);
  162. }
  163.  
  164. /*
  165.  * get_token
  166.  *
  167.  *
  168.  *
  169.  */
  170.  
  171. get_token()
  172. {
  173.  
  174. while(1) { /* handle base priority shifts caused by parenthesis */
  175.     if( *ttextp=='(' ) {
  176.     basepri+=(PRIMAX+1);
  177.     ttextp++; }
  178.     else if( *ttextp==')' ) {
  179.     basepri-=(PRIMAX+1);
  180.     if( basepri<0 ) {
  181.         fputs("Unmatched ')'", stderr);
  182.         exit(1); }
  183.     ttextp++; }
  184.     else
  185.     break; }
  186.  
  187. if( isalpha(*ttextp) ) {                      /* identifier */
  188.     char buf[40];
  189.     char *bufp=buf;
  190.     char *bufendp=buf+39;
  191.     char *p;
  192.  
  193.     while( isalpha(*ttextp) && bufp<bufendp )
  194.     *bufp++=*ttextp++;
  195.  
  196.     *bufp='\0';
  197.  
  198.     if( !(bufp<bufendp) ) {
  199.     fprintf(stderr, "identifier too long: '%s'", buf);
  200.     exit(1); }
  201.  
  202.     if( (p=getenv(strupr(buf))) == NULL ) {
  203.     fprintf(stderr, "variable '%s' not found in environment", buf);
  204.     exit(1); }
  205.  
  206.     yytoken=VALUE;
  207.     if( p[atod2(&yyfval, p)]!='\0' ) {
  208.     fprintf(stderr, "Environment variable '%s' has non-numeric contents '%s'", buf, p);
  209.     exit(1); }}
  210.  
  211. else if( isdigit(*ttextp) || *ttextp=='.' ) {
  212.     yytoken=VALUE;
  213.     ttextp+=atod2(&yyfval, ttextp); }
  214. else {
  215.     yytoken=*ttextp++;
  216.  
  217.     switch( yytoken ) {
  218.     case '+' : oppri=basepri+PRI1;
  219.            break;
  220.  
  221.     case '-' : oppri=basepri+PRI1;
  222.            break;
  223.  
  224.     case '*' : oppri=basepri+PRI2;
  225.            break;
  226.  
  227.     case '/' : oppri=basepri+PRI2;
  228.            break;
  229.  
  230.     case '\0': oppri=PRI0;
  231.            if( basepri > 0 ) {
  232.                fputs("Unmatched '('", stderr);
  233.                exit(1); }
  234.            yytoken=END;
  235.            break;
  236.  
  237.     default  : fprintf(stderr, "Unknown operator '%c'\n", yytoken);
  238.            exit(1);
  239.            break;
  240.     }}
  241.  
  242. return(0);
  243. }
  244.  
  245. /*
  246.  * atod2
  247.  *
  248.  *
  249.  *
  250.  */
  251.  
  252. int atod2(dp, st)
  253. double *dp;
  254. char *st;
  255. {
  256. int negative=0;
  257. double d=0;
  258. char *p=st;
  259.  
  260. if( *p=='-' ) {                 /* [-]nnnnn.nnnnE-nnn */
  261.     negative=1;
  262.     p++; }
  263. else if( *p=='+' )
  264.     p++;
  265.  
  266. while( isdigit(*p) ) {          /* -[nnnnn].nnnnE-nnn */
  267.     d*=10;
  268.     d+=(*p-'0');
  269.     p++; }
  270.  
  271. if( *p=='.' ) {                 /* -nnnnn[.]nnnnE-nnn */
  272.     double shifter=0.1;
  273.     p++;
  274.     while( isdigit(*p) ) {      /* -nnnnn.[nnnn]E-nnn */
  275.     d+=(shifter*(*p-'0'));
  276.     shifter/=10;
  277.     p++; }}
  278.  
  279. if( negative )                  /* [-]nnnnn.nnnnE-nnn */
  280.     d=-d;
  281.  
  282. if( *p=='e' || *p=='E' ) {      /* -nnnnn.nnnn[E]-nnn */
  283.     int exp=0;
  284.     double expm;
  285.  
  286.     p++;
  287.  
  288.     negative=0;
  289.     if( *p=='-' ) {             /* -nnnnn.nnnnE[-]nnn */
  290.     negative=1;
  291.     p++; }
  292.     else if( *p=='+' )
  293.     p++;
  294.  
  295.     while( isdigit(*p) ) {      /* -nnnnn.nnnnE-[nnn] */
  296.     exp*=10;
  297.     exp+=(*p-'0');
  298.     p++; }
  299.  
  300.     expm=pow(10.0, exp+0.0);
  301.  
  302.     if( negative )               /* -nnnnn.nnnnE[-]nnn */
  303.     expm=-expm;
  304.  
  305.     d*=expm; }
  306.  
  307. *dp=d;
  308.  
  309. return(p-st);
  310. }
  311.  
  312.  
  313. /*
  314.  * main
  315.  *
  316.  *
  317.  *
  318.  */
  319.  
  320. main(argc, argv)
  321. int argc;
  322. char *argv[];
  323. {
  324. double eval(char *);
  325.  
  326. char *inline;
  327. char *p;
  328. double rval;
  329.  
  330. if( argc!=2 ) {
  331.     fputs("usage : eval [formula]             /* zg 87/11/27 */\n\n", stderr);
  332.     fputs("        eg: C>eval a=1+2*3/4\n", stderr);
  333.     fputs("            a=2.5\n", stderr);
  334.     fputs("            C>eval (a+2)*2\n", stderr);
  335.     fputs("            9\n", stderr);
  336.     exit(1); }
  337.  
  338. inline=argv[1];
  339.  
  340. if( (p=strchr(inline, '=')) == NULL )
  341.     printf("%lg", eval(inline));
  342. else {
  343.     char buf[40];
  344.     char *tp;
  345.  
  346.     *p='\0';
  347.  
  348.     for(tp=inline; isalpha(*tp); tp++);
  349.     if( *tp != '\0' || tp == inline) {
  350.     fprintf(stderr, "identifiers must be [a-zA-Z]+\n");
  351.     exit(1); }
  352.  
  353.     rval=eval(p+1);
  354.     printf("%s=%lg", inline, rval );
  355.  
  356.     *buf=sprintf(buf, " set %.10s=%lg\r", inline, rval);
  357.     int2e(buf); }
  358.  
  359. return(0);
  360. }
  361.