diff options
author | Denys Vlasenko | 2009-06-05 16:24:29 +0200 |
---|---|---|
committer | Denys Vlasenko | 2009-06-05 16:24:29 +0200 |
commit | 71016baf5524d739d1dd4d9110b111a7c3ddcaf9 (patch) | |
tree | 4d012db2dc2dd20e0956c0b188e52ab43059d2cc | |
parent | 0f952c249e30834a3ee5cd821e9afc3197b05f9c (diff) | |
download | busybox-71016baf5524d739d1dd4d9110b111a7c3ddcaf9.zip busybox-71016baf5524d739d1dd4d9110b111a7c3ddcaf9.tar.gz |
printf: accept negative numbers for %x; sh: overflowed numbers are 0
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/printf.c | 8 | ||||
-rw-r--r-- | shell/math.c | 8 | ||||
-rw-r--r-- | shell/math.h | 4 |
3 files changed, 16 insertions, 4 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index 0b004ea..2beea71 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -78,6 +78,14 @@ static int multiconvert(const char *arg, void *result, converter convert) static void FAST_FUNC conv_strtoull(const char *arg, void *result) { *(unsigned long long*)result = bb_strtoull(arg, NULL, 0); + /* both coreutils 6.10 and bash 3.2: + * $ printf '%x\n' -2 + * fffffffffffffffe + * Mimic that: + */ + if (errno) { + *(unsigned long long*)result = bb_strtoll(arg, NULL, 0); + } } static void FAST_FUNC conv_strtoll(const char *arg, void *result) { diff --git a/shell/math.c b/shell/math.c index cc298bd..d75bcae 100644 --- a/shell/math.c +++ b/shell/math.c @@ -562,7 +562,11 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) } if (isdigit(arithval)) { numstackptr->var = NULL; + errno = 0; + /* call strtoul[l]: */ numstackptr->val = strto_arith_t(expr, (char **) &expr, 0); + if (errno) + numstackptr->val = 0; /* bash compat */ goto num; } for (p = op_tokens; ; p++) { @@ -592,7 +596,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) lasttok = TOK_NUM; /* Plus and minus are binary (not unary) _only_ if the last - * token was as number, or a right paren (which pretends to be + * token was a number, or a right paren (which pretends to be * a number, since it evaluates to one). Think about it. * It makes sense. */ if (lasttok != TOK_NUM) { @@ -611,7 +615,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) break; } } - /* We don't want a unary operator to cause recursive descent on the + /* We don't want an unary operator to cause recursive descent on the * stack, because there can be many in a row and it could cause an * operator to be evaluated before its argument is pushed onto the * integer stack. */ diff --git a/shell/math.h b/shell/math.h index 51dbb56..7b7898e 100644 --- a/shell/math.h +++ b/shell/math.h @@ -80,11 +80,11 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN #if ENABLE_SH_MATH_SUPPORT_64 typedef long long arith_t; #define arith_t_fmt "%lld" -#define strto_arith_t strtoll +#define strto_arith_t strtoull #else typedef long arith_t; #define arith_t_fmt "%ld" -#define strto_arith_t strtol +#define strto_arith_t strtoul #endif typedef const char *(*arith_var_lookup_t)(const char *name); |