git: e54db9a9ccd5 - main - seq: fix check for rounding error/truncation

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Mon, 19 Jun 2023 15:28:56 UTC
The branch main has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=e54db9a9ccd588f650a2e57bf9d1cbbafc0e12eb

commit e54db9a9ccd588f650a2e57bf9d1cbbafc0e12eb
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2023-06-19 01:37:06 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2023-06-19 15:02:38 +0000

    seq: fix check for rounding error/truncation
    
    Based on OpenBSD 30f0fd29ba6c:
    > We need to compare the printable version of the last value displayed,
    > not the floating point representation.  Otherwise, we may print the
    > last value twice.
    
    PR:             271964
    Reported by:    Daniel Kolesa
    Reviewed by:    yuripv
    Obtained from:  OpenBSD
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D40601
---
 usr.bin/seq/seq.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/usr.bin/seq/seq.c b/usr.bin/seq/seq.c
index 85fca6e88792..3618a106ec9e 100644
--- a/usr.bin/seq/seq.c
+++ b/usr.bin/seq/seq.c
@@ -88,14 +88,14 @@ main(int argc, char *argv[])
 {
 	const char *sep, *term;
 	struct lconv *locale;
-	char pad, *fmt, *cur_print, *last_print;
-	double first, last, incr, last_shown_value, cur, step;
+	char pad, *fmt, *cur_print, *last_print, *prev_print;
+	double first, last, incr, prev, cur, step;
 	int c, errflg, equalize;
 
 	pad = ZERO;
 	fmt = NULL;
 	first = 1.0;
-	last = incr = last_shown_value = 0.0;
+	last = incr = prev = 0.0;
 	c = errflg = equalize = 0;
 	sep = "\n";
 	term = NULL;
@@ -186,7 +186,7 @@ main(int argc, char *argv[])
 	    cur = first + incr * step++) {
 		printf(fmt, cur);
 		fputs(sep, stdout);
-		last_shown_value = cur;
+		prev = cur;
 	}
 
 	/*
@@ -194,10 +194,9 @@ main(int argc, char *argv[])
 	 *
 	 * 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'.
+	 * are equal after formatting truncation, but 'cur' and 'prev' 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'.
 	 */
 	if (asprintf(&cur_print, fmt, cur) < 0) {
 		err(1, "asprintf");
@@ -205,12 +204,17 @@ main(int argc, char *argv[])
 	if (asprintf(&last_print, fmt, last) < 0) {
 		err(1, "asprintf");
 	}
-	if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) {
+	if (asprintf(&prev_print, fmt, prev) < 0) {
+		err(1, "asprintf");
+	}
+	if (strcmp(cur_print, last_print) == 0 &&
+	    strcmp(cur_print, prev_print) != 0) {
 		fputs(last_print, stdout);
 		fputs(sep, stdout);
 	}
 	free(cur_print);
 	free(last_print);
+	free(prev_print);
 
 	if (term != NULL)
 		fputs(term, stdout);