Skip to content

Commit

Permalink
shell: implement optional "BASE#nnnn" numeric literals
Browse files Browse the repository at this point in the history
function                                             old     new   delta
evaluate_string                                      729     851    +122

Signed-off-by: Denys Vlasenko <[email protected]>
  • Loading branch information
Denys Vlasenko committed May 19, 2019
1 parent 30a4c32 commit 9edd268
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
5 changes: 5 additions & 0 deletions shell/Config.src
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions shell/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
16 changes: 10 additions & 6 deletions shell/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9edd268

Please sign in to comment.