ref: 0f675d0b71518d0acdc49dd9b60d937566446140
parent: d398196a5516713c0821925cc6b088ed6542c67b
author: Scott Flowers <flowerss@cranky.ca>
date: Wed Oct 22 15:04:05 EDT 2025
basic functionality working
--- a/README
+++ b/README
@@ -1,0 +1,17 @@
+This is an rpn calculator with basic trigonometric functions. It runs in the terminal, which acts like a ticker tape of the state of the calculations througout the session.
+
+There is a four position stack as in HP RPN calculators, labeled x, y, z, t from bottom to top. Trigonometric functions act on x, and algebraic functions act on y and x. It should be familiar to users of RPN calculators.
+
+Entering pi loads the constant pi into x.
+
+There are also exponentiation and logarithmic functions.
+
+Enter r to roll, which drops the stack and puts x into t.
+
+Enter d to drop, which drops the bottom value off the stack and duplicates t into z.
+
+Enter x to swap x and y on the stack.
+
+Hitting enter will re-enter the last x value.
+
+To exit, enter q, to clear the stack to all zeros, enter cls.
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,10 @@
+</$objtype/mkfile
+
+rpn: rpn.$O
+ $LD -o rpn rpn.$O
+
+rpn.$O: rpn.c
+ $CC $CFLAGS rpn.c
+
+clean:
+ rm *.[67] rpn
--- /dev/null
+++ b/rpn.c
@@ -1,0 +1,204 @@
+#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);
+}
--
⑨