diff options
Diffstat (limited to 'miscutils/dc.c')
-rw-r--r-- | miscutils/dc.c | 118 |
1 files changed, 52 insertions, 66 deletions
diff --git a/miscutils/dc.c b/miscutils/dc.c index f752a1377..0d09f5e2b 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c | |||
@@ -2,50 +2,11 @@ | |||
2 | /* | 2 | /* |
3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
4 | */ | 4 | */ |
5 | //config:config DC | 5 | |
6 | //config: bool "dc (4.2 kb)" | 6 | /* config/applet/usage bits are in bc.c */ |
7 | //config: default y | 7 | |
8 | //config: help | 8 | //#include "libbb.h" |
9 | //config: Dc is a reverse-polish desk calculator which supports unlimited | 9 | //#include "common_bufsiz.h" |
10 | //config: precision arithmetic. | ||
11 | //config: | ||
12 | //config:config FEATURE_DC_LIBM | ||
13 | //config: bool "Enable power and exp functions (requires libm)" | ||
14 | //config: default y | ||
15 | //config: depends on DC | ||
16 | //config: help | ||
17 | //config: Enable power and exp functions. | ||
18 | //config: NOTE: This will require libm to be present for linking. | ||
19 | |||
20 | //applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
21 | |||
22 | //kbuild:lib-$(CONFIG_DC) += dc.o | ||
23 | |||
24 | //usage:#define dc_trivial_usage | ||
25 | //usage: "EXPRESSION..." | ||
26 | //usage: | ||
27 | //usage:#define dc_full_usage "\n\n" | ||
28 | //usage: "Tiny RPN calculator. Operations:\n" | ||
29 | //usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n" | ||
30 | //usage: "p - print top of the stack (without popping),\n" | ||
31 | //usage: "f - print entire stack,\n" | ||
32 | //usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" | ||
33 | //usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" | ||
34 | //usage: | ||
35 | //usage:#define dc_example_usage | ||
36 | //usage: "$ dc 2 2 + p\n" | ||
37 | //usage: "4\n" | ||
38 | //usage: "$ dc 8 8 \\* 2 2 + / p\n" | ||
39 | //usage: "16\n" | ||
40 | //usage: "$ dc 0 1 and p\n" | ||
41 | //usage: "0\n" | ||
42 | //usage: "$ dc 0 1 or p\n" | ||
43 | //usage: "1\n" | ||
44 | //usage: "$ echo 72 9 div 8 mul p | dc\n" | ||
45 | //usage: "64\n" | ||
46 | |||
47 | #include "libbb.h" | ||
48 | #include "common_bufsiz.h" | ||
49 | #include <math.h> | 10 | #include <math.h> |
50 | 11 | ||
51 | #if 0 | 12 | #if 0 |
@@ -59,7 +20,6 @@ typedef unsigned long long data_t; | |||
59 | #define DATA_FMT LL_FMT | 20 | #define DATA_FMT LL_FMT |
60 | #endif | 21 | #endif |
61 | 22 | ||
62 | |||
63 | struct globals { | 23 | struct globals { |
64 | unsigned pointer; | 24 | unsigned pointer; |
65 | unsigned base; | 25 | unsigned base; |
@@ -75,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof( | |||
75 | base = 10; \ | 35 | base = 10; \ |
76 | } while (0) | 36 | } while (0) |
77 | 37 | ||
78 | |||
79 | static void check_under(void) | 38 | static void check_under(void) |
80 | { | 39 | { |
81 | if (pointer == 0) | 40 | if (pointer == 0) |
@@ -223,25 +182,25 @@ struct op { | |||
223 | 182 | ||
224 | static const struct op operators[] = { | 183 | static const struct op operators[] = { |
225 | #if ENABLE_FEATURE_DC_LIBM | 184 | #if ENABLE_FEATURE_DC_LIBM |
226 | {"**", power}, | 185 | {"^", power}, |
227 | {"exp", power}, | 186 | // {"exp", power}, |
228 | {"pow", power}, | 187 | // {"pow", power}, |
229 | #endif | 188 | #endif |
230 | {"%", mod}, | 189 | {"%", mod}, |
231 | {"mod", mod}, | 190 | // {"mod", mod}, |
191 | // logic ops are not standard, remove? | ||
232 | {"and", and}, | 192 | {"and", and}, |
233 | {"or", or}, | 193 | {"or", or}, |
234 | {"not", not}, | 194 | {"not", not}, |
235 | {"eor", eor}, | ||
236 | {"xor", eor}, | 195 | {"xor", eor}, |
237 | {"+", add}, | 196 | {"+", add}, |
238 | {"add", add}, | 197 | // {"add", add}, |
239 | {"-", sub}, | 198 | {"-", sub}, |
240 | {"sub", sub}, | 199 | // {"sub", sub}, |
241 | {"*", mul}, | 200 | {"*", mul}, |
242 | {"mul", mul}, | 201 | // {"mul", mul}, |
243 | {"/", divide}, | 202 | {"/", divide}, |
244 | {"div", divide}, | 203 | // {"div", divide}, |
245 | {"p", print_no_pop}, | 204 | {"p", print_no_pop}, |
246 | {"f", print_stack_no_pop}, | 205 | {"f", print_stack_no_pop}, |
247 | {"o", set_output_base}, | 206 | {"o", set_output_base}, |
@@ -282,23 +241,50 @@ static void stack_machine(const char *argument) | |||
282 | bb_error_msg_and_die("syntax error at '%s'", argument); | 241 | bb_error_msg_and_die("syntax error at '%s'", argument); |
283 | } | 242 | } |
284 | 243 | ||
244 | static void process_file(FILE *fp) | ||
245 | { | ||
246 | char *line; | ||
247 | while ((line = xmalloc_fgetline(fp)) != NULL) { | ||
248 | stack_machine(line); | ||
249 | free(line); | ||
250 | } | ||
251 | } | ||
252 | |||
285 | int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 253 | int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
286 | int dc_main(int argc UNUSED_PARAM, char **argv) | 254 | int dc_main(int argc UNUSED_PARAM, char **argv) |
287 | { | 255 | { |
256 | bool script = 0; | ||
257 | |||
288 | INIT_G(); | 258 | INIT_G(); |
289 | 259 | ||
290 | argv++; | 260 | /* Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs */ |
291 | if (!argv[0]) { | 261 | for (;;) { |
292 | /* take stuff from stdin if no args are given */ | 262 | int n = getopt(argc, argv, "e:f:"); |
293 | char *line; | 263 | if (n <= 0) |
294 | while ((line = xmalloc_fgetline(stdin)) != NULL) { | 264 | break; |
295 | stack_machine(line); | 265 | switch (n) { |
296 | free(line); | 266 | case 'e': |
267 | script = 1; | ||
268 | stack_machine(optarg); | ||
269 | break; | ||
270 | case 'f': | ||
271 | script = 1; | ||
272 | process_file(xfopen_for_read(optarg)); | ||
273 | break; | ||
274 | default: | ||
275 | bb_show_usage(); | ||
297 | } | 276 | } |
298 | } else { | ||
299 | do { | ||
300 | stack_machine(*argv); | ||
301 | } while (*++argv); | ||
302 | } | 277 | } |
278 | argv += optind; | ||
279 | |||
280 | if (*argv) { | ||
281 | do | ||
282 | process_file(xfopen_for_read(*argv++)); | ||
283 | while (*argv); | ||
284 | } else if (!script) { | ||
285 | /* Take stuff from stdin if no args are given */ | ||
286 | process_file(stdin); | ||
287 | } | ||
288 | |||
303 | return EXIT_SUCCESS; | 289 | return EXIT_SUCCESS; |
304 | } | 290 | } |