diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | cmds.c | 30 | ||||
-rw-r--r-- | cmds.h | 8 | ||||
-rw-r--r-- | main.c | 64 | ||||
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | state.h | 10 | ||||
-rw-r--r-- | util.c | 16 | ||||
-rw-r--r-- | util.h | 8 |
8 files changed, 107 insertions, 37 deletions
diff --git a/.gitignore b/.gitignore index c0df46a..b3c7d45 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,6 @@ flycheck_*.el # network security /network-security.data - +# meson build files +build/ +.cache/ diff --git a/cmds.c b/cmds.c new file mode 100644 index 0000000..0148c7b --- /dev/null +++ b/cmds.c @@ -0,0 +1,30 @@ +#include "state.h" +#include "cmds.h" +#include <err.h> +#include <math.h> +#include <stdlib.h> +#include <err.h> + +stack fceil(stack stack) { + stack.val[stack.count-1] = ceil(stack.val[stack.count-1]); + return stack; +} + +stack ffloor(stack stack) { + stack.val[stack.count-1] = floor(stack.val[stack.count-1]); + return stack; +} + +command CMD_LIST[] = { + {"ceil", &fceil, "truncate to the next integer"}, + {"floor", &ffloor, "truncate to the previous integer"}, + {0, 0, 0} +}; + +void initstate(state *s) { + int numel = 0; + for (int i = 0; CMD_LIST[i].name != 0; i++) numel = i; + char *sorted = malloc(sizeof(char *)*numel); + if (sorted == NULL) err(1, "could not allocate function names"); + /* todo: (merge, heap, quick) sort? */ +} diff --git a/cmds.h b/cmds.h new file mode 100644 index 0000000..ba54fac --- /dev/null +++ b/cmds.h @@ -0,0 +1,8 @@ +#ifndef CMDS_H +#define CMDS_H + +#include "state.h" + +extern command CMD_LIST[]; + +#endif diff --git a/main.c b/main.c index f72d7aa..2522e07 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,9 @@ +#include <math.h> #include <stdio.h> #include "state.h" #include "util.h" #include <stdlib.h> +#include <string.h> #include <err.h> #define BUF_SIZE 50 @@ -28,35 +30,47 @@ int main() { while(1){ fprintf(s.defout, s.prompt, s.command_count, s.last_op); s.last_op = 0; + char *endptr = NULL; 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; + buf[strcspn(buf, "\n")] = 0; + double interpreted = strtod(buf, &endptr); + if (interpreted == (double)0 && endptr == buf) { /* strtod returned the char it could not read */ + 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 if (t == FUNCTION) { + if (strcmp(buf, "quit") == 0) { + fprintf(s.defout, "quitting, bye!\n"); + exit(0); + } fprintf(s.defout, "unknown function %s\n", buf); + 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); + } else { /* we found a number */ + s.stack.val[s.stack.count++] = interpreted; } + 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 index e6012bf..b5937fe 100644 --- a/meson.build +++ b/meson.build @@ -1,3 +1,5 @@ project('rpncalc', 'c') src = ['main.c', 'state.c', 'util.c'] -executable('rpncalc', src) +cc = meson.get_compiler('c') +deps = cc.find_library('m', required : true) +executable('rpncalc', src, dependencies : deps) diff --git a/state.h b/state.h index 8a9b2d5..54b2981 100644 --- a/state.h +++ b/state.h @@ -11,13 +11,23 @@ typedef struct { } stack; typedef struct { + char *name; + stack (*exec)(stack); + char *description; +} command; + +typedef struct { int command_count; FILE *defbuf; FILE *defout; char last_op; char *prompt; stack stack; + + /* btree elements */ + char **sorted_names; /* sorted function names */ + stack *((*exec)(stack)); /* sorted function calls, same order as above */ } state; #endif diff --git a/util.c b/util.c index c4dd940..6b6cd37 100644 --- a/util.c +++ b/util.c @@ -1,7 +1,8 @@ #include "util.h" #include <math.h> +#include <string.h> -char OPERATOR_LIST[] = { +const char OPERATOR_LIST[] = { '+', '-', '*', @@ -9,12 +10,11 @@ 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; -} +const command COMMAND_LIST[] = { + {'c', "clear stack"}, + {'p', "pop last element"}, + {0, 0}, +}; int is_operator(char *s) { for (int i = 0; OPERATOR_LIST[i] != 0; i++) { @@ -26,5 +26,5 @@ int is_operator(char *s) { TYPE discriminate(char *s) { if (is_operator(s)) { return OPERATOR; - } else return DOUBLE; + } else return FUNCTION; } diff --git a/util.h b/util.h index 5f948d9..97ad00e 100644 --- a/util.h +++ b/util.h @@ -1,7 +1,11 @@ #ifndef UTIL_H #define UTIL_H -typedef enum {OPERATOR, DOUBLE, FUNCTION} TYPE; +typedef enum {OPERATOR, COMMAND ,DOUBLE, FUNCTION} TYPE; TYPE discriminate(char *s); - +typedef struct { + char n; + const char* desc; +} command; + #endif |