aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-05-19 17:23:31 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-05-19 17:23:31 +0200
commit9edd268bad93128bcadfbdde28bb978a4b4c5bab (patch)
tree0163e19dd3fb1dc0b16c3c694f4ba39fee0c5cb8
parent30a4c32a4d21728a7e25025f70fcc1d7cd722fe0 (diff)
downloadbusybox-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>
-rw-r--r--shell/Config.src5
-rw-r--r--shell/math.c36
-rw-r--r--shell/math.h16
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
102config FEATURE_SH_MATH_BASE
103 bool "Support BASE#nnnn literals"
104 default y
105 depends on FEATURE_SH_MATH
106
102config FEATURE_SH_EXTRA_QUIET 107config 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
517static 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
516static arith_t FAST_FUNC 552static arith_t FAST_FUNC
517evaluate_string(arith_state_t *math_state, const char *expr) 553evaluate_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
67typedef long long arith_t; 67typedef long long arith_t;
68#define ARITH_FMT "%lld" 68# define ARITH_FMT "%lld"
69#define strto_arith_t strtoull
70#else 69#else
71typedef long arith_t; 70typedef 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
78typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); 82typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name);
79typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); 83typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val);