dc: fix "small dc" to have standard command line API

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-08 18:59:07 +01:00
parent 23427a63fc
commit d0bc5fdfea
2 changed files with 48 additions and 25 deletions

View File

@ -159,8 +159,7 @@
//usage: //usage:
//usage:#define dc_full_usage "\n" //usage:#define dc_full_usage "\n"
//usage: "\nTiny RPN calculator. Operations:" //usage: "\nTiny RPN calculator. Operations:"
//usage: "\n+, -, *, /, %, ^, exp, ~, divmod, |, " //usage: "\n+, -, *, /, %, ~, ^, |,"
//usage: "modular exponentiation,"
//usage: "\np - print top of the stack (without popping)" //usage: "\np - print top of the stack (without popping)"
//usage: "\nf - print entire stack" //usage: "\nf - print entire stack"
//usage: "\nk - pop the value and set the precision" //usage: "\nk - pop the value and set the precision"

View File

@ -20,7 +20,6 @@ typedef unsigned long long data_t;
#define DATA_FMT "ll" #define DATA_FMT "ll"
#endif #endif
struct globals { struct globals {
unsigned pointer; unsigned pointer;
unsigned base; unsigned base;
@ -36,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(
base = 10; \ base = 10; \
} while (0) } while (0)
static void check_under(void) static void check_under(void)
{ {
if (pointer == 0) if (pointer == 0)
@ -184,25 +182,25 @@ struct op {
static const struct op operators[] = { static const struct op operators[] = {
#if ENABLE_FEATURE_DC_LIBM #if ENABLE_FEATURE_DC_LIBM
{"**", power}, {"^", power},
{"exp", power}, // {"exp", power},
{"pow", power}, // {"pow", power},
#endif #endif
{"%", mod}, {"%", mod},
{"mod", mod}, // {"mod", mod},
// logic ops are not standard, remove?
{"and", and}, {"and", and},
{"or", or}, {"or", or},
{"not", not}, {"not", not},
{"eor", eor},
{"xor", eor}, {"xor", eor},
{"+", add}, {"+", add},
{"add", add}, // {"add", add},
{"-", sub}, {"-", sub},
{"sub", sub}, // {"sub", sub},
{"*", mul}, {"*", mul},
{"mul", mul}, // {"mul", mul},
{"/", divide}, {"/", divide},
{"div", divide}, // {"div", divide},
{"p", print_no_pop}, {"p", print_no_pop},
{"f", print_stack_no_pop}, {"f", print_stack_no_pop},
{"o", set_output_base}, {"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); bb_error_msg_and_die("syntax error at '%s'", argument);
} }
int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; static void process_file(FILE *fp)
int dc_main(int argc UNUSED_PARAM, char **argv)
{ {
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; char *line;
while ((line = xmalloc_fgetline(stdin)) != NULL) { while ((line = xmalloc_fgetline(fp)) != NULL) {
stack_machine(line); stack_machine(line);
free(line); free(line);
} }
} else { }
do {
stack_machine(*argv); int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
} while (*++argv); int dc_main(int argc UNUSED_PARAM, char **argv)
{
bool script = 0;
INIT_G();
/* 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();
} }
}
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; return EXIT_SUCCESS;
} }