dc: fix "small dc" to have standard command line API
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 8 Dec 2018 17:59:07 +0000 (18:59 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 8 Dec 2018 17:59:07 +0000 (18:59 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
miscutils/bc.c
miscutils/dc.c

index 24e4b639202ab50e58047c7c897f79ef662076e4..e543b2b9321bce28bf0ee181b7508c127a9eff0f 100644 (file)
 //usage:
 //usage:#define dc_full_usage "\n"
 //usage:     "\nTiny RPN calculator. Operations:"
-//usage:     "\n+, -, *, /, %, ^, exp, ~, divmod, |, "
-//usage:       "modular exponentiation,"
+//usage:     "\n+, -, *, /, %, ~, ^, |,"
 //usage:     "\np - print top of the stack (without popping)"
 //usage:     "\nf - print entire stack"
 //usage:     "\nk - pop the value and set the precision"
index bca4778bf9ba4d4639fc20b8aee9ff4e1daaa2cc..17fdda8fd9e5fbb78b6b4be2cf127e7eba883647 100644 (file)
@@ -20,7 +20,6 @@ typedef unsigned long long data_t;
 #define DATA_FMT "ll"
 #endif
 
-
 struct globals {
        unsigned pointer;
        unsigned base;
@@ -36,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(
        base = 10; \
 } while (0)
 
-
 static void check_under(void)
 {
        if (pointer == 0)
@@ -184,25 +182,25 @@ struct op {
 
 static const struct op operators[] = {
 #if ENABLE_FEATURE_DC_LIBM
-       {"**",  power},
-       {"exp", power},
-       {"pow", power},
+       {"^",   power},
+//     {"exp", power},
+//     {"pow", power},
 #endif
        {"%",   mod},
-       {"mod", mod},
+//     {"mod", mod},
+       // logic ops are not standard, remove?
        {"and", and},
        {"or",  or},
        {"not", not},
-       {"eor", eor},
        {"xor", eor},
        {"+",   add},
-       {"add", add},
+//     {"add", add},
        {"-",   sub},
-       {"sub", sub},
+//     {"sub", sub},
        {"*",   mul},
-       {"mul", mul},
+//     {"mul", mul},
        {"/",   divide},
-       {"div", divide},
+//     {"div", divide},
        {"p", print_no_pop},
        {"f", print_stack_no_pop},
        {"o", set_output_base},
@@ -243,24 +241,50 @@ static void stack_machine(const char *argument)
        bb_error_msg_and_die("syntax error at '%s'", argument);
 }
 
+static void process_file(FILE *fp)
+{
+       char *line;
+       while ((line = xmalloc_fgetline(fp)) != NULL) {
+               stack_machine(line);
+               free(line);
+       }
+}
+
 int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int dc_main(int argc UNUSED_PARAM, char **argv)
 {
+       bool script = 0;
+
        INIT_G();
 
-//TODO: fix this, should take: dc -eSCRIPT -fFILE FILE
-       argv++;
-       if (!argv[0]) {
-               /* take stuff from stdin if no args are given */
-               char *line;
-               while ((line = xmalloc_fgetline(stdin)) != NULL) {
-                       stack_machine(line);
-                       free(line);
+       /* Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs */
+       for (;;) {
+               int n = getopt(argc, argv, "e:f:");
+               if (n <= 0)
+                       break;
+               switch (n) {
+               case 'e':
+                       script = 1;
+                       stack_machine(optarg);
+                       break;
+               case 'f':
+                       script = 1;
+                       process_file(xfopen_for_read(optarg));
+                       break;
+               default:
+                       bb_show_usage();
                }
-       } else {
-               do {
-                       stack_machine(*argv);
-               } while (*++argv);
        }
+       argv += optind;
+
+       if (*argv) {
+               do
+                       process_file(xfopen_for_read(*argv++));
+               while (*argv);
+       } else if (!script) {
+               /* Take stuff from stdin if no args are given */
+               process_file(stdin);
+       }
+
        return EXIT_SUCCESS;
 }