shell: implement optional "BASE#nnnn" numeric literals
No binary (build failed)
—
(log yok)
| @@ -99,6 +99,11 @@ config FEATURE_SH_MATH_64 | |
| slightly larger, but will allow computation with very large numbers. | |
| This is not in POSIX, so do not rely on this in portable code. | |
| + | config FEATURE_SH_MATH_BASE |
| + | bool "Support BASE#nnnn literals" |
| + | default y |
| + | depends on FEATURE_SH_MATH |
| + | |
| config FEATURE_SH_EXTRA_QUIET | |
| bool "Hide message on interactive shell startup" | |
| default y | |
| @@ -513,6 +513,42 @@ static const char op_tokens[] ALIGN1 = { | |
| }; | |
| #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) | |
| + | #if ENABLE_FEATURE_SH_MATH_BASE |
| + | static arith_t strto_arith_t(const char *nptr, char **endptr) |
| + | { |
| + | unsigned base; |
| + | arith_t n; |
| + | |
| + | # if ENABLE_FEATURE_SH_MATH_64 |
| + | n = strtoull(nptr, endptr, 0); |
| + | # else |
| + | n = strtoul(nptr, endptr, 0); |
| + | # endif |
| + | if (**endptr != '#' |
| + | || (*nptr < '1' || *nptr > '9') |
| + | || (n < 2 || n > 64) |
| + | ) { |
| + | return n; |
| + | } |
| + | |
| + | /* It's "N#nnnn" or "NN#nnnn" syntax, NN can't start with 0, |
| + | * NN is in 2..64 range. |
| + | */ |
| + | base = (unsigned)n; |
| + | n = 0; |
| + | nptr = *endptr + 1; |
| + | /* bash allows "N#" (empty "nnnn" part) */ |
| + | while (isdigit(*nptr)) { |
| + | /* bash does not check for overflows */ |
| + | n = n * base + (*nptr++ - '0'); |
| + | } |
| + | *endptr = (char*)nptr; |
| + | return n; |
| + | } |
| + | #define strto_arith_t(nptr, endptr, base_is_always_0) \ |
| + | strto_arith_t(nptr, endptr) |
| + | #endif |
| + | |
| static arith_t FAST_FUNC | |
| evaluate_string(arith_state_t *math_state, const char *expr) | |
| { | |
| @@ -65,15 +65,19 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |
| #if ENABLE_FEATURE_SH_MATH_64 | |
| typedef long long arith_t; | |
| - | #define ARITH_FMT "%lld" |
| - | #define strto_arith_t strtoull |
| + | # define ARITH_FMT "%lld" |
| #else | |
| typedef long arith_t; | |
| - | #define ARITH_FMT "%ld" |
| - | #define strto_arith_t strtoul |
| + | # define ARITH_FMT "%ld" |
| + | #endif |
| + | |
| + | #if !ENABLE_FEATURE_SH_MATH_BASE |
| + | # if ENABLE_FEATURE_SH_MATH_64 |
| + | # define strto_arith_t strtoull |
| + | # else |
| + | # define strto_arith_t strtoul |
| + | # endif |
| #endif | |
| - | //TODO: bash supports "BASE#nnnnn" numeric literals, e.g. 2#1111 = 15. |
| - | //Make strto_arith_t() support that? |
| typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | |
| typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); | |