bc: simplify string-tonumber conversion code

function                                             old     new   delta
bc_program_num                                      1108     983    -125
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-125)           Total: -125 bytes
   text	   data	    bss	    dec	    hex	filename
 985831	    477	   7296	 993604	  f2944	busybox_old
 985706	    477	   7296	 993479	  f28c7	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-09 13:21:54 +01:00
parent 3129f705fc
commit 4a024c7719

View File

@ -2199,49 +2199,45 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
static bool bc_num_strValid(const char *val, size_t base) static bool bc_num_strValid(const char *val, size_t base)
{ {
BcDig b; BcDig b;
bool small, radix = false; bool radix;
size_t i, len = strlen(val);
if (!len) return true;
small = base <= 10;
b = (BcDig)(small ? base + '0' : base - 10 + 'A');
for (i = 0; i < len; ++i) {
BcDig c = val[i];
b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A');
radix = false;
for (;;) {
BcDig c = *val++;
if (c == '\0')
break;
if (c == '.') { if (c == '.') {
if (radix) return false; if (radix) return false;
radix = true; radix = true;
continue; continue;
} }
if (c < '0' || c >= b || (c > '9' && c < 'A'))
if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b)))
return false; return false;
} }
return true; return true;
} }
// Note: n is already "bc_num_zero()"ed,
// leading zeroes in "val" are removed
static void bc_num_parseDecimal(BcNum *n, const char *val) static void bc_num_parseDecimal(BcNum *n, const char *val)
{ {
size_t len, i; size_t len, i;
const char *ptr; const char *ptr;
bool zero = true; bool zero;
for (i = 0; val[i] == '0'; ++i);
val += i;
len = strlen(val); len = strlen(val);
bc_num_zero(n); if (len == 0)
return;
if (len != 0) { zero = true;
for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.'; for (i = 0; val[i]; ++i) {
bc_num_expand(n, len); if (val[i] != '0' && val[i] != '.') {
zero = false;
break;
}
} }
bc_num_expand(n, len);
ptr = strchr(val, '.'); ptr = strchr(val, '.');
@ -2255,26 +2251,29 @@ static void bc_num_parseDecimal(BcNum *n, const char *val)
} }
} }
// Note: n is already "bc_num_zero()"ed,
// leading zeroes in "val" are removed
static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base)
{ {
BcStatus s; BcStatus s;
BcNum temp, mult, result; BcNum temp, mult, result;
BcDig c = '\0'; BcDig c = '\0';
bool zero = true;
unsigned long v; unsigned long v;
size_t i, digits, len = strlen(val); size_t i, digits;
bc_num_zero(n); for (i = 0; ; ++i) {
if (val[i] == '\0')
for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); return;
if (zero) return; if (val[i] != '.' && val[i] != '0')
break;
}
bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&temp);
bc_num_init_DEF_SIZE(&mult); bc_num_init_DEF_SIZE(&mult);
for (i = 0; i < len; ++i) { for (;;) {
c = *val++;
c = val[i]; if (c == '\0') goto int_err;
if (c == '.') break; if (c == '.') break;
v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
@ -2286,19 +2285,15 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base)
if (s) goto int_err; if (s) goto int_err;
} }
if (i == len) {
c = val[i];
if (c == 0) goto int_err;
}
bc_num_init(&result, base->len); bc_num_init(&result, base->len);
//bc_num_zero(&result); - already is //bc_num_zero(&result); - already is
bc_num_one(&mult); bc_num_one(&mult);
for (i += 1, digits = 0; i < len; ++i, ++digits) { digits = 0;
for (;;) {
c = val[i]; c = *val++;
if (c == 0) break; if (c == '\0') break;
digits++;
v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
@ -2318,8 +2313,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base)
if (n->len != 0) { if (n->len != 0) {
if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); if (n->rdx < digits) bc_num_extend(n, digits - n->rdx);
} } else
else
bc_num_zero(n); bc_num_zero(n);
err: err:
@ -2498,6 +2492,9 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
if (!bc_num_strValid(val, base_t)) if (!bc_num_strValid(val, base_t))
return bc_error("bad number string"); return bc_error("bad number string");
bc_num_zero(n);
while (*val == '0') val++;
if (base_t == 10) if (base_t == 10)
bc_num_parseDecimal(n, val); bc_num_parseDecimal(n, val);
else else
@ -6387,7 +6384,7 @@ static BcStatus bc_program_asciify(void)
{ {
BcStatus s; BcStatus s;
BcResult *r, res; BcResult *r, res;
BcNum *num = NULL, n; BcNum *num, n;
char *str, *str2, c; char *str, *str2, c;
size_t len = G.prog.strs.len, idx; size_t len = G.prog.strs.len, idx;
unsigned long val; unsigned long val;
@ -6396,6 +6393,7 @@ static BcStatus bc_program_asciify(void)
return bc_error_stack_has_too_few_elements(); return bc_error_stack_has_too_few_elements();
r = bc_vec_top(&G.prog.results); r = bc_vec_top(&G.prog.results);
num = NULL; // TODO: is this NULL needed?
s = bc_program_num(r, &num, false); s = bc_program_num(r, &num, false);
if (s) return s; if (s) return s;