diff options
Diffstat (limited to 'math.c')
-rw-r--r-- | math.c | 149 |
1 files changed, 149 insertions, 0 deletions
@@ -0,0 +1,149 @@ +#include "internal.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <math.h> + +/* 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; +} |