dc: tweak parsing
https://bugs.debian.org/538685 dc requires whitespace between language elements. We were requiring 1 2 + p instead of the abbreviated 1 2+p (for example). function old new delta stack_machine 97 126 +29 dc_main 117 79 -38 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 29/-38) Total: -9 bytes Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
8e92df15b5
commit
70e30e8eec
@ -196,14 +196,6 @@ struct op {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct op operators[] = {
|
static const struct op operators[] = {
|
||||||
{"+", add},
|
|
||||||
{"add", add},
|
|
||||||
{"-", sub},
|
|
||||||
{"sub", sub},
|
|
||||||
{"*", mul},
|
|
||||||
{"mul", mul},
|
|
||||||
{"/", divide},
|
|
||||||
{"div", divide},
|
|
||||||
#if ENABLE_FEATURE_DC_LIBM
|
#if ENABLE_FEATURE_DC_LIBM
|
||||||
{"**", power},
|
{"**", power},
|
||||||
{"exp", power},
|
{"exp", power},
|
||||||
@ -216,28 +208,47 @@ static const struct op operators[] = {
|
|||||||
{"not", not},
|
{"not", not},
|
||||||
{"eor", eor},
|
{"eor", eor},
|
||||||
{"xor", eor},
|
{"xor", eor},
|
||||||
|
{"+", add},
|
||||||
|
{"add", add},
|
||||||
|
{"-", sub},
|
||||||
|
{"sub", sub},
|
||||||
|
{"*", mul},
|
||||||
|
{"mul", mul},
|
||||||
|
{"/", 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},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Feed the stack machine */
|
||||||
static void stack_machine(const char *argument)
|
static void stack_machine(const char *argument)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
double d;
|
double number;
|
||||||
const struct op *o;
|
const struct op *o;
|
||||||
|
|
||||||
d = strtod(argument, &end);
|
next:
|
||||||
if (end != argument && *end == '\0') {
|
number = strtod(argument, &end);
|
||||||
push(d);
|
if (end != argument) {
|
||||||
return;
|
argument = end;
|
||||||
|
push(number);
|
||||||
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We might have matched a digit, eventually advance the argument */
|
||||||
|
argument = skip_whitespace(argument);
|
||||||
|
|
||||||
|
if (*argument == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
o = operators;
|
o = operators;
|
||||||
do {
|
do {
|
||||||
if (strcmp(o->name, argument) == 0) {
|
const size_t name_len = strlen(o->name);
|
||||||
|
if (strncmp(o->name, argument, name_len) == 0) {
|
||||||
|
argument += name_len;
|
||||||
o->function();
|
o->function();
|
||||||
return;
|
goto next;
|
||||||
}
|
}
|
||||||
o++;
|
o++;
|
||||||
} while (o != operators + ARRAY_SIZE(operators));
|
} while (o != operators + ARRAY_SIZE(operators));
|
||||||
@ -254,25 +265,11 @@ int dc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (!argv[0]) {
|
if (!argv[0]) {
|
||||||
/* take stuff from stdin if no args are given */
|
/* take stuff from stdin if no args are given */
|
||||||
char *line;
|
char *line;
|
||||||
char *cursor;
|
|
||||||
char *token;
|
|
||||||
while ((line = xmalloc_fgetline(stdin)) != NULL) {
|
while ((line = xmalloc_fgetline(stdin)) != NULL) {
|
||||||
cursor = line;
|
stack_machine(line);
|
||||||
while (1) {
|
|
||||||
token = skip_whitespace(cursor);
|
|
||||||
if (*token == '\0')
|
|
||||||
break;
|
|
||||||
cursor = skip_non_whitespace(token);
|
|
||||||
if (*cursor != '\0')
|
|
||||||
*cursor++ = '\0';
|
|
||||||
stack_machine(token);
|
|
||||||
}
|
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// why? it breaks "dc -2 2 + p"
|
|
||||||
//if (argv[0][0] == '-')
|
|
||||||
// bb_show_usage();
|
|
||||||
do {
|
do {
|
||||||
stack_machine(*argv);
|
stack_machine(*argv);
|
||||||
} while (*++argv);
|
} while (*++argv);
|
||||||
|
56
testsuite/dc.tests
Executable file
56
testsuite/dc.tests
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2015 by Bernhard Reutner-Fischer
|
||||||
|
# Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||||
|
|
||||||
|
. ./testing.sh
|
||||||
|
|
||||||
|
# testing "test name" "command" "expected result" "file input" "stdin"
|
||||||
|
|
||||||
|
testing "dc basic syntax (stdin, multiple args)" \
|
||||||
|
"dc" \
|
||||||
|
"30\n" \
|
||||||
|
"" "10 20+p"
|
||||||
|
|
||||||
|
testing "dc basic syntax (argv, single arg)" \
|
||||||
|
"dc '10 20+p'" \
|
||||||
|
"30\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc basic syntax (argv, multiple args)" \
|
||||||
|
"dc 10 20+p" \
|
||||||
|
"30\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc complex with spaces (single arg)" \
|
||||||
|
"dc '8 8 * 2 2 + / p'" \
|
||||||
|
"16\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc complex without spaces (single arg)" \
|
||||||
|
"dc '8 8*2 2+/p'" \
|
||||||
|
"16\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc complex with spaces (multiple args)" \
|
||||||
|
"dc 8 8 \* 2 2 + / p" \
|
||||||
|
"16\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc complex without spaces (multiple args)" \
|
||||||
|
"dc 8 8\*2 2+/p" \
|
||||||
|
"16\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
exit $FAILCOUNT
|
||||||
|
|
||||||
|
# we do not support arguments
|
||||||
|
testing "dc -e <exprs>" \
|
||||||
|
"dc -e '10 2+f'" \
|
||||||
|
"12\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
|
testing "dc -f <exprs-from-given-file>" \
|
||||||
|
"dc -f input" \
|
||||||
|
"12\n" \
|
||||||
|
"10 2+f" ""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user