X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fseq.c;h=03ae3c632be4a175144e4c466ae12c5296734edc;hb=8d680b51148b9cbe7dd3afd37022f3390dd999ef;hp=cf856bf0416dcb0d61e5e0f93f9bf235591c0443;hpb=c021cb08b58dee7480fe6035d8ac00f0dbe83188;p=oweals%2Fbusybox.git diff --git a/coreutils/seq.c b/coreutils/seq.c index cf856bf04..03ae3c632 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -6,47 +6,94 @@ * * 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) { - double last, increment, i; - enum { OPT_w = 1, OPT_s }; - const char *sep = "\n"; - bool is_consecutive = 0; - unsigned opt = getopt32(argv, "+ws:", &sep); - unsigned width = 0; + enum { + OPT_w = (1 << 0), + OPT_s = (1 << 1), + }; + double first, last, increment, v; + unsigned n; + unsigned width; + unsigned frac_part; + const char *sep, *opt_s = "\n"; + unsigned opt; + +#if ENABLE_LOCALE_SUPPORT + /* Undo busybox.c: on input, we want to use dot + * as fractional separator, regardless of current locale */ + setlocale(LC_NUMERIC, "C"); +#endif + opt = getopt32(argv, "+ws:", &opt_s); 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. */ - while ((increment > 0 && i <= last) || (increment < 0 && i >= last)) { - if (is_consecutive++) { - printf("%s", sep); - } - printf("%0*g", width, i); - i += increment; + +#if ENABLE_LOCALE_SUPPORT + setlocale(LC_NUMERIC, ""); +#endif + + /* 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; } - bb_putchar('\n'); + if (!(opt & OPT_w)) + width = 0; + + sep = ""; + v = first; + n = 0; + while (increment >= 0 ? v <= last : v >= last) { + printf("%s%0*.*f", sep, width, frac_part, v); + sep = opt_s; + /* v += increment; - would accumulate floating point errors */ + n++; + v = first + n * increment; + } + if (n) /* if while loop executed at least once */ + bb_putchar('\n'); + return fflush(stdout); }