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