#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. */ | |
static 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(int argc, char * * argv) | |
{ | |
while ( argc >= 2 ) { | |
stack_machine(argv[1]); | |
argv++; | |
argc--; | |
} | |
stack_machine(0); | |
return 0; | |
} |