about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--main.c65
-rw-r--r--meson.build3
-rw-r--r--state.c6
-rw-r--r--util.c32
4 files changed, 106 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..f72d7aa
--- /dev/null
+++ b/main.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include "state.h"
+#include "util.h"
+#include <stdlib.h>
+#include <err.h>
+
+#define BUF_SIZE 50
+
+/* rpncalc: a simple reverse polish notation calculator */
+int main() {
+  
+  /* initialize state struct and its values */
+  state s;
+  /* default input buffer is stdin */
+  s.defbuf = stdin;
+  /* default output buffer is stdout */
+  s.defout = stdout;
+  s.last_op = 0;
+  /* set default interactive prompt */
+  s.prompt = "[%d]> ";
+  stack stack = {{0}, 0};
+  /* initialize value stack */
+  s.stack = stack;
+  s.command_count = 0;
+  
+  /* start reading from defbuf */
+  char buf[BUF_SIZE];
+  while(1){
+    fprintf(s.defout, s.prompt, s.command_count, s.last_op);
+    s.last_op = 0;
+    if (s.stack.count == STACK_SIZE) err(1, "exceeded stack size");
+    fgets(buf, BUF_SIZE, s.defbuf);
+    TYPE t = discriminate(buf);
+    if (t == OPERATOR ) {
+      if (s.stack.count == 1) {
+	fprintf(s.defout, "not enough arguments\n");
+	continue;
+      }
+      char operator = buf[0];
+      if (operator == '+') {
+	s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-1]+s.stack.val[s.stack.count-2];
+	s.stack.val[s.stack.count--] = 0; /* lower count by 1 */
+	s.last_op = '+';
+      } else if (operator == '-') {
+	s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]-s.stack.val[s.stack.count-1];
+	s.stack.val[s.stack.count--] = 0; /* lower count by 1 */
+	s.last_op = '-';
+      } else if (operator == '*') {
+	s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]*s.stack.val[s.stack.count-1];
+	s.stack.val[s.stack.count--] = 0; /* lower count by 1 */
+	s.last_op = '*';
+      } else if (operator == '/') {
+	s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]/s.stack.val[s.stack.count-1];
+	s.stack.val[s.stack.count--] = 0; /* lower count by 1 */
+	s.last_op = '/';
+      }
+    } else {
+      s.stack.val[s.stack.count++]=strtod(buf, NULL);
+    }
+    s.command_count++;
+    for (int i = 0; i < s.stack.count; i++) {
+      fprintf(s.defout,"%d → %f\n",i, s.stack.val[i]);
+    }
+  }
+}
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..e6012bf
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,3 @@
+project('rpncalc', 'c')
+src = ['main.c', 'state.c', 'util.c']
+executable('rpncalc', src)
diff --git a/state.c b/state.c
new file mode 100644
index 0000000..2c504e8
--- /dev/null
+++ b/state.c
@@ -0,0 +1,6 @@
+#include "state.h"
+
+void push(state *s, double d) {
+  s->stack.val[s->stack.count+1] = d;
+  s->stack.count += 1;
+}
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..555c445
--- /dev/null
+++ b/util.c
@@ -0,0 +1,32 @@
+#include "util.h"
+#include <math.h>
+
+char OPERATOR_LIST[] = {
+  '+',
+  '-',
+  '*',
+  '/',
+  0
+};
+
+int is_decimal(char *s) {
+  for (int i = 0; s[i] != 0; i++) {
+    if (s[i] == ',' || s[i] == '.') return 1;
+  }
+  return 0;
+}
+
+int is_operator(char *s) {
+  for (int i = 0; OPERATOR_LIST[i] != 0; i++) {
+    if (s[0] == OPERATOR_LIST[i]) return 1;
+  }
+  return 0;
+}
+
+TYPE discriminate(char *s) {
+  if (is_decimal(s)) {
+    return DOUBLE;
+  } else if (is_operator(s)) {
+    return OPERATOR;
+  } else return INT;
+}