From 1f3e8dc36947bdcc2d008fba3cdc29e2c79f9c27 Mon Sep 17 00:00:00 2001 From: andersen Date: Tue, 5 Oct 1999 16:24:54 +0000 Subject: Initial revision git-svn-id: svn://busybox.net/trunk/busybox@5 69ca8d6d-28ef-0310-b511-8ec308f3f277 --- math.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 math.c (limited to 'math.c') diff --git a/math.c b/math.c new file mode 100644 index 000000000..5c1560a4e --- /dev/null +++ b/math.c @@ -0,0 +1,149 @@ +#include "internal.h" +#include +#include +#include +#include + +/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ + +const char math_usage[] = "math expression ..."; + +static double stack[100]; +static unsigned int pointer; + +static void +push(double a) +{ + if ( pointer >= (sizeof(stack) / sizeof(*stack)) ) { + fprintf(stderr, "math: stack overflow\n"); + exit(-1); + } + else + stack[pointer++] = a; +} + +static double +pop() +{ + if ( pointer == 0 ) { + fprintf(stderr, "math: stack underflow\n"); + exit(-1); + } + return stack[--pointer]; +} + +static void +add() +{ + push(pop() + pop()); +} + +static void +sub() +{ + double subtrahend = pop(); + + push(pop() - subtrahend); +} + +static void +mul() +{ + push(pop() * pop()); +} + +static void +divide() +{ + double divisor = pop(); + push(pop() / divisor); +} + +static void +and() +{ + push((unsigned int)pop() & (unsigned int)pop()); +} + +static void +or() +{ + push((unsigned int)pop() | (unsigned int)pop()); +} + +static void +eor() +{ + push((unsigned int)pop() ^ (unsigned int)pop()); +} + +static void +not() +{ + push(~(unsigned int)pop()); +} + +static void +print() +{ + printf("%g\n", pop()); +} + +struct op { + const char * name; + void (*function)(); +}; + +static const struct op operators[] = { + { "add", add }, + { "and", and }, + { "div", divide }, + { "eor", eor }, + { "mul", mul }, + { "not", not }, + { "or", or }, + { "sub", sub }, + { 0, 0 } +}; + +static void +stack_machine(const char * argument) +{ + char * endPointer = 0; + double d; + const struct op * o = operators; + + if ( argument == 0 ) { + print(); + return; + } + + d = strtod(argument, &endPointer); + + if ( endPointer != argument ) { + push(d); + return; + } + + while ( o->name != 0 ) { + if ( strcmp(o->name, argument) == 0 ) { + (*(o->function))(); + return; + } + o++; + } + fprintf(stderr, "math: %s: syntax error.\n", argument); + exit(-1); +} + +int +math_main(struct FileInfo * i, int argc, char * * argv) +{ + while ( argc >= 2 ) { + stack_machine(argv[1]); + argv++; + argc--; + } + stack_machine(0); + return 0; +} -- cgit v1.2.3-55-g6feb