338
/* The NUL-terminated string S0 of length S_LEN represents a valid
339
non-negative decimal integer. Adjust the string and length so
340
that the pair describe the next-larger value. */
342
incr (char **s0, size_t *s_len)
345
char *endp = s + *s_len - 1;
358
/* Compare A and B (each a NUL-terminated digit string), with lengths
359
given by A_LEN and B_LEN. Return +1 if A < B, -1 if B < A, else 0. */
361
cmp (char const *a, size_t a_len, char const *b, size_t b_len)
367
return (strcmp (a, b));
370
/* Trim leading 0's from S, but if S is all 0's, leave one.
371
Return a pointer to the trimmed string. */
372
static char const * _GL_ATTRIBUTE_PURE
373
trim_leading_zeros (char const *s)
379
/* If there were only 0's, back up, to leave one. */
385
/* Print all whole numbers from A to B, inclusive -- to stdout, each
386
followed by a newline. If B < A, return false and print nothing.
387
Otherwise, return true. */
389
seq_fast (char const *a, char const *b)
391
/* Skip past any leading 0's. Without this, our naive cmp
392
function would declare 000 to be larger than 99. */
393
a = trim_leading_zeros (a);
394
b = trim_leading_zeros (b);
396
size_t p_len = strlen (a);
397
size_t q_len = strlen (b);
398
size_t n = MAX (p_len, q_len);
399
char *p0 = xmalloc (n + 1);
400
char *p = memcpy (p0 + n - p_len, a, p_len + 1);
401
char *q0 = xmalloc (n + 1);
402
char *q = memcpy (q0 + n - q_len, b, q_len + 1);
404
bool ok = cmp (p, p_len, q, q_len) <= 0;
407
/* Buffer at least this many output lines per fwrite call.
408
This gives a speed-up of more than 2x over the unbuffered code
409
when printing the first 10^9 integers. */
411
char *buf = xmalloc (N * (n + 1));
412
char const *buf_end = buf + N * (n + 1);
416
while (cmp (p, p_len, q, q_len) < 0)
419
z = mempcpy (z, p, p_len);
421
if (buf_end - n - 1 < z)
423
fwrite (buf, z - buf, 1, stdout);
428
/* Write any remaining, buffered output. */
430
fwrite (buf, z - buf, 1, stdout);
432
IF_LINT (free (buf));
440
/* Return true if S consists of at least one digit and no non-digits. */
441
static bool _GL_ATTRIBUTE_PURE
442
all_digits_p (char const *s)
444
size_t n = strlen (s);
445
return ISDIGIT (s[0]) && n == strspn (s, "0123456789");
340
449
main (int argc, char **argv)
414
524
format_str = long_double_format (format_str, &layout);
526
if (format_str != NULL && equal_width)
528
error (0, 0, _("format string may not be specified"
529
" when printing equal width strings"));
530
usage (EXIT_FAILURE);
533
/* If the following hold:
534
- no format string, [FIXME: relax this, eventually]
535
- integer start (or no start)
537
- increment == 1 or not specified [FIXME: relax this, eventually]
538
then use the much more efficient integer-only code. */
539
if (all_digits_p (argv[optind])
540
&& (n_args == 1 || all_digits_p (argv[optind + 1]))
541
&& (n_args < 3 || STREQ ("1", argv[optind + 2]))
542
&& !equal_width && !format_str && strlen (separator) == 1)
544
char const *s1 = n_args == 1 ? "1" : argv[optind];
545
char const *s2 = n_args == 1 ? argv[optind] : argv[optind + 1];
546
if (seq_fast (s1, s2))
549
/* Upon any failure, let the more general code deal with it. */
416
552
last = scan_arg (argv[optind++]);
418
554
if (optind < argc)
430
if (format_str != NULL && equal_width)
566
if (first.precision == 0 && step.precision == 0 && last.precision == 0
567
&& 0 <= first.value && step.value == 1 && 0 <= last.value
568
&& !equal_width && !format_str && strlen (separator) == 1)
433
format string may not be specified when printing equal width strings"));
434
usage (EXIT_FAILURE);
572
if (asprintf (&s1, "%0.Lf", first.value) < 0)
574
if (asprintf (&s2, "%0.Lf", last.value) < 0)
577
if (seq_fast (s1, s2))
586
/* Upon any failure, let the more general code deal with it. */
437
589
if (format_str == NULL)