]> Chaos Git - misc/ysh.git/commitdiff
builtins: implement prefix notation math funcs
authorJon Feldman <chaos.kagami@gmail.com>
Wed, 26 Jul 2017 19:32:27 +0000 (15:32 -0400)
committerJon Feldman <chaos.kagami@gmail.com>
Wed, 26 Jul 2017 19:50:29 +0000 (15:50 -0400)
builtin/math.c
util.c
util.h

index f7eb024860a17bfa48279baa35c987783560e208..5274ef97ff1135d9d5211e933ef10ed837a2612c 100644 (file)
@@ -1 +1,236 @@
 // Future home of 'math' builtins.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "parse.h"
+#include "util.h"
+
+int builtin_add(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    long long int total = 0;
+
+    for(size_t idx = 1; argv[idx] != 0; idx++) {
+        long long int ret = strtoll(argv[idx], NULL, 0);
+        if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno) {
+            perror("builtin: add");
+            return -1;
+        }
+        total += ret;
+    }
+
+    char* str = malloc_trap(50); // This is the max possible length of a LLONG, plus nul term
+    memset(str, 0, 50);
+
+    switch(nam[0]) {
+        case 'x':
+            snprintf(str, 50, "0x%llx", total);
+            break;
+        case 'X':
+            snprintf(str, 50, "0x%llX", total);
+            break;
+        case 'o':
+            snprintf(str, 50, "0%llo", total);
+            break;
+        default:
+            snprintf(str, 50, "%lld", total);
+            break;
+    }
+
+    if (stdout) {
+        *stdout = str;
+    } else {
+        printf("%s\n", str);
+    }
+
+    return 0;
+}
+
+int builtin_sub(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    long long int total = 0;
+
+    for(size_t idx = 1; argv[idx] != 0; idx++) {
+        long long int ret = strtoll(argv[idx], NULL, 0);
+        if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno) {
+            perror("builtin: add");
+            return -1;
+        }
+        if (idx == 1) {
+            total = ret;
+        } else {
+            total -= ret;
+        }
+    }
+
+    char* str = malloc_trap(50); // This is the max possible length of a LLONG, plus nul term
+    memset(str, 0, 50);
+
+    switch(nam[0]) {
+        case 'x':
+            snprintf(str, 50, "0x%llx", total);
+            break;
+        case 'X':
+            snprintf(str, 50, "0x%llX", total);
+            break;
+        case 'o':
+            snprintf(str, 50, "0%llo", total);
+            break;
+        default:
+            snprintf(str, 50, "%lld", total);
+            break;
+    }
+
+    if (stdout) {
+        *stdout = str;
+    } else {
+        printf("%s\n", str);
+    }
+
+    return 0;
+}
+
+int builtin_mul(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    long long int total = 1;
+
+    for(size_t idx = 1; argv[idx] != 0; idx++) {
+        long long int ret = strtoll(argv[idx], NULL, 0);
+        if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno) {
+            perror("builtin: add");
+            return -1;
+        }
+        total *= ret;
+    }
+
+    char* str = malloc_trap(50); // This is the max possible length of a LLONG, plus nul term
+    memset(str, 0, 50);
+
+    switch(nam[0]) {
+        case 'x':
+            snprintf(str, 50, "0x%llx", total);
+            break;
+        case 'X':
+            snprintf(str, 50, "0x%llX", total);
+            break;
+        case 'o':
+            snprintf(str, 50, "0%llo", total);
+            break;
+        default:
+            snprintf(str, 50, "%lld", total);
+            break;
+    }
+
+    if (stdout) {
+        *stdout = str;
+    } else {
+        printf("%s\n", str);
+    }
+
+    return 0;
+}
+
+int builtin_div(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    long long int total = 0;
+
+    for(size_t idx = 1; argv[idx] != 0; idx++) {
+        long long int ret = strtoll(argv[idx], NULL, 0);
+        if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno) {
+            perror("builtin: add");
+            return -1;
+        }
+        if (idx == 1) {
+            total = ret;
+        } else {
+            total /= ret;
+        }
+    }
+
+    char* str = malloc_trap(50); // This is the max possible length of a LLONG, plus nul term
+    memset(str, 0, 50);
+
+    switch(nam[0]) {
+        case 'x':
+            snprintf(str, 50, "0x%llx", total);
+            break;
+        case 'X':
+            snprintf(str, 50, "0x%llX", total);
+            break;
+        case 'o':
+            snprintf(str, 50, "0%llo", total);
+            break;
+        default:
+            snprintf(str, 50, "%lld", total);
+            break;
+    }
+
+    if (stdout) {
+        *stdout = str;
+    } else {
+        printf("%s\n", str);
+    }
+
+    return 0;
+}
+
+int builtin_modulo(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    long long int total = 0;
+
+    for(size_t idx = 1; argv[idx] != 0; idx++) {
+        long long int ret = strtoll(argv[idx], NULL, 0);
+        if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno) {
+            perror("builtin: add");
+            return -1;
+        }
+        if (idx == 1) {
+            total = ret;
+        } else {
+            total %= ret;
+        }
+    }
+
+    char* str = malloc_trap(50); // This is the max possible length of a LLONG, plus nul term
+    memset(str, 0, 50);
+
+    switch(nam[0]) {
+        case 'x':
+            snprintf(str, 50, "0x%llx", total);
+            break;
+        case 'X':
+            snprintf(str, 50, "0x%llX", total);
+            break;
+        case 'o':
+            snprintf(str, 50, "0%llo", total);
+            break;
+        default:
+            snprintf(str, 50, "%lld", total);
+            break;
+    }
+
+    if (stdout) {
+        *stdout = str;
+    } else {
+        printf("%s\n", str);
+    }
+
+    return 0;
+}
diff --git a/util.c b/util.c
index 31d948feef746e810509bf612802cb2ba7d07932..d881b9444e58756a5cc6cbbcff228b6952e4fd69 100644 (file)
--- a/util.c
+++ b/util.c
 #include "util.h"
 
 builtin_info_t builtin_info[] = {
-    { "cd", builtin_chdir },
+    { "cd",  builtin_chdir },
+
+    { "+",   builtin_add },
+    { "x+",  builtin_add },
+    { "X+",  builtin_add },
+    { "o+",  builtin_add },
+
+    { "-",   builtin_sub },
+    { "x-",  builtin_sub },
+    { "X-",  builtin_sub },
+    { "o-",  builtin_sub },
+
+    { "*",   builtin_mul },
+    { "x*",  builtin_mul },
+    { "X*",  builtin_mul },
+    { "o*",  builtin_mul },
+
+    { "/",   builtin_div },
+    { "x/",  builtin_div },
+    { "X/",  builtin_div },
+    { "o/",  builtin_div },
+
+    { "%",   builtin_modulo },
+    { "x%",  builtin_modulo },
+    { "X%",  builtin_modulo },
+    { "o%",  builtin_modulo },
+
     { "",   NULL },
 };
 
diff --git a/util.h b/util.h
index ee8cf9ef3b72f7a87306ad70368cb2c8c90e81c1..41c1f6f88e350cce70b11d8b3c5c028ddd348712 100644 (file)
--- a/util.h
+++ b/util.h
@@ -19,4 +19,11 @@ void execute(ast_t* tree, char** stdout);
 // Builtins; these are in the builtin subdir, and all must have the builtin_fn_t prototype
 int builtin_chdir(char* nam, char** argv, char** stdout);
 
+// Math builtins
+int builtin_add(char* nam, char** argv, char** stdout);
+int builtin_sub(char* nam, char** argv, char** stdout);
+int builtin_mul(char* nam, char** argv, char** stdout);
+int builtin_div(char* nam, char** argv, char** stdout);
+int builtin_modulo(char* nam, char** argv, char** stdout);
+
 #endif