hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/user/calc.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-10-04 02:02:15 +0200
committerhachem <im@hachem.wtf>2026-10-04 02:02:15 +0200
commit7c1bd03a71cccfcf48e79d241787021b0de98e73 (patch)
treeb7131a1f4eee60d24781d3f549d191e17793c282 /user/calc.c
parent627f05098785327744e666c9149375125499d2ff (diff)
feat: add more user programs
Diffstat (limited to 'user/calc.c')
-rw-r--r--user/calc.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/user/calc.c b/user/calc.c
new file mode 100644
index 0000000..2d0e3f8
--- /dev/null
+++ b/user/calc.c
@@ -0,0 +1,78 @@
+#include "user.h"
+
+static int is_digit(char character)
+{
+ return character >= '0' && character <= '9';
+}
+
+void _start(void)
+{
+ put("calc, e.g. 3 + 4 * 2 (left to right), empty line quits\n");
+
+ char line[128];
+ for (;;)
+ {
+ put("> ");
+ int length = read_line(line, 128);
+ put("\n");
+ if (length == 0)
+ break;
+
+ long accumulator = 0;
+ char operator = '+';
+ int valid = 1;
+ int saw_number = 0;
+ int position = 0;
+ while (position < length)
+ {
+ char character = line[position];
+ if (character == ' ')
+ {
+ position++;
+ continue;
+ }
+ if (is_digit(character))
+ {
+ long value = 0;
+ while (position < length && is_digit(line[position]))
+ value = value * 10 + (line[position++] - '0');
+ if (operator == '+')
+ accumulator += value;
+ else if (operator == '-')
+ accumulator -= value;
+ else if (operator == '*')
+ accumulator *= value;
+ else if (operator == '/' || operator == '%')
+ {
+ if (value == 0)
+ {
+ put("divide by zero\n");
+ valid = 0;
+ break;
+ }
+ accumulator = (operator == '/') ? accumulator / value : accumulator % value;
+ }
+ saw_number = 1;
+ }
+ else if (character == '+' || character == '-' || character == '*'
+ || character == '/' || character == '%')
+ {
+ operator = character;
+ position++;
+ }
+ else
+ {
+ put("bad character\n");
+ valid = 0;
+ break;
+ }
+ }
+ if (valid && saw_number)
+ {
+ put("= ");
+ put_int(accumulator);
+ put("\n");
+ }
+ }
+ sys_exit(0);
+}