X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fseq.c;h=8986192930e61025f22ec06840c18add4928217c;hb=cd8eece88ed6da58209a18a8c3edac73eab27e1c;hp=51e3add8168f361de95d66c2b3983ee5a6a45ffe;hpb=73a20f355102b715e1ce5f5d268539ee932de708;p=oweals%2Fbusybox.git diff --git a/coreutils/seq.c b/coreutils/seq.c index 51e3add81..898619293 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -4,39 +4,106 @@ * * Copyright (C) 2004, Glenn McGrath * - * Licensed under the GPL v2, see the file LICENSE in this tarball. + * Licensed under GPLv2, see file LICENSE in this source tree. */ -#include -#include -#include "busybox.h" +//usage:#define seq_trivial_usage +//usage: "[-w] [-s SEP] [FIRST [INC]] LAST" +//usage:#define seq_full_usage "\n\n" +//usage: "Print numbers from FIRST to LAST, in steps of INC.\n" +//usage: "FIRST, INC default to 1.\n" +//usage: "\n -w Pad to last with leading zeros" +//usage: "\n -s SEP String separator" -extern int seq_main(int argc, char **argv) +#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, first, increment, i; - + 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; first = increment = 1; + errno = 0; switch (argc) { - case 4: - increment=atof(argv[2]); + char *pp; case 3: - first=atof(argv[1]); + increment = strtod(argv[1], &pp); + errno |= *pp; case 2: - last=atof(argv[argc -1]); - break; + first = strtod(argv[0], &pp); + errno |= *pp; + case 1: + last = strtod(argv[argc-1], &pp); + if (!errno && *pp == '\0') + break; default: bb_show_usage(); } - /* You should note that this is pos-5.0.91 semantics, -- FK. */ - if (first < last ? increment > 0 : increment < 0) { - for (i = first; - (first < last) ? (i <= last) : (i >= last); - i += increment) - { - printf("%g\n", i); - } +#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; + } + if (!(opt & OPT_w)) + width = 0; + + sep = ""; + v = first; + n = 0; + while (increment >= 0 ? v <= last : v >= last) { + if (printf("%s%0*.*f", sep, width, frac_part, v) < 0) + break; /* I/O error, bail out (yes, this really happens) */ + 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 EXIT_SUCCESS; + return fflush_all(); }