diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-19 17:23:31 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-19 17:23:31 +0200 |
| commit | 9edd268bad93128bcadfbdde28bb978a4b4c5bab (patch) | |
| tree | 0163e19dd3fb1dc0b16c3c694f4ba39fee0c5cb8 /shell | |
| parent | 30a4c32a4d21728a7e25025f70fcc1d7cd722fe0 (diff) | |
| download | busybox-w32-9edd268bad93128bcadfbdde28bb978a4b4c5bab.tar.gz busybox-w32-9edd268bad93128bcadfbdde28bb978a4b4c5bab.tar.bz2 busybox-w32-9edd268bad93128bcadfbdde28bb978a4b4c5bab.zip | |
shell: implement optional "BASE#nnnn" numeric literals
function old new delta
evaluate_string 729 851 +122
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/Config.src | 5 | ||||
| -rw-r--r-- | shell/math.c | 36 | ||||
| -rw-r--r-- | shell/math.h | 16 |
3 files changed, 51 insertions, 6 deletions
diff --git a/shell/Config.src b/shell/Config.src index bc7218fe5..d7623f774 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
| @@ -99,6 +99,11 @@ config FEATURE_SH_MATH_64 | |||
| 99 | slightly larger, but will allow computation with very large numbers. | 99 | slightly larger, but will allow computation with very large numbers. |
| 100 | This is not in POSIX, so do not rely on this in portable code. | 100 | This is not in POSIX, so do not rely on this in portable code. |
| 101 | 101 | ||
| 102 | config FEATURE_SH_MATH_BASE | ||
| 103 | bool "Support BASE#nnnn literals" | ||
| 104 | default y | ||
| 105 | depends on FEATURE_SH_MATH | ||
| 106 | |||
| 102 | config FEATURE_SH_EXTRA_QUIET | 107 | config FEATURE_SH_EXTRA_QUIET |
| 103 | bool "Hide message on interactive shell startup" | 108 | bool "Hide message on interactive shell startup" |
| 104 | default y | 109 | default y |
diff --git a/shell/math.c b/shell/math.c index 611b3beab..2ea0317e9 100644 --- a/shell/math.c +++ b/shell/math.c | |||
| @@ -513,6 +513,42 @@ static const char op_tokens[] ALIGN1 = { | |||
| 513 | }; | 513 | }; |
| 514 | #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) | 514 | #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) |
| 515 | 515 | ||
| 516 | #if ENABLE_FEATURE_SH_MATH_BASE | ||
| 517 | static arith_t strto_arith_t(const char *nptr, char **endptr) | ||
| 518 | { | ||
| 519 | unsigned base; | ||
| 520 | arith_t n; | ||
| 521 | |||
| 522 | # if ENABLE_FEATURE_SH_MATH_64 | ||
| 523 | n = strtoull(nptr, endptr, 0); | ||
| 524 | # else | ||
| 525 | n = strtoul(nptr, endptr, 0); | ||
| 526 | # endif | ||
| 527 | if (**endptr != '#' | ||
| 528 | || (*nptr < '1' || *nptr > '9') | ||
| 529 | || (n < 2 || n > 64) | ||
| 530 | ) { | ||
| 531 | return n; | ||
| 532 | } | ||
| 533 | |||
| 534 | /* It's "N#nnnn" or "NN#nnnn" syntax, NN can't start with 0, | ||
| 535 | * NN is in 2..64 range. | ||
| 536 | */ | ||
| 537 | base = (unsigned)n; | ||
| 538 | n = 0; | ||
| 539 | nptr = *endptr + 1; | ||
| 540 | /* bash allows "N#" (empty "nnnn" part) */ | ||
| 541 | while (isdigit(*nptr)) { | ||
| 542 | /* bash does not check for overflows */ | ||
| 543 | n = n * base + (*nptr++ - '0'); | ||
| 544 | } | ||
| 545 | *endptr = (char*)nptr; | ||
| 546 | return n; | ||
| 547 | } | ||
| 548 | #define strto_arith_t(nptr, endptr, base_is_always_0) \ | ||
| 549 | strto_arith_t(nptr, endptr) | ||
| 550 | #endif | ||
| 551 | |||
| 516 | static arith_t FAST_FUNC | 552 | static arith_t FAST_FUNC |
| 517 | evaluate_string(arith_state_t *math_state, const char *expr) | 553 | evaluate_string(arith_state_t *math_state, const char *expr) |
| 518 | { | 554 | { |
diff --git a/shell/math.h b/shell/math.h index 2c5ae9b44..ec9decb1f 100644 --- a/shell/math.h +++ b/shell/math.h | |||
| @@ -65,15 +65,19 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
| 65 | 65 | ||
| 66 | #if ENABLE_FEATURE_SH_MATH_64 | 66 | #if ENABLE_FEATURE_SH_MATH_64 |
| 67 | typedef long long arith_t; | 67 | typedef long long arith_t; |
| 68 | #define ARITH_FMT "%lld" | 68 | # define ARITH_FMT "%lld" |
| 69 | #define strto_arith_t strtoull | ||
| 70 | #else | 69 | #else |
| 71 | typedef long arith_t; | 70 | typedef long arith_t; |
| 72 | #define ARITH_FMT "%ld" | 71 | # define ARITH_FMT "%ld" |
| 73 | #define strto_arith_t strtoul | 72 | #endif |
| 73 | |||
| 74 | #if !ENABLE_FEATURE_SH_MATH_BASE | ||
| 75 | # if ENABLE_FEATURE_SH_MATH_64 | ||
| 76 | # define strto_arith_t strtoull | ||
| 77 | # else | ||
| 78 | # define strto_arith_t strtoul | ||
| 79 | # endif | ||
| 74 | #endif | 80 | #endif |
| 75 | //TODO: bash supports "BASE#nnnnn" numeric literals, e.g. 2#1111 = 15. | ||
| 76 | //Make strto_arith_t() support that? | ||
| 77 | 81 | ||
| 78 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | 82 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); |
| 79 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); | 83 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); |
