diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-15 11:16:27 +0400 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-15 11:16:27 +0400 |
commit | cd3dd42c28832da92ee0d4d3afe7cf722e38f80c (patch) | |
tree | 6c97c10fb539f2d8cb8d3f34eff73ac6bcecf70b /coreutils/seq.c | |
parent | 82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09 (diff) |
seq: fix testsuite failures
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils/seq.c')
-rw-r--r-- | coreutils/seq.c | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/coreutils/seq.c b/coreutils/seq.c index 4b853c698..bb39a5b54 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -6,12 +6,10 @@ * * Licensed under the GPL v2, see the file LICENSE in this tarball. */ - #include "libbb.h" /* This is a NOFORK applet. Be very careful! */ - int seq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int seq_main(int argc, char **argv) { @@ -19,35 +17,72 @@ int seq_main(int argc, char **argv) OPT_w = (1 << 0), OPT_s = (1 << 1), }; - double last, increment, i; + double first, last, increment, v; + unsigned n; + unsigned width; + unsigned frac_part; const char *sep, *opt_s = "\n"; unsigned opt = getopt32(argv, "+ws:", &opt_s); - unsigned width = 0; argc -= optind; argv += optind; - i = increment = 1; + first = increment = 1; + errno = 0; switch (argc) { + char *pp; case 3: - increment = atof(argv[1]); + increment = strtod(argv[1], &pp); + errno |= *pp; case 2: - i = atof(*argv); + first = strtod(argv[0], &pp); + errno |= *pp; case 1: - last = atof(argv[argc-1]); - break; + last = strtod(argv[argc-1], &pp); + if (!errno && *pp == '\0') + break; default: bb_show_usage(); } - if (opt & OPT_w) /* Pad to length of start or last */ - width = MAX(strlen(*argv), strlen(argv[argc-1])); - /* You should note that this is pos-5.0.91 semantics, -- FK. */ + /* Last checked to be compatible with: coreutils-6.10 */ + width = 0; + frac_part = 0; + while (1) { + char *dot = strchrnul(*argv, '.'); + int w = (dot - *argv); + int f = strlen(dot); + if (width < w) + width = w; + argv++; + if (!*argv) + break; + /* Why do the above _before_ frac check below? + * Try "seq 1 2.0" and "seq 1.0 2.0": + * coreutils never pay attention to the number + * of fractional digits in last arg. */ + if (frac_part < f) + frac_part = f; + } + if (frac_part) { + frac_part--; + if (frac_part) + width += frac_part + 1; + } + if (!(opt & OPT_w)) + width = 0; + sep = ""; - while ((increment > 0 && i <= last) || (increment < 0 && i >= last)) { - printf("%s%0*g", sep, width, i); + v = first; + n = 0; + while (increment >= 0 ? v <= last : v >= last) { + printf("%s%0*.*f", sep, width, frac_part, v); sep = opt_s; - i += increment; + /* v += increment; - would accumulate floating point errors */ + n++; + v = first + n * increment; } - bb_putchar('\n'); + if (n) /* if while loop executed at least once */ + bb_putchar('\n'); + return fflush(stdout); } |