From: Jon Feldman Date: Wed, 26 Jul 2017 19:32:27 +0000 (-0400) Subject: builtins: implement prefix notation math funcs X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=b334ea00d21170a8fbbc7d0c3caf651aab849ffc;p=misc%2Fysh.git builtins: implement prefix notation math funcs --- diff --git a/builtin/math.c b/builtin/math.c index f7eb024..5274ef9 100644 --- a/builtin/math.c +++ b/builtin/math.c @@ -1 +1,236 @@ // Future home of 'math' builtins. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 31d948f..d881b94 100644 --- a/util.c +++ b/util.c @@ -12,7 +12,33 @@ #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 ee8cf9e..41c1f6f 100644 --- 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