/* seq - print sequence of numbers to standard output.                          This is the seq utility
   Copyright (C) 1994-2018 Free Software Foundation, Inc.                       
                                                                                
   This program is free software: you can redistribute it and/or modify         
   it under the terms of the GNU General Public License as published by         
   the Free Software Foundation, either version 3 of the License, or            
   (at your option) any later version.                                          
                                                                                
   This program is distributed in the hope that it will be useful,              
   but WITHOUT ANY WARRANTY; without even the implied warranty of               
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
   GNU General Public License for more details.                                 
                                                                                
   You should have received a copy of the GNU General Public License            
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */   The GNUv3 license
                                                                                
/* Written by Ulrich Drepper.  */                                               
                                                                                
#include <config.h>                                                             Provides system specific information
#include <getopt.h>                                                             ...!includes auto-comment...
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "c-strtod.h"                                                           ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
#include "xstrtod.h"                                                            ...!includes auto-comment...
                                                                                
/* Roll our own isfinite/isnan rather than using <math.h>, so that we don't     
   have to worry about linking -lm just for isfinite.  */                       
#ifndef isfinite                                                                Line 33
# define isfinite(x) ((x) * 0 == 0)                                             Line 34
#endif                                                                          Line 35
#ifndef isnan                                                                   Line 36
# define isnan(x) ((x) != (x))                                                  Line 37
#endif                                                                          Line 38
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "seq"                                                      Line 41
                                                                                
#define AUTHORS proper_name ("Ulrich Drepper")                                  Line 43
                                                                                
/* If true print all number with equal width.  */                               
static bool equal_width;                                                        Line 46
                                                                                
/* The string used to separate two numbers.  */                                 
static char const *separator;                                                   Line 49
                                                                                
/* The string output after all numbers have been output.                        
   Usually "\n" or "\0".  */                                                    
static char const terminator[] = "\n";                                          Line 53
                                                                                
static struct option const long_options[] =                                     Line 55
{                                                                               
  { "equal-width", no_argument, NULL, 'w'},                                     Line 57
  { "format", required_argument, NULL, 'f'},                                    Line 58
  { "separator", required_argument, NULL, 's'},                                 Line 59
  {GETOPT_HELP_OPTION_DECL},                                                    Line 60
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 61
  { NULL, 0, NULL, 0}                                                           Line 62
};                                                                              Block 1
                                                                                
void                                                                            Line 65
usage (int status)                                                              Line 66
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 68
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 70
    {                                                                           
      printf (_("\                                                              Line 72
Usage: %s [OPTION]... LAST\n\                                                   Line 73
  or:  %s [OPTION]... FIRST LAST\n\                                             Line 74
  or:  %s [OPTION]... FIRST INCREMENT LAST\n\                                   Line 75
"), program_name, program_name, program_name);                                  Line 76
      fputs (_("\                                                               Line 77
Print numbers from FIRST to LAST, in steps of INCREMENT.\n\                     Line 78
"), stdout);                                                                    Line 79
                                                                                
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      fputs (_("\                                                               Line 83
  -f, --format=FORMAT      use printf style floating-point FORMAT\n\            Line 84
  -s, --separator=STRING   use STRING to separate numbers (default: \\n)\n\     Line 85
  -w, --equal-width        equalize width by padding with leading zeroes\n\     Line 86
"), stdout);                                                                    Line 87
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 88
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 89
      fputs (_("\                                                               Line 90
\n\                                                                             
If FIRST or INCREMENT is omitted, it defaults to 1.  That is, an\n\             Line 92
omitted INCREMENT defaults to 1 even when LAST is smaller than FIRST.\n\        Line 93
The sequence of numbers ends when the sum of the current number and\n\          Line 94
INCREMENT would become greater than LAST.\n\                                    Line 95
FIRST, INCREMENT, and LAST are interpreted as floating point values.\n\         Line 96
INCREMENT is usually positive if FIRST is smaller than LAST, and\n\             Line 97
INCREMENT is usually negative if FIRST is greater than LAST.\n\                 Line 98
INCREMENT must not be 0; none of FIRST, INCREMENT and LAST may be NaN.\n\       Line 99
"), stdout);                                                                    Line 100
      fputs (_("\                                                               Line 101
FORMAT must be suitable for printing one argument of type 'double';\n\          Line 102
it defaults to %.PRECf if FIRST, INCREMENT, and LAST are all fixed point\n\     Line 103
decimal numbers with maximum precision PREC, and to %g otherwise.\n\            Line 104
"), stdout);                                                                    Line 105
      emit_ancillary_info (PROGRAM_NAME);                                       Line 106
    }                                                                           
  exit (status);                                                                Line 108
}                                                                               Block 2
                                                                                
/* A command-line operand.  */                                                  
struct operand                                                                  Line 112
{                                                                               
  /* Its value, converted to 'long double'.  */                                 
  long double value;                                                            Line 115
                                                                                
  /* Its print width, if it were printed out in a form similar to its           
     input form.  An input like "-.1" is treated like "-0.1", and an            
     input like "1." is treated like "1", but otherwise widths are              
     left alone.  */                                                            
  size_t width;                                                                 Line 121
                                                                                
  /* Number of digits after the decimal point, or INT_MAX if the                
     number can't easily be expressed as a fixed-point number.  */              
  int precision;                                                                Line 125
};                                                                              
typedef struct operand operand;                                                 Line 127
                                                                                
/* Description of what a number-generating format will generate.  */            
struct layout                                                                   Line 130
{                                                                               
  /* Number of bytes before and after the number.  */                           
  size_t prefix_len;                                                            Line 133
  size_t suffix_len;                                                            Line 134
};                                                                              
                                                                                
/* Read a long double value from the command line.                              
   Return if the string is correct else signal error.  */                       
                                                                                
static operand                                                                  Line 140
scan_arg (const char *arg)                                                      Line 141
{                                                                               
  operand ret;                                                                  Line 143
                                                                                
  if (! xstrtold (arg, NULL, &ret.value, c_strtold))                            Line 145
    {                                                                           
      error (0, 0, _("invalid floating point argument: %s"), quote (arg));      Line 147
      usage (EXIT_FAILURE);                                                     Line 148
    }                                                                           
                                                                                
  if (isnan (ret.value))                                                        Line 151
    {                                                                           
      error (0, 0, _("invalid %s argument: %s"), quote_n (0, "not-a-number"),   Line 153
             quote_n (1, arg));                                                 Line 154
      usage (EXIT_FAILURE);                                                     Line 155
    }                                                                           
                                                                                
  /* We don't output spaces or '+' so don't include in width */                 
  while (isspace (to_uchar (*arg)) || *arg == '+')                              Line 159
    arg++;                                                                      Line 160
                                                                                
  /* Default to auto width and precision.  */                                   
  ret.width = 0;                                                                Line 163
  ret.precision = INT_MAX;                                                      Line 164
                                                                                
  /* Use no precision (and possibly fast generation) for integers.  */          
  char const *decimal_point = strchr (arg, '.');                                Line 167
  if (! decimal_point && ! strchr (arg, 'p') /* not a hex float */)             Line 168
    ret.precision = 0;                                                          Line 169
                                                                                
  /* auto set width and precision for decimal inputs.  */                       
  if (! arg[strcspn (arg, "xX")] && isfinite (ret.value))                       Line 172
    {                                                                           
      size_t fraction_len = 0;                                                  Line 174
      ret.width = strlen (arg);                                                 Line 175
                                                                                
      if (decimal_point)                                                        Line 177
        {                                                                       
          fraction_len = strcspn (decimal_point + 1, "eE");                     Line 179
          if (fraction_len <= INT_MAX)                                          Line 180
            ret.precision = fraction_len;                                       Line 181
          ret.width += (fraction_len == 0                      /* #.  -> #   */ Line 182
                        ? -1                                                    Line 183
                        : (decimal_point == arg                /* .#  -> 0.# */ Line 184
                           || ! ISDIGIT (decimal_point[-1]))); /* -.# -> 0.# */ Line 185
        }                                                                       
      char const *e = strchr (arg, 'e');                                        Line 187
      if (! e)                                                                  Line 188
        e = strchr (arg, 'E');                                                  Line 189
      if (e)                                                                    Line 190
        {                                                                       
          long exponent = strtol (e + 1, NULL, 10);                             Line 192
          ret.precision += exponent < 0 ? -exponent                             Line 193
                                        : - MIN (ret.precision, exponent);      Line 194
          /* Don't account for e.... in the width since this is not output.  */ 
          ret.width -= strlen (arg) - (e - arg);                                Line 196
          /* Adjust the width as per the exponent.  */                          
          if (exponent < 0)                                                     Line 198
            {                                                                   
              if (decimal_point)                                                Line 200
                {                                                               
                  if (e == decimal_point + 1) /* undo #. -> # above  */         Line 202
                    ret.width++;                                                Line 203
                }                                                               
              else                                                              Line 205
                ret.width++;                                                    Line 206
              exponent = -exponent;                                             Line 207
            }                                                                   
          else                                                                  Line 209
            {                                                                   
              if (decimal_point && ret.precision == 0 && fraction_len)          Line 211
                ret.width--; /* discount space for '.'  */                      Line 212
              exponent -= MIN (fraction_len, exponent);                         Line 213
            }                                                                   
          ret.width += exponent;                                                Line 215
        }                                                                       
    }                                                                           
                                                                                
  return ret;                                                                   Line 219
}                                                                               Block 5
                                                                                
/* If FORMAT is a valid printf format for a double argument, return             
   its long double equivalent, allocated from dynamic storage, and              
   store into *LAYOUT a description of the output layout; otherwise,            
   report an error and exit.  */                                                
                                                                                
static char const *                                                             Line 227
long_double_format (char const *fmt, struct layout *layout)                     Line 228
{                                                                               
  size_t i;                                                                     Line 230
  size_t prefix_len = 0;                                                        Line 231
  size_t suffix_len = 0;                                                        Line 232
  size_t length_modifier_offset;                                                Line 233
  bool has_L;                                                                   Line 234
                                                                                
  for (i = 0; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1) Line 236
    {                                                                           
      if (!fmt[i])                                                              Line 238
        die (EXIT_FAILURE, 0,                                                   Line 239
             _("format %s has no %% directive"), quote (fmt));                  Line 240
      prefix_len++;                                                             Line 241
    }                                                                           
                                                                                
  i++;                                                                          Line 244
  i += strspn (fmt + i, "-+#0 '");                                              Line 245
  i += strspn (fmt + i, "0123456789");                                          Line 246
  if (fmt[i] == '.')                                                            Line 247
    {                                                                           
      i++;                                                                      Line 249
      i += strspn (fmt + i, "0123456789");                                      Line 250
    }                                                                           
                                                                                
  length_modifier_offset = i;                                                   Line 253
  has_L = (fmt[i] == 'L');                                                      Line 254
  i += has_L;                                                                   Line 255
  if (fmt[i] == '\0')                                                           Line 256
    die (EXIT_FAILURE, 0, _("format %s ends in %%"), quote (fmt));              Line 257
  if (! strchr ("efgaEFGA", fmt[i]))                                            Line 258
    die (EXIT_FAILURE, 0,                                                       Line 259
         _("format %s has unknown %%%c directive"), quote (fmt), fmt[i]);       Line 260
                                                                                
  for (i++; ; i += (fmt[i] == '%') + 1)                                         Line 262
    if (fmt[i] == '%' && fmt[i + 1] != '%')                                     Line 263
      die (EXIT_FAILURE, 0, _("format %s has too many %% directives"),          Line 264
           quote (fmt));                                                        Line 265
    else if (fmt[i])                                                            Line 266
      suffix_len++;                                                             Line 267
    else                                                                        Line 268
      {                                                                         
        size_t format_size = i + 1;                                             Line 270
        char *ldfmt = xmalloc (format_size + 1);                                Line 271
        memcpy (ldfmt, fmt, length_modifier_offset);                            Line 272
        ldfmt[length_modifier_offset] = 'L';                                    Line 273
        strcpy (ldfmt + length_modifier_offset + 1,                             Line 274
                fmt + length_modifier_offset + has_L);                          Line 275
        layout->prefix_len = prefix_len;                                        Line 276
        layout->suffix_len = suffix_len;                                        Line 277
        return ldfmt;                                                           Line 278
      }                                                                         
}                                                                               Block 6
                                                                                
static void ATTRIBUTE_NORETURN                                                  Line 282
io_error (void)                                                                 Line 283
{                                                                               
  /* FIXME: consider option to silently ignore errno=EPIPE */                   
  clearerr (stdout);                                                            Line 286
  die (EXIT_FAILURE, errno, _("write error"));                                  Line 287
}                                                                               
                                                                                
/* Actually print the sequence of numbers in the specified range, with the      
   given or default stepping and format.  */                                    
                                                                                
static void                                                                     Line 293
print_numbers (char const *fmt, struct layout layout,                           Line 294
               long double first, long double step, long double last)           Line 295
{                                                                               
  bool out_of_range = (step < 0 ? first < last : last < first);                 Line 297
                                                                                
  if (! out_of_range)                                                           Line 299
    {                                                                           
      long double x = first;                                                    Line 301
      long double i;                                                            Line 302
                                                                                
      for (i = 1; ; i++)                                                        Line 304
        {                                                                       
          long double x0 = x;                                                   Line 306
          if (printf (fmt, x) < 0)                                              Line 307
            io_error ();                                                        Line 308
          if (out_of_range)                                                     Line 309
            break;                                                              Line 310
          x = first + i * step;                                                 Line 311
          out_of_range = (step < 0 ? x < last : last < x);                      Line 312
                                                                                
          if (out_of_range)                                                     Line 314
            {                                                                   
              /* If the number just past LAST prints as a value equal           
                 to LAST, and prints differently from the previous              
                 number, then print the number.  This avoids problems           
                 with rounding.  For example, with the x86 it causes            
                 "seq 0 0.000001 0.000003" to print 0.000003 instead            
                 of stopping at 0.000002.  */                                   
                                                                                
              bool print_extra_number = false;                                  Line 323
              long double x_val;                                                Line 324
              char *x_str;                                                      Line 325
              int x_strlen;                                                     Line 326
              setlocale (LC_NUMERIC, "C");                                      Sets up internationalization (i18n)
              x_strlen = asprintf (&x_str, fmt, x);                             Line 328
              setlocale (LC_NUMERIC, "");                                       Sets up internationalization (i18n)
              if (x_strlen < 0)                                                 Line 330
                xalloc_die ();                                                  ...!common auto-comment...
              x_str[x_strlen - layout.suffix_len] = '\0';                       Line 332
                                                                                
              if (xstrtold (x_str + layout.prefix_len, NULL, &x_val, c_strtold) Line 334
                  && x_val == last)                                             Line 335
                {                                                               
                  char *x0_str = NULL;                                          Line 337
                  if (asprintf (&x0_str, fmt, x0) < 0)                          Line 338
                    xalloc_die ();                                              ...!common auto-comment...
                  print_extra_number = !STREQ (x0_str, x_str);                  Line 340
                  free (x0_str);                                                Line 341
                }                                                               
                                                                                
              free (x_str);                                                     Line 344
              if (! print_extra_number)                                         Line 345
                break;                                                          Line 346
            }                                                                   
                                                                                
          if (fputs (separator, stdout) == EOF)                                 Line 349
            io_error ();                                                        Line 350
        }                                                                       
                                                                                
      if (fputs (terminator, stdout) == EOF)                                    Line 353
        io_error ();                                                            Line 354
    }                                                                           
}                                                                               Block 8
                                                                                
/* Return the default format given FIRST, STEP, and LAST.  */                   
static char const *                                                             Line 359
get_default_format (operand first, operand step, operand last)                  Line 360
{                                                                               
  static char format_buf[sizeof "%0.Lf" + 2 * INT_STRLEN_BOUND (int)];          Line 362
                                                                                
  int prec = MAX (first.precision, step.precision);                             Line 364
                                                                                
  if (prec != INT_MAX && last.precision != INT_MAX)                             Line 366
    {                                                                           
      if (equal_width)                                                          Line 368
        {                                                                       
          /* increase first_width by any increased precision in step */         
          size_t first_width = first.width + (prec - first.precision);          Line 371
          /* adjust last_width to use precision from first/step */              
          size_t last_width = last.width + (prec - last.precision);             Line 373
          if (last.precision && prec == 0)                                      Line 374
            last_width--;  /* don't include space for '.' */                    Line 375
          if (last.precision == 0 && prec)                                      Line 376
            last_width++;  /* include space for '.' */                          Line 377
          if (first.precision == 0 && prec)                                     Line 378
            first_width++;  /* include space for '.' */                         Line 379
          size_t width = MAX (first_width, last_width);                         Line 380
          if (width <= INT_MAX)                                                 Line 381
            {                                                                   
              int w = width;                                                    Line 383
              sprintf (format_buf, "%%0%d.%dLf", w, prec);                      Line 384
              return format_buf;                                                Line 385
            }                                                                   
        }                                                                       
      else                                                                      Line 388
        {                                                                       
          sprintf (format_buf, "%%.%dLf", prec);                                Line 390
          return format_buf;                                                    Line 391
        }                                                                       
    }                                                                           
                                                                                
  return "%Lg";                                                                 Line 395
}                                                                               Block 9
                                                                                
/* The NUL-terminated string S0 of length S_LEN represents a valid              
   non-negative decimal integer.  Adjust the string and length so               
   that the pair describe the next-larger value.  */                            
static void                                                                     Line 401
incr (char **s0, size_t *s_len)                                                 Line 402
{                                                                               
  char *s = *s0;                                                                Line 404
  char *endp = s + *s_len - 1;                                                  Line 405
                                                                                
  do                                                                            
    {                                                                           
      if ((*endp)++ < '9')                                                      Line 409
        return;                                                                 Line 410
      *endp-- = '0';                                                            Line 411
    }                                                                           
  while (endp >= s);                                                            Line 413
  *--(*s0) = '1';                                                               Line 414
  ++*s_len;                                                                     Line 415
}                                                                               Block 10
                                                                                
/* Compare A and B (each a NUL-terminated digit string), with lengths           
   given by A_LEN and B_LEN.  Return +1 if A < B, -1 if B < A, else 0.  */      
static int                                                                      Line 420
cmp (char const *a, size_t a_len, char const *b, size_t b_len)                  Line 421
{                                                                               
  if (a_len < b_len)                                                            Line 423
    return -1;                                                                  Line 424
  if (b_len < a_len)                                                            Line 425
    return 1;                                                                   Line 426
  return (strcmp (a, b));                                                       Line 427
}                                                                               Block 11
                                                                                
/* Trim leading 0's from S, but if S is all 0's, leave one.                     
   Return a pointer to the trimmed string.  */                                  
static char const * _GL_ATTRIBUTE_PURE                                          Line 432
trim_leading_zeros (char const *s)                                              Line 433
{                                                                               
  char const *p = s;                                                            Line 435
  while (*s == '0')                                                             Line 436
    ++s;                                                                        Line 437
                                                                                
  /* If there were only 0's, back up, to leave one.  */                         
  if (!*s && s != p)                                                            Line 440
    --s;                                                                        Line 441
  return s;                                                                     Line 442
}                                                                               Block 12
                                                                                
/* Print all whole numbers from A to B, inclusive -- to stdout, each            
   followed by a newline.  If B < A, return false and print nothing.            
   Otherwise, return true.  */                                                  
static bool                                                                     Line 448
seq_fast (char const *a, char const *b)                                         Line 449
{                                                                               
  bool inf = STREQ (b, "inf");                                                  Line 451
                                                                                
  /* Skip past any leading 0's.  Without this, our naive cmp                    
     function would declare 000 to be larger than 99.  */                       
  a = trim_leading_zeros (a);                                                   Line 455
  b = trim_leading_zeros (b);                                                   Line 456
                                                                                
  size_t p_len = strlen (a);                                                    Line 458
  size_t q_len = inf ? 0 : strlen (b);                                          Line 459
                                                                                
  /* Allow for at least 31 digits without realloc.                              
     1 more than p_len is needed for the inf case.  */                          
  size_t inc_size = MAX (MAX (p_len + 1, q_len), 31);                           Line 463
                                                                                
  /* Copy input strings (incl NUL) to end of new buffers.  */                   
  char *p0 = xmalloc (inc_size + 1);                                            Line 466
  char *p = memcpy (p0 + inc_size - p_len, a, p_len + 1);                       Line 467
  char *q;                                                                      Line 468
  char *q0;                                                                     Line 469
  if (! inf)                                                                    Line 470
    {                                                                           
      q0 = xmalloc (inc_size + 1);                                              Line 472
      q = memcpy (q0 + inc_size - q_len, b, q_len + 1);                         Line 473
    }                                                                           
  else                                                                          Line 475
    q = q0 = NULL;                                                              Line 476
                                                                                
  bool ok = inf || cmp (p, p_len, q, q_len) <= 0;                               Line 478
  if (ok)                                                                       Line 479
    {                                                                           
      /* Reduce number of fwrite calls which is seen to                         
         give a speed-up of more than 2x over the unbuffered code               
         when printing the first 10^9 integers.  */                             
      size_t buf_size = MAX (BUFSIZ, (inc_size + 1) * 2);                       Line 484
      char *buf = xmalloc (buf_size);                                           Line 485
      char const *buf_end = buf + buf_size;                                     Line 486
                                                                                
      char *bufp = buf;                                                         Line 488
                                                                                
      /* Write first number to buffer.  */                                      
      bufp = mempcpy (bufp, p, p_len);                                          Line 491
                                                                                
      /* Append separator then number.  */                                      
      while (inf || cmp (p, p_len, q, q_len) < 0)                               Line 494
        {                                                                       
          *bufp++ = *separator;                                                 Line 496
          incr (&p, &p_len);                                                    Line 497
                                                                                
          /* Double up the buffers when needed for the inf case.  */            
          if (p_len == inc_size)                                                Line 500
            {                                                                   
              inc_size *= 2;                                                    Line 502
              p0 = xrealloc (p0, inc_size + 1);                                 Line 503
              p = memmove (p0 + p_len, p0, p_len + 1);                          Line 504
                                                                                
              if (buf_size < (inc_size + 1) * 2)                                Line 506
                {                                                               
                  size_t buf_offset = bufp - buf;                               Line 508
                  buf_size = (inc_size + 1) * 2;                                Line 509
                  buf = xrealloc (buf, buf_size);                               Line 510
                  buf_end = buf + buf_size;                                     Line 511
                  bufp = buf + buf_offset;                                      Line 512
                }                                                               
            }                                                                   
                                                                                
          bufp = mempcpy (bufp, p, p_len);                                      Line 516
          /* If no place for another separator + number then                    
             output buffer so far, and reset to start of buffer.  */            
          if (buf_end - (p_len + 1) < bufp)                                     Line 519
            {                                                                   
              if (fwrite (buf, bufp - buf, 1, stdout) != 1)                     Line 521...!syscalls auto-comment...
                io_error ();                                                    Line 522
              bufp = buf;                                                       Line 523
            }                                                                   
        }                                                                       
                                                                                
      /* Write any remaining buffered output, and the terminator.  */           
      *bufp++ = *terminator;                                                    Line 528
      if (fwrite (buf, bufp - buf, 1, stdout) != 1)                             Line 529...!syscalls auto-comment...
        io_error ();                                                            Line 530
                                                                                
      IF_LINT (free (buf));                                                     Line 532
    }                                                                           
                                                                                
  free (p0);                                                                    Line 535
  free (q0);                                                                    Line 536
  return ok;                                                                    Line 537
}                                                                               Block 13
                                                                                
/* Return true if S consists of at least one digit and no non-digits.  */       
static bool _GL_ATTRIBUTE_PURE                                                  Line 541
all_digits_p (char const *s)                                                    Line 542
{                                                                               
  size_t n = strlen (s);                                                        Line 544
  return ISDIGIT (s[0]) && n == strspn (s, "0123456789");                       Line 545
}                                                                               Block 14
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 549
{                                                                               
  int optc;                                                                     Line 551
  operand first = { 1, 1, 0 };                                                  Line 552
  operand step = { 1, 1, 0 };                                                   Line 553
  operand last;                                                                 Line 554
  struct layout layout = { 0, 0 };                                              Line 555
                                                                                
  /* The printf(3) format used for output.  */                                  
  char const *format_str = NULL;                                                Line 558
                                                                                
  initialize_main (&argc, &argv);                                               VMS-specific entry point handling wildcard expansion
  set_program_name (argv[0]);                                                   Retains program name and discards path
  setlocale (LC_ALL, "");                                                       Sets up internationalization (i18n)
  bindtextdomain (PACKAGE, LOCALEDIR);                                          Assigns i18n directorySets text domain for _() [gettext()] function
  textdomain (PACKAGE);                                                         Sets text domain for _() [gettext()] function
                                                                                
  atexit (close_stdout);                                                        Close stdout on exit (see gnulib)
                                                                                
  equal_width = false;                                                          Line 568
  separator = "\n";                                                             Line 569
                                                                                
  /* We have to handle negative numbers in the command line but this            
     conflicts with the command line arguments.  So explicitly check first      
     whether the next argument looks like a negative number.  */                
  while (optind < argc)                                                         Line 574
    {                                                                           
      if (argv[optind][0] == '-'                                                Line 576
          && ((optc = argv[optind][1]) == '.' || ISDIGIT (optc)))               Line 577
        {                                                                       
          /* means negative number */                                           
          break;                                                                Line 580
        }                                                                       
                                                                                
      optc = getopt_long (argc, argv, "+f:s:w", long_options, NULL);            Line 583
      if (optc == -1)                                                           Line 584
        break;                                                                  Line 585
                                                                                
      switch (optc)                                                             Line 587
        {                                                                       
        case 'f':                                                               Line 589
          format_str = optarg;                                                  Line 590
          break;                                                                Line 591
                                                                                
        case 's':                                                               Line 593
          separator = optarg;                                                   Line 594
          break;                                                                Line 595
                                                                                
        case 'w':                                                               Line 597
          equal_width = true;                                                   Line 598
          break;                                                                Line 599
                                                                                
        case_GETOPT_HELP_CHAR;                                                  Line 601
                                                                                
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 603
                                                                                
        default:                                                                Line 605
          usage (EXIT_FAILURE);                                                 Line 606
        }                                                                       
    }                                                                           
                                                                                
  unsigned int n_args = argc - optind;                                          Line 610
  if (n_args < 1)                                                               Line 611
    {                                                                           
      error (0, 0, _("missing operand"));                                       Line 613
      usage (EXIT_FAILURE);                                                     Line 614
    }                                                                           
                                                                                
  if (3 < n_args)                                                               Line 617
    {                                                                           
      error (0, 0, _("extra operand %s"), quote (argv[optind + 3]));            Line 619
      usage (EXIT_FAILURE);                                                     Line 620
    }                                                                           
                                                                                
  if (format_str)                                                               Line 623
    format_str = long_double_format (format_str, &layout);                      Line 624
                                                                                
  if (format_str != NULL && equal_width)                                        Line 626
    {                                                                           
      error (0, 0, _("format string may not be specified"                       Line 628
                     " when printing equal width strings"));                    Line 629
      usage (EXIT_FAILURE);                                                     Line 630
    }                                                                           
                                                                                
  /* If the following hold:                                                     
     - no format string, [FIXME: relax this, eventually]                        
     - integer start (or no start)                                              
     - integer end                                                              
     - increment == 1 or not specified [FIXME: relax this, eventually]          
     then use the much more efficient integer-only code.  */                    
  if (all_digits_p (argv[optind])                                               Line 639
      && (n_args == 1 || all_digits_p (argv[optind + 1]))                       Line 640
      && (n_args < 3 || (STREQ ("1", argv[optind + 1])                          Line 641
                         && all_digits_p (argv[optind + 2])))                   Line 642
      && !equal_width && !format_str && strlen (separator) == 1)                Line 643
    {                                                                           
      char const *s1 = n_args == 1 ? "1" : argv[optind];                        Line 645
      char const *s2 = argv[optind + (n_args - 1)];                             Line 646
      if (seq_fast (s1, s2))                                                    Line 647
        return EXIT_SUCCESS;                                                    Line 648
                                                                                
      /* Upon any failure, let the more general code deal with it.  */          
    }                                                                           
                                                                                
  last = scan_arg (argv[optind++]);                                             Line 653
                                                                                
  if (optind < argc)                                                            Line 655
    {                                                                           
      first = last;                                                             Line 657
      last = scan_arg (argv[optind++]);                                         Line 658
                                                                                
      if (optind < argc)                                                        Line 660
        {                                                                       
          step = last;                                                          Line 662
          if (step.value == 0)                                                  Line 663
            {                                                                   
              error (0, 0, _("invalid Zero increment value: %s"),               Line 665
                     quote (argv[optind-1]));                                   Line 666
              usage (EXIT_FAILURE);                                             Line 667
            }                                                                   
                                                                                
          last = scan_arg (argv[optind++]);                                     Line 670
        }                                                                       
    }                                                                           
                                                                                
  if ((isfinite (first.value) && first.precision == 0)                          Line 674
      && step.precision == 0 && last.precision == 0                             Line 675
      && 0 <= first.value && step.value == 1 && 0 <= last.value                 Line 676
      && !equal_width && !format_str && strlen (separator) == 1)                Line 677
    {                                                                           
      char *s1;                                                                 Line 679
      char *s2;                                                                 Line 680
      if (asprintf (&s1, "%0.Lf", first.value) < 0)                             Line 681
        xalloc_die ();                                                          ...!common auto-comment...
      if (! isfinite (last.value))                                              Line 683
        s2 = xstrdup ("inf"); /* Ensure "inf" is used.  */                      Line 684
      else if (asprintf (&s2, "%0.Lf", last.value) < 0)                         Line 685
        xalloc_die ();                                                          ...!common auto-comment...
                                                                                
      if (*s1 != '-' && *s2 != '-' && seq_fast (s1, s2))                        Line 688
        {                                                                       
          IF_LINT (free (s1));                                                  Line 690
          IF_LINT (free (s2));                                                  Line 691
          return EXIT_SUCCESS;                                                  Line 692
        }                                                                       
                                                                                
      free (s1);                                                                Line 695
      free (s2);                                                                Line 696
      /* Upon any failure, let the more general code deal with it.  */          
    }                                                                           
                                                                                
  if (format_str == NULL)                                                       Line 700
    format_str = get_default_format (first, step, last);                        Line 701
                                                                                
  print_numbers (format_str, layout, first.value, step.value, last.value);      Line 703
                                                                                
  return EXIT_SUCCESS;                                                          Line 705
}                                                                               Block 15