blob: 1f6d093b974fe99cc680281800879e39111f1beb [file] [log] [blame]
Eric Andersencc8ed391999-10-05 16:24:54 +00001#include "internal.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <math.h>
6
7/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
8
Eric Andersene77ae3a1999-10-19 20:03:34 +00009static const char math_usage[] = "math expression ...";
Eric Andersencc8ed391999-10-05 16:24:54 +000010
11static double stack[100];
12static unsigned int pointer;
13
14static void
15push(double a)
16{
17 if ( pointer >= (sizeof(stack) / sizeof(*stack)) ) {
18 fprintf(stderr, "math: stack overflow\n");
19 exit(-1);
20 }
21 else
22 stack[pointer++] = a;
23}
24
25static double
26pop()
27{
28 if ( pointer == 0 ) {
29 fprintf(stderr, "math: stack underflow\n");
30 exit(-1);
31 }
32 return stack[--pointer];
33}
34
35static void
36add()
37{
38 push(pop() + pop());
39}
40
41static void
42sub()
43{
44 double subtrahend = pop();
45
46 push(pop() - subtrahend);
47}
48
49static void
50mul()
51{
52 push(pop() * pop());
53}
54
55static void
56divide()
57{
58 double divisor = pop();
59 push(pop() / divisor);
60}
61
62static void
63and()
64{
65 push((unsigned int)pop() & (unsigned int)pop());
66}
67
68static void
69or()
70{
71 push((unsigned int)pop() | (unsigned int)pop());
72}
73
74static void
75eor()
76{
77 push((unsigned int)pop() ^ (unsigned int)pop());
78}
79
80static void
81not()
82{
83 push(~(unsigned int)pop());
84}
85
86static void
87print()
88{
89 printf("%g\n", pop());
90}
91
92struct op {
93 const char * name;
94 void (*function)();
95};
96
97static const struct op operators[] = {
98 { "add", add },
99 { "and", and },
100 { "div", divide },
101 { "eor", eor },
102 { "mul", mul },
103 { "not", not },
104 { "or", or },
105 { "sub", sub },
106 { 0, 0 }
107};
108
109static void
110stack_machine(const char * argument)
111{
112 char * endPointer = 0;
113 double d;
114 const struct op * o = operators;
115
116 if ( argument == 0 ) {
117 print();
118 return;
119 }
120
121 d = strtod(argument, &endPointer);
122
123 if ( endPointer != argument ) {
124 push(d);
125 return;
126 }
127
128 while ( o->name != 0 ) {
129 if ( strcmp(o->name, argument) == 0 ) {
130 (*(o->function))();
131 return;
132 }
133 o++;
134 }
135 fprintf(stderr, "math: %s: syntax error.\n", argument);
136 exit(-1);
137}
138
139int
Eric Andersenf6be9441999-10-13 21:12:06 +0000140math_main(int argc, char * * argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000141{
142 while ( argc >= 2 ) {
143 stack_machine(argv[1]);
144 argv++;
145 argc--;
146 }
147 stack_machine(0);
148 return 0;
149}