aboutsummaryrefslogtreecommitdiff
path: root/miscutils/dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/dc.c')
-rw-r--r--miscutils/dc.c118
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
63struct globals { 23struct 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
79static void check_under(void) 38static void check_under(void)
80{ 39{
81 if (pointer == 0) 40 if (pointer == 0)
@@ -223,25 +182,25 @@ struct op {
223 182
224static const struct op operators[] = { 183static 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
244static 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
285int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 253int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
286int dc_main(int argc UNUSED_PARAM, char **argv) 254int 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}