svn commit: r335739 - in stable/11/usr.bin/seq: . tests
Kyle Evans
kevans at FreeBSD.org
Wed Jun 27 21:03:06 UTC 2018
Author: kevans
Date: Wed Jun 27 21:03:05 2018
New Revision: 335739
URL: https://svnweb.freebsd.org/changeset/base/335739
Log:
MFC r330086, r333155: seq(1) improvements
MFC r330086 (cem): seq(1): Consistently include 'last' for non-integers
The source of error is a rounded increment being too large and thus the loop
steps slightly past 'last'. Perform a final comparison using the formatted
string values (truncated precision) to determine if we still need to print
the 'last' value.
MFC r333155: seq(1): Move long_opts up with globals
PR: 217149
Added:
stable/11/usr.bin/seq/tests/
- copied from r330086, head/usr.bin/seq/tests/
Modified:
stable/11/usr.bin/seq/Makefile
stable/11/usr.bin/seq/seq.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/usr.bin/seq/Makefile
==============================================================================
--- stable/11/usr.bin/seq/Makefile Wed Jun 27 21:00:09 2018 (r335738)
+++ stable/11/usr.bin/seq/Makefile Wed Jun 27 21:03:05 2018 (r335739)
@@ -1,8 +1,13 @@
# $NetBSD: Makefile,v 1.3 2009/04/14 22:15:26 lukem Exp $
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= seq
LIBADD= m
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
.include <bsd.prog.mk>
Modified: stable/11/usr.bin/seq/seq.c
==============================================================================
--- stable/11/usr.bin/seq/seq.c Wed Jun 27 21:00:09 2018 (r335738)
+++ stable/11/usr.bin/seq/seq.c Wed Jun 27 21:03:05 2018 (r335739)
@@ -57,6 +57,15 @@ __FBSDID("$FreeBSD$");
static const char *decimal_point = "."; /* default */
static char default_format[] = { "%g" }; /* default */
+static const struct option long_opts[] =
+{
+ {"format", required_argument, NULL, 'f'},
+ {"separator", required_argument, NULL, 's'},
+ {"terminator", required_argument, NULL, 't'},
+ {"equal-width", no_argument, NULL, 'w'},
+ {NULL, no_argument, NULL, 0}
+};
+
/* Prototypes */
static double e_atof(const char *);
@@ -68,15 +77,6 @@ static int valid_format(const char *);
static char *generate_format(double, double, double, int, char);
static char *unescape(char *);
-static const struct option long_opts[] =
-{
- {"format", required_argument, NULL, 'f'},
- {"separator", required_argument, NULL, 's'},
- {"terminator", required_argument, NULL, 't'},
- {"equal-width", no_argument, NULL, 'w'},
- {NULL, no_argument, NULL, 0}
-};
-
/*
* The seq command will print out a numeric sequence from 1, the default,
* to a user specified upper limit by 1. The lower bound and increment
@@ -86,17 +86,20 @@ static const struct option long_opts[] =
int
main(int argc, char *argv[])
{
- int c = 0, errflg = 0;
- int equalize = 0;
- double first = 1.0;
- double last = 0.0;
- double incr = 0.0;
+ const char *sep, *term;
struct lconv *locale;
- char *fmt = NULL;
- const char *sep = "\n";
- const char *term = NULL;
- char pad = ZERO;
+ char pad, *fmt, *cur_print, *last_print;
+ double first, last, incr, last_shown_value, cur, step;
+ int c, errflg, equalize;
+ pad = ZERO;
+ fmt = NULL;
+ first = 1.0;
+ last = incr = last_shown_value = 0.0;
+ c = errflg = equalize = 0;
+ sep = "\n";
+ term = NULL;
+
/* Determine the locale's decimal point. */
locale = localeconv();
if (locale && locale->decimal_point && locale->decimal_point[0] != '\0')
@@ -179,17 +182,32 @@ main(int argc, char *argv[])
} else
fmt = generate_format(first, incr, last, equalize, pad);
- if (incr > 0) {
- for (; first <= last; first += incr) {
- printf(fmt, first);
- fputs(sep, stdout);
- }
- } else {
- for (; first >= last; first += incr) {
- printf(fmt, first);
- fputs(sep, stdout);
- }
+ for (step = 1, cur = first; incr > 0 ? cur <= last : cur >= last;
+ cur = first + incr * step++) {
+ printf(fmt, cur);
+ fputs(sep, stdout);
+ last_shown_value = cur;
}
+
+ /*
+ * Did we miss the last value of the range in the loop above?
+ *
+ * We might have, so check if the printable version of the last
+ * computed value ('cur') and desired 'last' value are equal. If they
+ * are equal after formatting truncation, but 'cur' and
+ * 'last_shown_value' are not equal, it means the exit condition of the
+ * loop held true due to a rounding error and we still need to print
+ * 'last'.
+ */
+ asprintf(&cur_print, fmt, cur);
+ asprintf(&last_print, fmt, last);
+ if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) {
+ fputs(last_print, stdout);
+ fputs(sep, stdout);
+ }
+ free(cur_print);
+ free(last_print);
+
if (term != NULL)
fputs(term, stdout);
More information about the svn-src-stable
mailing list