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:#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"

View 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;
}