bc: code shrink in zbc_lex_number()

function                                             old     new   delta
zbc_lex_number                                       279     190     -89

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-11 17:36:21 +01:00
parent b402ff844c
commit c355c4a7d6

View File

@ -2976,29 +2976,40 @@ static void bc_lex_whitespace(BcLex *l)
static BC_STATUS zbc_lex_number(BcLex *l, char start) static BC_STATUS zbc_lex_number(BcLex *l, char start)
{ {
const char *buf = l->buf + l->i; const char *buf = l->buf + l->i;
size_t len, hits = 0, bslashes = 0, i = 0, j; size_t len, bslashes, i, ccnt;
char c = buf[i]; bool pt;
bool last_pt, pt = start == '.';
last_pt = pt; pt = (start == '.');
l->t.t = BC_LEX_NUMBER; l->t.t = BC_LEX_NUMBER;
bslashes = 0;
while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') || ccnt = i = 0;
(c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n'))) for (;;) {
{ char c = buf[i];
if (c != '\\') { if (c == '\0')
last_pt = c == '.'; break;
pt = pt || last_pt; if (c == '\\' && buf[i + 1] == '\n') {
i += 2;
bslashes++;
continue;
} }
else { if (!isdigit(c) && (c < 'A' || c > 'F')) {
++i; if (c != '.') break;
bslashes += 1; // if '.' was already seen, stop on second one:
if (pt) break;
pt = 1;
} }
// buf[i] is one of "0-9A-F."
c = buf[++i]; i++;
if (c != '.')
ccnt = i;
} }
//i is buf[i] index of the first not-yet-parsed char
l->i += i;
//ccnt is the number of chars in the number string, excluding possible
//trailing "." and possible following trailing "\<newline>"(s).
len = ccnt - bslashes * 2 + 1; // +1 byte for NUL termination
len = i + !last_pt - bslashes * 2;
// This check makes sense only if size_t is (much) larger than BC_MAX_NUM. // This check makes sense only if size_t is (much) larger than BC_MAX_NUM.
if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { if (SIZE_MAX > (BC_MAX_NUM | 0xff)) {
if (len > BC_MAX_NUM) if (len > BC_MAX_NUM)
@ -3006,26 +3017,23 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start)
} }
bc_vec_pop_all(&l->t.v); bc_vec_pop_all(&l->t.v);
bc_vec_expand(&l->t.v, len + 1); bc_vec_expand(&l->t.v, 1 + len);
bc_vec_push(&l->t.v, &start); bc_vec_push(&l->t.v, &start);
for (buf -= 1, j = 1; j < len + hits * 2; ++j) { while (ccnt != 0) {
c = buf[j];
// If we have hit a backslash, skip it. We don't have // If we have hit a backslash, skip it. We don't have
// to check for a newline because it's guaranteed. // to check for a newline because it's guaranteed.
if (hits < bslashes && c == '\\') { if (*buf == '\\') {
++hits; buf += 2;
++j; ccnt -= 2;
continue; continue;
} }
bc_vec_push(&l->t.v, buf);
bc_vec_push(&l->t.v, &c); buf++;
ccnt--;
} }
bc_vec_pushZeroByte(&l->t.v); bc_vec_pushZeroByte(&l->t.v);
l->i += i;
RETURN_STATUS(BC_STATUS_SUCCESS); RETURN_STATUS(BC_STATUS_SUCCESS);
} }