shithub: rpn

ref: 2420a49cd63f5f979afd0ddde2e8628f36dc103f
dir: /rpn.c/

View raw version
#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);
}