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>
This commit is contained in:
parent
30a4c32a4d
commit
9edd268bad
@ -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
|
||||
|
36
shell/math.c
36
shell/math.c
@ -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)
|
||||
{
|
||||
|
16
shell/math.h
16
shell/math.h
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user