150 lines
2.0 KiB
C
150 lines
2.0 KiB
C
#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(int argc, char * * argv)
|
|
{
|
|
while ( argc >= 2 ) {
|
|
stack_machine(argv[1]);
|
|
argv++;
|
|
argc--;
|
|
}
|
|
stack_machine(0);
|
|
return 0;
|
|
}
|