+ wrap things in B<> to make pod2man happy
[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 ...\n\n"
11                 "This is a Tiny RPN calculator that understands the\n"
12                 "following operations: +, -, /, *, and, or, not, eor.\n"
13                 "i.e. 'math 2 2 add' -> 4, and 'math 8 8 \\* 2 2 + /' -> 16\n";
14
15 static double stack[100];
16 static unsigned int pointer;
17
18 static void push(double a)
19 {
20         if (pointer >= (sizeof(stack) / sizeof(*stack))) {
21                 fprintf(stderr, "math: stack overflow\n");
22                 exit(-1);
23         } else
24                 stack[pointer++] = a;
25 }
26
27 static double pop()
28 {
29         if (pointer == 0) {
30                 fprintf(stderr, "math: stack underflow\n");
31                 exit(-1);
32         }
33         return stack[--pointer];
34 }
35
36 static void add()
37 {
38         push(pop() + pop());
39 }
40
41 static void sub()
42 {
43         double subtrahend = pop();
44
45         push(pop() - subtrahend);
46 }
47
48 static void mul()
49 {
50         push(pop() * pop());
51 }
52
53 static void divide()
54 {
55         double divisor = pop();
56
57         push(pop() / divisor);
58 }
59
60 static void and()
61 {
62         push((unsigned int) pop() & (unsigned int) pop());
63 }
64
65 static void or()
66 {
67         push((unsigned int) pop() | (unsigned int) pop());
68 }
69
70 static void eor()
71 {
72         push((unsigned int) pop() ^ (unsigned int) pop());
73 }
74
75 static void not()
76 {
77         push(~(unsigned int) pop());
78 }
79
80 static void print()
81 {
82         printf("%g\n", pop());
83 }
84
85 struct op {
86         const char *name;
87         void (*function) ();
88 };
89
90 static const struct op operators[] = {
91         {"+", add},
92         {"-", sub},
93         {"*", mul},
94         {"/", divide},
95         {"and", and},
96         {"or", or},
97         {"not", not},
98         {"eor", eor},
99         {0, 0}
100 };
101
102 static void stack_machine(const char *argument)
103 {
104         char *endPointer = 0;
105         double d;
106         const struct op *o = operators;
107
108         if (argument == 0) {
109                 print();
110                 return;
111         }
112
113         d = strtod(argument, &endPointer);
114
115         if (endPointer != argument) {
116                 push(d);
117                 return;
118         }
119
120         while (o->name != 0) {
121                 if (strcmp(o->name, argument) == 0) {
122                         (*(o->function)) ();
123                         return;
124                 }
125                 o++;
126         }
127         fprintf(stderr, "math: %s: syntax error.\n", argument);
128         exit(-1);
129 }
130
131 int math_main(int argc, char **argv)
132 {
133         if (argc < 1 || *argv[1]=='-')
134                 usage(math_usage);
135         while (argc >= 2) {
136                 stack_machine(argv[1]);
137                 argv++;
138                 argc--;
139         }
140         stack_machine(0);
141         exit( TRUE);
142 }