Some formatting updates (ran the code through indent)
[oweals/busybox.git] / math.c
1 /* vi: set sw=4 ts=4: */
2 #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
10 static const char math_usage[] = "math expression ...";
11
12 static double stack[100];
13 static unsigned int pointer;
14
15 static void push(double a)
16 {
17         if (pointer >= (sizeof(stack) / sizeof(*stack))) {
18                 fprintf(stderr, "math: stack overflow\n");
19                 exit(-1);
20         } else
21                 stack[pointer++] = a;
22 }
23
24 static double pop()
25 {
26         if (pointer == 0) {
27                 fprintf(stderr, "math: stack underflow\n");
28                 exit(-1);
29         }
30         return stack[--pointer];
31 }
32
33 static void add()
34 {
35         push(pop() + pop());
36 }
37
38 static void sub()
39 {
40         double subtrahend = pop();
41
42         push(pop() - subtrahend);
43 }
44
45 static void mul()
46 {
47         push(pop() * pop());
48 }
49
50 static void divide()
51 {
52         double divisor = pop();
53
54         push(pop() / divisor);
55 }
56
57 static void and()
58 {
59         push((unsigned int) pop() & (unsigned int) pop());
60 }
61
62 static void or()
63 {
64         push((unsigned int) pop() | (unsigned int) pop());
65 }
66
67 static void eor()
68 {
69         push((unsigned int) pop() ^ (unsigned int) pop());
70 }
71
72 static void not()
73 {
74         push(~(unsigned int) pop());
75 }
76
77 static void print()
78 {
79         printf("%g\n", pop());
80 }
81
82 struct op {
83         const char *name;
84         void (*function) ();
85 };
86
87 static 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}
97 };
98
99 static void stack_machine(const char *argument)
100 {
101         char *endPointer = 0;
102         double d;
103         const struct op *o = operators;
104
105         if (argument == 0) {
106                 print();
107                 return;
108         }
109
110         d = strtod(argument, &endPointer);
111
112         if (endPointer != argument) {
113                 push(d);
114                 return;
115         }
116
117         while (o->name != 0) {
118                 if (strcmp(o->name, argument) == 0) {
119                         (*(o->function)) ();
120                         return;
121                 }
122                 o++;
123         }
124         fprintf(stderr, "math: %s: syntax error.\n", argument);
125         exit(-1);
126 }
127
128 int math_main(int argc, char **argv)
129 {
130         while (argc >= 2) {
131                 stack_machine(argv[1]);
132                 argv++;
133                 argc--;
134         }
135         stack_machine(0);
136         return 0;
137 }