Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/miscutils/dc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 3885 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 /* vi: set sw=4 ts=4: */
2 /*
3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4 */
5
6 #include "busybox.h"
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <math.h>
13
14 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
15
16 static double stack[100];
17 static unsigned int pointer;
18 static unsigned char base;
19
20 static void push(double a)
21 {
22 if (pointer >= (sizeof(stack) / sizeof(*stack)))
23 bb_error_msg_and_die("stack overflow");
24 stack[pointer++] = a;
25 }
26
27 static double pop(void)
28 {
29 if (pointer == 0)
30 bb_error_msg_and_die("stack underflow");
31 return stack[--pointer];
32 }
33
34 static void add(void)
35 {
36 push(pop() + pop());
37 }
38
39 static void sub(void)
40 {
41 double subtrahend = pop();
42
43 push(pop() - subtrahend);
44 }
45
46 static void mul(void)
47 {
48 push(pop() * pop());
49 }
50
51 static void power(void)
52 {
53 double topower = pop();
54
55 push(pow(pop(), topower));
56 }
57
58 static void divide(void)
59 {
60 double divisor = pop();
61
62 push(pop() / divisor);
63 }
64
65 static void mod(void)
66 {
67 unsigned int d = pop();
68
69 push((unsigned int) pop() % d);
70 }
71
72 static void and(void)
73 {
74 push((unsigned int) pop() & (unsigned int) pop());
75 }
76
77 static void or(void)
78 {
79 push((unsigned int) pop() | (unsigned int) pop());
80 }
81
82 static void eor(void)
83 {
84 push((unsigned int) pop() ^ (unsigned int) pop());
85 }
86
87 static void not(void)
88 {
89 push(~(unsigned int) pop());
90 }
91
92 static void set_output_base(void)
93 {
94 base=(unsigned char)pop();
95 if ((base != 10) && (base != 16)) {
96 fprintf(stderr, "Error: base = %d is not supported.\n", base);
97 base=10;
98 }
99 }
100
101 static void print_base(double print)
102 {
103 if (base == 16)
104 printf("%x\n", (unsigned int)print);
105 else
106 printf("%g\n", print);
107 }
108
109 static void print_stack_no_pop(void)
110 {
111 unsigned int i=pointer;
112 while (i)
113 print_base(stack[--i]);
114 }
115
116 static void print_no_pop(void)
117 {
118 print_base(stack[pointer-1]);
119 }
120
121 struct op {
122 const char *name;
123 void (*function) (void);
124 };
125
126 static const struct op operators[] = {
127 {"+", add},
128 {"add", add},
129 {"-", sub},
130 {"sub", sub},
131 {"*", mul},
132 {"mul", mul},
133 {"/", divide},
134 {"div", divide},
135 {"**", power},
136 {"exp", power},
137 {"pow", power},
138 {"%", mod},
139 {"mod", mod},
140 {"and", and},
141 {"or", or},
142 {"not", not},
143 {"eor", eor},
144 {"xor", eor},
145 {"p", print_no_pop},
146 {"f", print_stack_no_pop},
147 {"o", set_output_base},
148 {0, 0}
149 };
150
151 static void stack_machine(const char *argument)
152 {
153 char *endPointer = 0;
154 double d;
155 const struct op *o = operators;
156
157 if (argument == 0)
158 return;
159
160 d = strtod(argument, &endPointer);
161
162 if (endPointer != argument) {
163 push(d);
164 return;
165 }
166
167 while (o->name != 0) {
168 if (strcmp(o->name, argument) == 0) {
169 (*(o->function)) ();
170 return;
171 }
172 o++;
173 }
174 bb_error_msg_and_die("%s: syntax error", argument);
175 }
176
177 /* return pointer to next token in buffer and set *buffer to one char
178 * past the end of the above mentioned token
179 */
180 static char *get_token(char **buffer)
181 {
182 char *start = NULL;
183 char *current;
184
185 current = skip_whitespace(*buffer);
186 if (*current != 0) {
187 start = current;
188 while (!isspace(*current) && *current != 0) { current++; }
189 *buffer = current;
190 }
191 return start;
192 }
193
194 /* In Perl one might say, scalar m|\s*(\S+)\s*|g */
195 static int number_of_tokens(char *buffer)
196 {
197 int i = 0;
198 char *b = buffer;
199 while (get_token(&b)) { i++; }
200 return i;
201 }
202
203 int dc_main(int argc, char **argv)
204 {
205 /* take stuff from stdin if no args are given */
206 if (argc <= 1) {
207 int i, len;
208 char *line = NULL;
209 char *cursor = NULL;
210 char *token = NULL;
211 while ((line = xmalloc_getline(stdin))) {
212 cursor = line;
213 len = number_of_tokens(line);
214 for (i = 0; i < len; i++) {
215 token = get_token(&cursor);
216 *cursor++ = 0;
217 stack_machine(token);
218 }
219 free(line);
220 }
221 } else {
222 if (*argv[1]=='-')
223 bb_show_usage();
224 while (argc >= 2) {
225 stack_machine(argv[1]);
226 argv++;
227 argc--;
228 }
229 }
230 return EXIT_SUCCESS;
231 }