1 /* seq - print sequence of numbers to standard output.
2 Copyright (C) 94, 1995, 96 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Ulrich Drepper. */
29 static double scan_double_arg
__P ((const char *arg
));
30 static int check_format
__P ((const char *format_string
));
31 static char *get_width_format
__P ((void));
32 static int print_numbers
__P ((const char *format_str
));
34 /* If nonzero print all number with equal width. */
35 static int equal_width
;
37 /* The printf(3) format used for output. */
38 static char *format_str
;
40 /* The starting number. */
43 /* The name that this program was run with. */
46 /* The string used to separate two numbers. */
47 static char *separator
;
49 /* The string output after all numbers have been output.
50 Usually "\n" or "\0". */
51 /* FIXME: make this an option. */
52 static char *terminator
= "\n";
54 /* If nonzero, display usage information and exit. */
57 /* If nonzero, print the version on standard output and exit. */
58 static int show_version
;
63 /* The last number. */
66 static struct option
const long_options
[] =
68 { "equal-width", no_argument
, NULL
, 'w'},
69 { "format", required_argument
, NULL
, 'f'},
70 { "help", no_argument
, &show_help
, 1},
71 { "separator", required_argument
, NULL
, 's'},
72 { "version", no_argument
, &show_version
, 1},
80 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
85 Usage: %s [OPTION]... LAST\n\
86 or: %s [OPTION]... FIRST LAST\n\
87 or: %s [OPTION]... FIRST INCREMENT LAST\n\
88 "), program_name
, program_name
, program_name
);
90 Print numbers from FIRST (default 1) to LAST, moving by STEP (default 1).\n\
92 -f, --format FORMAT use printf(3) style FORMAT (default: %%g)\n\
93 -s, --separator STRING use STRING for separating numbers (default: \\n)\n\
94 -w, --equal-width equalize width by padding with leading zeroes\n\
95 --help display this help and exit\n\
96 --version output version information and exit\n\
98 FIRST, INCREMENT, and LAST are interpreted as floating point values.\n\
99 INCREMENT should be positive if FIRST is smaller than LAST, and negative\n\
100 otherwise. When given, the FORMAT argument must contain exactly one of\n\
101 the printf-style, floating point output formats %%e, %%f, or %%g.\n\
108 main (int argc
, char **argv
)
114 program_name
= argv
[0];
115 setlocale (LC_ALL
, "");
116 bindtextdomain (PACKAGE
, LOCALEDIR
);
117 textdomain (PACKAGE
);
125 /* We have to handle negative numbers in the command line but this
126 conflicts with the command line arguments. So the getopt mode is
127 REQUIRE_ORDER (the '+' in the format string) and it abort on the
128 first non-option or negative number. */
129 while ((optc
= getopt_long (argc
, argv
, "+0123456789f:s:w", long_options
,
132 if ('0' <= optc
&& optc
<= '9')
134 /* means negative number */
163 printf ("seq - %s\n", PACKAGE_VERSION
);
175 error (0, 0, _("too few arguments"));
179 last
= scan_double_arg (argv
[optind
++]);
184 last
= scan_double_arg (argv
[optind
++]);
190 last
= scan_double_arg (argv
[optind
++]);
200 if (format_str
!= NULL
&& equal_width
)
203 format string may not be specified when printing equal width strings"));
209 step
= first
<= last
? 1.0 : -1.0;
212 if (format_str
!= NULL
)
214 if (!check_format (format_str
))
216 error (0, 0, _("invalid format string: `%s'"), format_str
);
223 format_str
= get_width_format ();
228 errs
= print_numbers (format_str
);
234 /* Read a double value from the command line.
235 Return if the string is correct else signal error. */
238 scan_double_arg (const char *arg
)
242 if (xstrtod (arg
, NULL
, &ret_val
))
244 error (0, 0, _("invalid floating point argument: %s"), arg
);
252 /* Check whether the format string is valid for a single double
254 Return 0 if not, 1 if correct. */
257 check_format (const char *format_string
)
259 while (*format_string
!= '\0')
261 if (*format_string
== '%')
264 if (*format_string
!= '%')
270 if (*format_string
== '\0')
273 format_string
+= strspn (format_string
, "-+#0");
274 if (isdigit (*format_string
))
276 format_string
+= strspn (format_string
, "012345789");
278 if (*format_string
== '.')
279 format_string
+= strspn (++format_string
, "0123456789");
282 if (*format_string
!= 'e' && *format_string
!= 'f' &&
283 *format_string
!= 'g')
287 while (*format_string
!= '\0')
289 if (*format_string
== '%')
292 if (*format_string
!= '%')
302 #if defined (HAVE_RINT) && defined (HAVE_MODF) && defined (HAVE_FLOOR)
304 /* Return a printf-style format string with which all selected numbers
305 will format to strings of the same width. */
310 static char buffer
[256];
320 min_val
= first
- step
* floor ((first
- last
) / step
);
326 max_val
= first
+ step
* floor ((last
- first
) / step
);
329 sprintf (buffer
, "%g", rint (max_val
));
330 if (buffer
[strspn (buffer
, "0123456789")] != '\0')
332 width1
= strlen (buffer
);
336 sprintf (buffer
, "%g", rint (min_val
));
337 if (buffer
[strspn (buffer
, "-0123456789")] != '\0')
339 width2
= strlen (buffer
);
341 width1
= width1
> width2
? width1
: width2
;
345 sprintf (buffer
, "%g", 1.0 + modf (min_val
, &temp
));
346 width1
= strlen (buffer
);
351 if (buffer
[0] != '1' || buffer
[1] != '.' ||
352 buffer
[2 + strspn (&buffer
[2], "0123456789")] != '\0')
357 sprintf (buffer
, "%g", 1.0 + modf (step
, &temp
));
358 width2
= strlen (buffer
);
363 if (buffer
[0] != '1' || buffer
[1] != '.' ||
364 buffer
[2 + strspn (&buffer
[2], "0123456789")] != '\0')
368 frac_width
= width1
> width2
? width1
: width2
;
371 sprintf (buffer
, "%%0%d.%df", full_width
+ 1 + frac_width
, frac_width
);
373 sprintf (buffer
, "%%0%dg", full_width
);
378 #else /* one of the math functions rint, modf, floor is missing. */
381 get_width_format (void)
383 /* We cannot compute the needed information to determine the correct
384 answer. So we simply return a value that works for all cases. */
390 /* Actually print the sequence of numbers in the specified range, with the
391 given or default stepping and format. */
393 print_numbers (const char *format_str
)
402 _("when the starting value is larger than the limit,\n\
403 the increment must be negative"));
408 printf (format_str
, first
);
409 for (i
= 1; /* empty */; i
++)
411 double x
= first
+ i
* step
;
416 fputs (separator
, stdout
);
417 printf (format_str
, x
);
427 _("when the starting value is smaller than the limit,\n\
428 the increment must be positive"));
433 printf (format_str
, first
);
434 for (i
= 1; /* empty */; i
++)
436 double x
= first
+ i
* step
;
441 fputs (separator
, stdout
);
442 printf (format_str
, x
);
445 fputs (terminator
, stdout
);