seq: explicate incr

* src/seq.c (incr): Change API to make the code easier to follow,
and also to avoid undefined behavior on hypothetical platforms
where '9' == INT_MAX (!).  Caller changed.
This commit is contained in:
Paul Eggert 2024-11-08 09:35:35 -08:00
parent ddb6f5f442
commit ecb157940d

View File

@ -403,24 +403,27 @@ get_default_format (operand first, operand step, operand last)
return "%Lg"; return "%Lg";
} }
/* The NUL-terminated string S0 of length S_LEN represents a valid /* The nonempty char array P represents a valid non-negative decimal integer.
non-negative decimal integer. Adjust the string and length so ENDP points just after the last char in P.
that the pair describe the next-larger value. */ Adjust the array to describe the next-larger integer and return
static void whether this grows the array by one on the left. */
incr (char **s0, size_t *s_len) static bool
incr_grows (char *p, char *endp)
{ {
char *s = *s0;
char *endp = s + *s_len - 1;
do do
{ {
if ((*endp)++ < '9') endp--;
return; if (*endp < '9')
*endp-- = '0'; {
(*endp)++;
return false;
} }
while (endp >= s); *endp = '0';
*--(*s0) = '1'; }
++*s_len; while (p < endp);
p[-1] = '1';
return true;
} }
/* Compare A and B (each a NUL-terminated digit string), with lengths /* Compare A and B (each a NUL-terminated digit string), with lengths
@ -505,8 +508,10 @@ seq_fast (char const *a, char const *b, uintmax_t step)
/* Append separator then number. */ /* Append separator then number. */
while (true) while (true)
{ {
char *endp = p + p_len;
for (uintmax_t n_incr = step; n_incr; n_incr--) for (uintmax_t n_incr = step; n_incr; n_incr--)
incr (&p, &p_len); p -= incr_grows (p, endp);
p_len = endp - p;
if (! inf && 0 < cmp (p, p_len, q, q_len)) if (! inf && 0 < cmp (p, p_len, q, q_len))
break; break;