dc: tweak parsing
No binary (build failed)
—
(log yok)
| @@ -196,14 +196,6 @@ struct op { | |
| }; | |
| static const struct op operators[] = { | |
| - | {"+", add}, |
| - | {"add", add}, |
| - | {"-", sub}, |
| - | {"sub", sub}, |
| - | {"*", mul}, |
| - | {"mul", mul}, |
| - | {"/", divide}, |
| - | {"div", divide}, |
| #if ENABLE_FEATURE_DC_LIBM | |
| {"**", power}, | |
| {"exp", power}, | |
| @@ -216,28 +208,47 @@ static const struct op operators[] = { | |
| {"not", not}, | |
| {"eor", eor}, | |
| {"xor", eor}, | |
| + | {"+", add}, |
| + | {"add", add}, |
| + | {"-", sub}, |
| + | {"sub", sub}, |
| + | {"*", mul}, |
| + | {"mul", mul}, |
| + | {"/", divide}, |
| + | {"div", divide}, |
| {"p", print_no_pop}, | |
| {"f", print_stack_no_pop}, | |
| {"o", set_output_base}, | |
| }; | |
| + | /* Feed the stack machine */ |
| static void stack_machine(const char *argument) | |
| { | |
| char *end; | |
| - | double d; |
| + | double number; |
| const struct op *o; | |
| - | d = strtod(argument, &end); |
| - | if (end != argument && *end == '\0') { |
| - | push(d); |
| - | return; |
| + | next: |
| + | number = strtod(argument, &end); |
| + | if (end != argument) { |
| + | 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; | |
| 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(); | |
| - | return; |
| + | goto next; |
| } | |
| o++; | |
| } while (o != operators + ARRAY_SIZE(operators)); | |
| @@ -254,25 +265,11 @@ int dc_main(int argc UNUSED_PARAM, char **argv) | |
| if (!argv[0]) { | |
| /* take stuff from stdin if no args are given */ | |
| char *line; | |
| - | char *cursor; |
| - | char *token; |
| while ((line = xmalloc_fgetline(stdin)) != NULL) { | |
| - | cursor = line; |
| - | while (1) { |
| - | token = skip_whitespace(cursor); |
| - | if (*token == '\0') |
| - | break; |
| - | cursor = skip_non_whitespace(token); |
| - | if (*cursor != '\0') |
| - | *cursor++ = '\0'; |
| - | stack_machine(token); |
| - | } |
| + | stack_machine(line); |
| free(line); | |
| } | |
| } else { | |
| - | // why? it breaks "dc -2 2 + p" |
| - | //if (argv[0][0] == '-') |
| - | // bb_show_usage(); |
| do { | |
| stack_machine(*argv); | |
| } while (*++argv); | |
| @@ -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" "" |
| + | |