diff options
Diffstat (limited to 'dc.c')
-rw-r--r-- | dc.c | 182 |
1 files changed, 0 insertions, 182 deletions
@@ -1,182 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | #include <ctype.h> | ||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <unistd.h> | ||
7 | #include <math.h> | ||
8 | #include "busybox.h" | ||
9 | |||
10 | /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ | ||
11 | |||
12 | static double stack[100]; | ||
13 | static unsigned int pointer; | ||
14 | |||
15 | static void push(double a) | ||
16 | { | ||
17 | if (pointer >= (sizeof(stack) / sizeof(*stack))) | ||
18 | error_msg_and_die("stack overflow"); | ||
19 | stack[pointer++] = a; | ||
20 | } | ||
21 | |||
22 | static double pop() | ||
23 | { | ||
24 | if (pointer == 0) | ||
25 | error_msg_and_die("stack underflow"); | ||
26 | return stack[--pointer]; | ||
27 | } | ||
28 | |||
29 | static void add() | ||
30 | { | ||
31 | push(pop() + pop()); | ||
32 | } | ||
33 | |||
34 | static void sub() | ||
35 | { | ||
36 | double subtrahend = pop(); | ||
37 | |||
38 | push(pop() - subtrahend); | ||
39 | } | ||
40 | |||
41 | static void mul() | ||
42 | { | ||
43 | push(pop() * pop()); | ||
44 | } | ||
45 | |||
46 | static void divide() | ||
47 | { | ||
48 | double divisor = pop(); | ||
49 | |||
50 | push(pop() / divisor); | ||
51 | } | ||
52 | |||
53 | static void and() | ||
54 | { | ||
55 | push((unsigned int) pop() & (unsigned int) pop()); | ||
56 | } | ||
57 | |||
58 | static void or() | ||
59 | { | ||
60 | push((unsigned int) pop() | (unsigned int) pop()); | ||
61 | } | ||
62 | |||
63 | static void eor() | ||
64 | { | ||
65 | push((unsigned int) pop() ^ (unsigned int) pop()); | ||
66 | } | ||
67 | |||
68 | static void not() | ||
69 | { | ||
70 | push(~(unsigned int) pop()); | ||
71 | } | ||
72 | |||
73 | static void print() | ||
74 | { | ||
75 | printf("%g\n", pop()); | ||
76 | } | ||
77 | |||
78 | struct op { | ||
79 | const char *name; | ||
80 | void (*function) (); | ||
81 | }; | ||
82 | |||
83 | static const struct op operators[] = { | ||
84 | {"+", add}, | ||
85 | {"add", add}, | ||
86 | {"-", sub}, | ||
87 | {"sub", sub}, | ||
88 | {"*", mul}, | ||
89 | {"mul", mul}, | ||
90 | {"/", divide}, | ||
91 | {"div", divide}, | ||
92 | {"and", and}, | ||
93 | {"or", or}, | ||
94 | {"not", not}, | ||
95 | {"eor", eor}, | ||
96 | {0, 0} | ||
97 | }; | ||
98 | |||
99 | static void stack_machine(const char *argument) | ||
100 | { | ||
101 | char *endPointer = 0; | ||
102 | double d; | ||
103 | const struct op *o = operators; | ||
104 | |||
105 | if (argument == 0) { | ||
106 | print(); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | d = strtod(argument, &endPointer); | ||
111 | |||
112 | if (endPointer != argument) { | ||
113 | push(d); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | while (o->name != 0) { | ||
118 | if (strcmp(o->name, argument) == 0) { | ||
119 | (*(o->function)) (); | ||
120 | return; | ||
121 | } | ||
122 | o++; | ||
123 | } | ||
124 | error_msg_and_die("%s: syntax error.", argument); | ||
125 | } | ||
126 | |||
127 | /* return pointer to next token in buffer and set *buffer to one char | ||
128 | * past the end of the above mentioned token | ||
129 | */ | ||
130 | static char *get_token(char **buffer) | ||
131 | { | ||
132 | char *start = NULL; | ||
133 | char *current = *buffer; | ||
134 | |||
135 | while (isspace(*current)) { current++; } | ||
136 | if (*current != 0) { | ||
137 | start = current; | ||
138 | while (!isspace(*current) && current != 0) { current++; } | ||
139 | *buffer = current; | ||
140 | } | ||
141 | return start; | ||
142 | } | ||
143 | |||
144 | /* In Perl one might say, scalar m|\s*(\S+)\s*|g */ | ||
145 | static int number_of_tokens(char *buffer) | ||
146 | { | ||
147 | int i = 0; | ||
148 | char *b = buffer; | ||
149 | while (get_token(&b)) { i++; } | ||
150 | return i; | ||
151 | } | ||
152 | |||
153 | int dc_main(int argc, char **argv) | ||
154 | { | ||
155 | /* take stuff from stdin if no args are given */ | ||
156 | if (argc <= 1) { | ||
157 | int i, len; | ||
158 | char *line = NULL; | ||
159 | char *cursor = NULL; | ||
160 | char *token = NULL; | ||
161 | while ((line = get_line_from_file(stdin))) { | ||
162 | cursor = line; | ||
163 | len = number_of_tokens(line); | ||
164 | for (i = 0; i < len; i++) { | ||
165 | token = get_token(&cursor); | ||
166 | *cursor++ = 0; | ||
167 | stack_machine(token); | ||
168 | } | ||
169 | free(line); | ||
170 | } | ||
171 | } else { | ||
172 | if (*argv[1]=='-') | ||
173 | show_usage(); | ||
174 | while (argc >= 2) { | ||
175 | stack_machine(argv[1]); | ||
176 | argv++; | ||
177 | argc--; | ||
178 | } | ||
179 | } | ||
180 | stack_machine(0); | ||
181 | return EXIT_SUCCESS; | ||
182 | } | ||