123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- #include <stdio.h>
- #include <stdlib.h> /* for atof() */
- #include <math.h> /* sin, exp, and pow */
- #include "defines.h"
- #include <errno.h>
- #include <fenv.h>
- int getop(char []);
- void push(double);
- double pop(void);
- void clear(void);
- /* reverse Polish calculator */
- int main()
- {
-
- size_t size;
- double variable[26]; /* variable stack */
- int type;
- double op2,outcome;
- char *s ;
- int dontprintme=0;
-
- feclearexcept(FE_ALL_EXCEPT);
- int i=0;
- int len=0;
- while (1)
- {
- i=0;
- // len=getline(s,&size,stdin);// != EOF ???? @bug
- len=getline(&s,&size,stdin);
- while ( (i<len+1) && (s!=0) )
- {
- // while count how long the next token is
-
- int k=0;
- while((s[i]==' ')||(s[i]=='\t'))
- {
- i++;
- }
- if (s[i]=='\0')
- break;
- if (s[i]!='\n')
- while((s[i]!=' ')&&(s[i]!='\t')&&(s[i]!='\n')&&(s[i]!='\0'))
- {
- k++;
- i++;
- }
- else //if \n
- {
- i++;
- k++;
- }
-
- i-=k; //we're going to recount these ones.
- // allocate new char[] for this token
- char temp[k+1];
-
- // copy it into this new char[]
- for (int j=0;j<k;j++)
- {
- temp[j]=s[i];
- i++;
- }
- temp[k]='\0'; //terminate de string
-
- // getop for this token
- type = getop(temp);
-
- //continue as usual
-
- double d0;
- double d1;
- int t0;
- int t1;
- switch (type) {
-
- case '\377':
- printf("** !eof detected! **");
- break;
-
- case STRNG:
- /** */
- printf(" ** error: not yet implemented ** \n");
- break;
-
- case GET:
- /** check if it's a valid variable */
- t0 = pop(); //name
- if ((t0>=0) && (t0<26))
- push(variable[t0]);
- else
- printf("\n ** error: variable %d not in range ** \n",t0);
- /** push the variable on to the top of the stack **/
- break;
-
- case SET:
- t0 = pop(); //name
- d0 = pop(); //value
- if ((t0>=0) && (t0<26))
- variable[t0]=d0;
- else
- printf("\n ** error: variable %d not in range ** \n",t0);
- dontprintme=1;
- break;
- /** the variables will be xa through xz */
- /** set has two arguments, one variable, one value */
- /** **/
-
- case POW:
- d0=pop();
- d1=pop();
- push(pow(d0,d1));
- break;
- case EXP:
- d0=pop();
- push(exp(d0));
- break;
- case PEEK:
- d0=pop();
- d1=pop();
- printf("\t%.8g\n",d0);
- printf("\t%.8g\n",d1);
- dontprintme=1;
- push(d1);
- push(d0);
- break;
- case SINE:
- op2=pop();
- push(sin(op2));
- // printf("sin(op2): \t%.8g\n",sin(op2));
- break;
- case SWAP:
- d0 = pop();
- d1 = pop();
- push(d0);
- push(d1);
- dontprintme=1;
- break;
-
- case CLEAR:
- clear();
- dontprintme=1;
- break;
- case DUPE:
- d0 = pop();
- push(d0);
- push(d0);
- break;
-
- case NUMBER:
- push(atof(temp));
- break;
-
- case '+':
- push(pop() + pop());
- break;
- case '*':
- push(pop() * pop());
- break;
- case '-':
- op2 = pop();
- push(pop() - op2);
- break;
- case '/':
- op2 = pop();
- if (op2 != 0.0)
- push(pop() / op2);
- else
- printf("error: zero divisor\n");
- break;
-
- case '%':
- t0 = pop();
- t1 = pop();
- if (t0 != 0)
- push(t0%t1);
- else
- {
- push(t0%t1);
- printf("this might not work, mod by 0?");
- }
-
- break;
- case '\n':
- if(dontprintme)
- {
- dontprintme=0;
- break;
- }
- int ferr=fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |
- FE_UNDERFLOW);
- if (ferr!=0)
- {
- printf("\n ** an error occurred in the math ** \n underflow/overflow?\n");
- feclearexcept(FE_ALL_EXCEPT);
- }
- //else
- // {
- outcome=pop();
- printf("\t%.8g\n", outcome);
- push(outcome);
- // }
- break;
- default:
- printf("error: unknown command %s\n", temp);
- break;
- }
- }
- }
- return 0;
- }
- #define MAXVAL 100 /* maximum depth of val stack */
- int sp = 0; /* next free stack position */
- double val[MAXVAL]; /* value stack */
- void clear(void)
- {
- sp=0;
- }
- /* push: push f onto value stack */
- void push(double f)
- {
- if (sp < MAXVAL)
- val[sp++] = f;
- else
- printf("error: stack full, can't push %g\n", f);
- }
- /* pop: pop and return top value from stack */
- double pop(void)
- {
- if (sp > 0)
- return val[--sp];
- else {
- printf("error: stack empty\n");
- return 0.0;
- }
- }
|