blob: 75b4cdeb590bc2e66724f2fda140d14d3be94ee1 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersencc8ed391999-10-05 16:24:54 +00002#include "internal.h"
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <math.h>
7
8/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
9
Eric Andersene77ae3a1999-10-19 20:03:34 +000010static const char math_usage[] = "math expression ...";
Eric Andersencc8ed391999-10-05 16:24:54 +000011
Erik Andersene49d5ec2000-02-08 19:58:47 +000012static double stack[100];
13static unsigned int pointer;
Eric Andersencc8ed391999-10-05 16:24:54 +000014
Erik Andersene49d5ec2000-02-08 19:58:47 +000015static void push(double a)
Eric Andersencc8ed391999-10-05 16:24:54 +000016{
Erik Andersene49d5ec2000-02-08 19:58:47 +000017 if (pointer >= (sizeof(stack) / sizeof(*stack))) {
Eric Andersencc8ed391999-10-05 16:24:54 +000018 fprintf(stderr, "math: stack overflow\n");
19 exit(-1);
Erik Andersene49d5ec2000-02-08 19:58:47 +000020 } else
Eric Andersencc8ed391999-10-05 16:24:54 +000021 stack[pointer++] = a;
22}
23
Erik Andersene49d5ec2000-02-08 19:58:47 +000024static double pop()
Eric Andersencc8ed391999-10-05 16:24:54 +000025{
Erik Andersene49d5ec2000-02-08 19:58:47 +000026 if (pointer == 0) {
Eric Andersencc8ed391999-10-05 16:24:54 +000027 fprintf(stderr, "math: stack underflow\n");
28 exit(-1);
29 }
30 return stack[--pointer];
31}
32
Erik Andersene49d5ec2000-02-08 19:58:47 +000033static void add()
Eric Andersencc8ed391999-10-05 16:24:54 +000034{
35 push(pop() + pop());
36}
37
Erik Andersene49d5ec2000-02-08 19:58:47 +000038static void sub()
Eric Andersencc8ed391999-10-05 16:24:54 +000039{
Erik Andersene49d5ec2000-02-08 19:58:47 +000040 double subtrahend = pop();
Eric Andersencc8ed391999-10-05 16:24:54 +000041
42 push(pop() - subtrahend);
43}
44
Erik Andersene49d5ec2000-02-08 19:58:47 +000045static void mul()
Eric Andersencc8ed391999-10-05 16:24:54 +000046{
47 push(pop() * pop());
48}
49
Erik Andersene49d5ec2000-02-08 19:58:47 +000050static void divide()
Eric Andersencc8ed391999-10-05 16:24:54 +000051{
Erik Andersene49d5ec2000-02-08 19:58:47 +000052 double divisor = pop();
53
Eric Andersencc8ed391999-10-05 16:24:54 +000054 push(pop() / divisor);
55}
56
Erik Andersene49d5ec2000-02-08 19:58:47 +000057static void and()
Eric Andersencc8ed391999-10-05 16:24:54 +000058{
Erik Andersene49d5ec2000-02-08 19:58:47 +000059 push((unsigned int) pop() & (unsigned int) pop());
Eric Andersencc8ed391999-10-05 16:24:54 +000060}
61
Erik Andersene49d5ec2000-02-08 19:58:47 +000062static void or()
Eric Andersencc8ed391999-10-05 16:24:54 +000063{
Erik Andersene49d5ec2000-02-08 19:58:47 +000064 push((unsigned int) pop() | (unsigned int) pop());
Eric Andersencc8ed391999-10-05 16:24:54 +000065}
66
Erik Andersene49d5ec2000-02-08 19:58:47 +000067static void eor()
Eric Andersencc8ed391999-10-05 16:24:54 +000068{
Erik Andersene49d5ec2000-02-08 19:58:47 +000069 push((unsigned int) pop() ^ (unsigned int) pop());
Eric Andersencc8ed391999-10-05 16:24:54 +000070}
71
Erik Andersene49d5ec2000-02-08 19:58:47 +000072static void not()
Eric Andersencc8ed391999-10-05 16:24:54 +000073{
Erik Andersene49d5ec2000-02-08 19:58:47 +000074 push(~(unsigned int) pop());
Eric Andersencc8ed391999-10-05 16:24:54 +000075}
76
Erik Andersene49d5ec2000-02-08 19:58:47 +000077static void print()
Eric Andersencc8ed391999-10-05 16:24:54 +000078{
79 printf("%g\n", pop());
80}
81
82struct op {
Erik Andersene49d5ec2000-02-08 19:58:47 +000083 const char *name;
84 void (*function) ();
Eric Andersencc8ed391999-10-05 16:24:54 +000085};
86
Erik Andersene49d5ec2000-02-08 19:58:47 +000087static const struct op operators[] = {
88 {"add", add},
89 {"and", and},
90 {"div", divide},
91 {"eor", eor},
92 {"mul", mul},
93 {"not", not},
94 {"or", or},
95 {"sub", sub},
96 {0, 0}
Eric Andersencc8ed391999-10-05 16:24:54 +000097};
98
Erik Andersene49d5ec2000-02-08 19:58:47 +000099static void stack_machine(const char *argument)
Eric Andersencc8ed391999-10-05 16:24:54 +0000100{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000101 char *endPointer = 0;
102 double d;
103 const struct op *o = operators;
Eric Andersencc8ed391999-10-05 16:24:54 +0000104
Erik Andersene49d5ec2000-02-08 19:58:47 +0000105 if (argument == 0) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000106 print();
107 return;
108 }
109
110 d = strtod(argument, &endPointer);
111
Erik Andersene49d5ec2000-02-08 19:58:47 +0000112 if (endPointer != argument) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000113 push(d);
114 return;
115 }
116
Erik Andersene49d5ec2000-02-08 19:58:47 +0000117 while (o->name != 0) {
118 if (strcmp(o->name, argument) == 0) {
119 (*(o->function)) ();
Eric Andersencc8ed391999-10-05 16:24:54 +0000120 return;
121 }
122 o++;
123 }
124 fprintf(stderr, "math: %s: syntax error.\n", argument);
125 exit(-1);
126}
127
Erik Andersene49d5ec2000-02-08 19:58:47 +0000128int math_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000129{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000130 while (argc >= 2) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000131 stack_machine(argv[1]);
132 argv++;
133 argc--;
134 }
135 stack_machine(0);
136 return 0;
137}