1 /* vi: set sw=4 ts=4: */
3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
14 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
16 static double stack[100];
17 static unsigned int pointer;
18 static unsigned char base;
20 static void push(double a)
22 if (pointer >= (sizeof(stack) / sizeof(*stack)))
23 bb_error_msg_and_die("stack overflow");
27 static double pop(void)
30 bb_error_msg_and_die("stack underflow");
31 return stack[--pointer];
41 double subtrahend = pop();
43 push(pop() - subtrahend);
51 static void power(void)
53 double topower = pop();
55 push(pow(pop(), topower));
58 static void divide(void)
60 double divisor = pop();
62 push(pop() / divisor);
67 unsigned int d = pop();
69 push((unsigned int) pop() % d);
74 push((unsigned int) pop() & (unsigned int) pop());
79 push((unsigned int) pop() | (unsigned int) pop());
84 push((unsigned int) pop() ^ (unsigned int) pop());
89 push(~(unsigned int) pop());
92 static void set_output_base(void)
94 base=(unsigned char)pop();
95 if ((base != 10) && (base != 16)) {
96 fprintf(stderr, "Error: base = %d is not supported.\n", base);
101 static void print_base(double print)
104 printf("%x\n", (unsigned int)print);
106 printf("%g\n", print);
109 static void print_stack_no_pop(void)
111 unsigned int i=pointer;
113 print_base(stack[--i]);
116 static void print_no_pop(void)
118 print_base(stack[pointer-1]);
123 void (*function) (void);
126 static const struct op operators[] = {
146 {"f", print_stack_no_pop},
147 {"o", set_output_base},
151 static void stack_machine(const char *argument)
153 char *endPointer = 0;
155 const struct op *o = operators;
160 d = strtod(argument, &endPointer);
162 if (endPointer != argument) {
167 while (o->name != 0) {
168 if (strcmp(o->name, argument) == 0) {
174 bb_error_msg_and_die("%s: syntax error", argument);
177 /* return pointer to next token in buffer and set *buffer to one char
178 * past the end of the above mentioned token
180 static char *get_token(char **buffer)
183 char *current = *buffer;
185 while (isspace(*current)) { current++; }
188 while (!isspace(*current) && *current != 0) { current++; }
194 /* In Perl one might say, scalar m|\s*(\S+)\s*|g */
195 static int number_of_tokens(char *buffer)
199 while (get_token(&b)) { i++; }
203 int dc_main(int argc, char **argv)
205 /* take stuff from stdin if no args are given */
211 while ((line = xmalloc_getline(stdin))) {
213 len = number_of_tokens(line);
214 for (i = 0; i < len; i++) {
215 token = get_token(&cursor);
217 stack_machine(token);
225 stack_machine(argv[1]);