ref: e062038db3825e8355e2c4ae6413f88eb816e58b
dir: /rpn.c/
#include <u.h>
#include <libc.h>
#define STACKSIZE 4
double stack[STACKSIZE];
int sp = 0;
char *stacklabel = "tzyx";
void push(double val) {
if(sp < STACKSIZE)
stack[sp++] = val;
else {
memmove(stack, stack + 1, (STACKSIZE - 1) * sizeof(double));
stack[STACKSIZE - 1] = val;
}
}
void initstack(void) {
int i;
for(i=0; i<STACKSIZE; i++)
push(0);
}
double pop(void) {
/* if(sp == 0){
print("stack underflow\n");
return 0;
} */
double val = stack[3];
double top = stack[0];
memmove(stack + 1, stack, (STACKSIZE - 1) * sizeof(double));
stack[0] = top;
return val;
}
void showstack(void) {
int i;
print("stack:\n");
for(i = 0; i < sp; i++)
print("%c: %g\n", stacklabel[(4-sp)+i], stack[i]);
}
void swap(void) {
if(sp < 2){
print("not enough values to swap\n");
return;
}
double tmp = stack[sp - 1];
stack[sp - 1] = stack[sp - 2];
stack[sp - 2] = tmp;
}
void drop(void) {
pop();
}
void roll(void) {
double tmp = stack[3];
pop();
stack[0] = tmp;
}
void clear(void) {
push(0);
push(0);
push(0);
push(0);
}
void help(void) {
print("Enter numbers or + - * /, 'q' to quit\n");
print("x swaps bottom of stack\n");
print("d drops bottom of stack\n");
print("r rolls stack\n");
print("cls clears stack\n");
print("trig functions are in degrees\n");
print("pi enters the value of pi\n");
print("s, S are sin / asin\n");
print("c, C are cos / acos\n");
print("t, T are tan / atan\n");
print("yx raises y to the power of x\n");
}
void main(void) {
char buf[128];
int n;
double x;
print("RPN calculator\n");
initstack();
showstack();
for(;;) {
print("> ");
n = read(0, buf, sizeof(buf));
if(n <= 0)
break;
// Trim newline and null-terminate
if(buf[n-1] == '\n')
buf[n-1] = 0;
else
buf[n] = 0;
if((strcmp(buf, "exit") == 0) || (strcmp(buf, "q") == 0))
break;
if((strcmp(buf, "") == 0) && (sp > 0)) {
double a = pop();
push(a);
push(a);
} else if(strcmp(buf, "+") == 0)
push(pop() + pop());
else if(strcmp(buf, "-") == 0) {
double b = pop();
double a = pop();
push(a - b);
}
else if(strcmp(buf, "*") == 0)
push(pop() * pop());
else if(strcmp(buf, "/") == 0) {
double b = pop();
double a = pop();
if(b == 0)
print("division by zero\n");
else
push(a / b);
} else if(strcmp(buf, "s") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float deg = pop();
float rad = deg * (PI / 180.0);
push(sin(rad));
}
} else if(strcmp(buf, "S") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float val = pop();
float rad = asin(val);
float deg = rad / (PI / 180.0);
push(deg);
}
} else if(strcmp(buf, "c") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float deg = pop();
float rad = deg * (PI / 180.0);
push(cos(rad));
}
} else if(strcmp(buf, "C") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float val = pop();
float rad = acos(val);
float deg = rad / (PI / 180.0);
push(deg);
}
} else if(strcmp(buf, "t") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float deg = pop();
float rad = deg * (PI / 180.0);
push(tan(rad));
}
} else if(strcmp(buf, "T") ==0) {
if(sp < 1) {
print("stack underflow\n");
} else {
float val = pop();
float rad = atan(val);
float deg = rad / (PI / 180.0);
push(deg);
}
} else if(strcmp(buf, "pi") == 0)
push (PI);
else if(strcmp(buf, "yx") == 0) {
double b = pop();
double a = pop();
push(pow(a, b));
}
else if(strcmp(buf, "x") == 0)
swap();
else if(strcmp(buf, "d") == 0)
drop();
else if(strcmp(buf, "r") == 0)
roll();
else if((strcmp(buf, "cls") == 0) || (strcmp(buf, "clear") == 0))
clear();
else if(strcmp(buf, "help") == 0)
help();
else {
x = atof(buf);
push(x);
}
showstack();
}
exits(nil);
}