dc: fix "small dc" to have standard command line API
No binary (build failed)
—
(log yok)
| @@ -159,8 +159,7 @@ | |
| //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" | |
| @@ -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; | |
| } | |