More stuff.
[oweals/busybox.git] / math.c
1 #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
9 const char                      math_usage[] = "math expression ...";
10
11 static double           stack[100];
12 static unsigned int     pointer;
13
14 static void
15 push(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
25 static double
26 pop()
27 {
28         if ( pointer == 0 ) {
29                 fprintf(stderr, "math: stack underflow\n");
30                 exit(-1);
31         }
32         return stack[--pointer];
33 }
34
35 static void
36 add()
37 {
38         push(pop() + pop());
39 }
40
41 static void
42 sub()
43 {
44         double  subtrahend = pop();
45
46         push(pop() - subtrahend);
47 }
48
49 static void
50 mul()
51 {
52         push(pop() * pop());
53 }
54
55 static void
56 divide()
57 {
58         double  divisor = pop();
59         push(pop() / divisor);
60 }
61
62 static void
63 and()
64 {
65         push((unsigned int)pop() & (unsigned int)pop());
66 }
67
68 static void
69 or()
70 {
71         push((unsigned int)pop() | (unsigned int)pop());
72 }
73
74 static void
75 eor()
76 {
77         push((unsigned int)pop() ^ (unsigned int)pop());
78 }
79
80 static void
81 not()
82 {
83         push(~(unsigned int)pop());
84 }
85
86 static void
87 print()
88 {
89         printf("%g\n", pop());
90 }
91
92 struct op {
93         const char *    name;
94         void                    (*function)();
95 };
96
97 static 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
109 static void
110 stack_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
139 int
140 math_main(struct FileInfo * i, int argc, char * * argv)
141 {
142         while ( argc >= 2 ) {
143                 stack_machine(argv[1]);
144                 argv++;
145                 argc--;
146         }
147         stack_machine(0);
148         return 0;
149 }