diff options
-rw-r--r-- | miscutils/bc.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 6ab3a4252..5a4c92a1c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2976,29 +2976,40 @@ static void bc_lex_whitespace(BcLex *l) static BC_STATUS zbc_lex_number(BcLex *l, char start) { const char *buf = l->buf + l->i; - size_t len, hits = 0, bslashes = 0, i = 0, j; - char c = buf[i]; - bool last_pt, pt = start == '.'; + size_t len, bslashes, i, ccnt; + bool pt; - last_pt = pt; + pt = (start == '.'); l->t.t = BC_LEX_NUMBER; - - while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') || - (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n'))) - { - if (c != '\\') { - last_pt = c == '.'; - pt = pt || last_pt; + bslashes = 0; + ccnt = i = 0; + for (;;) { + char c = buf[i]; + if (c == '\0') + break; + if (c == '\\' && buf[i + 1] == '\n') { + i += 2; + bslashes++; + continue; } - else { - ++i; - bslashes += 1; + if (!isdigit(c) && (c < 'A' || c > 'F')) { + if (c != '.') break; + // if '.' was already seen, stop on second one: + if (pt) break; + pt = 1; } - - c = buf[++i]; + // buf[i] is one of "0-9A-F." + 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. if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { 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_expand(&l->t.v, len + 1); + bc_vec_expand(&l->t.v, 1 + len); bc_vec_push(&l->t.v, &start); - for (buf -= 1, j = 1; j < len + hits * 2; ++j) { - - c = buf[j]; - + while (ccnt != 0) { // If we have hit a backslash, skip it. We don't have // to check for a newline because it's guaranteed. - if (hits < bslashes && c == '\\') { - ++hits; - ++j; + if (*buf == '\\') { + buf += 2; + ccnt -= 2; continue; } - - bc_vec_push(&l->t.v, &c); + bc_vec_push(&l->t.v, buf); + buf++; + ccnt--; } bc_vec_pushZeroByte(&l->t.v); - l->i += i; RETURN_STATUS(BC_STATUS_SUCCESS); } |