From 30f0fd29ba6c5cb385908d42cdff89a10af6dfde Mon Sep 17 00:00:00 2001 From: millert Date: Mon, 12 Jun 2023 20:15:06 +0000 Subject: [PATCH] seq: fix check for rounding error/truncation 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. OK deraadt@ --- usr.bin/seq/seq.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/usr.bin/seq/seq.c b/usr.bin/seq/seq.c index 56f678a6de4..be07176072c 100644 --- a/usr.bin/seq/seq.c +++ b/usr.bin/seq/seq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: seq.c,v 1.6 2022/02/25 16:00:39 tb Exp $ */ +/* $OpenBSD: seq.c,v 1.7 2023/06/12 20:15:06 millert Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -89,13 +89,13 @@ main(int argc, char *argv[]) double first = 1.0; double last = 0.0; double incr = 0.0; - double last_shown_value = 0.0; + double prev = 0.0; double cur, step; struct lconv *locale; char *fmt = NULL; const char *sep = "\n"; const char *term = "\n"; - char *cur_print, *last_print; + char *cur_print, *last_print, *prev_print; char pad = ZERO; if (pledge("stdio", NULL) == -1) @@ -176,34 +176,37 @@ main(int argc, char *argv[]) } else fmt = generate_format(first, incr, last, equalize, pad); + warnx("first: %f, incr: %f", first, incr); for (step = 1, cur = first; incr > 0 ? cur <= last : cur >= last; cur = first + incr * step++) { if (cur != first) fputs(sep, stdout); printf(fmt, cur); - last_shown_value = cur; + prev = 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'. + * computed value ('cur') and desired 'last' value are equal. If + * they are equal after formatting truncation, but 'cur' and 'prev' + * are different, 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) == -1 || - asprintf(&last_print, fmt, last) == -1) + asprintf(&last_print, fmt, last) == -1 || + asprintf(&prev_print, fmt, prev) == -1) err(1, "asprintf"); - if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) { + if (strcmp(cur_print, last_print) == 0 && + strcmp(cur_print, prev_print) != 0) { if (cur != first) fputs(sep, stdout); fputs(last_print, stdout); } free(cur_print); free(last_print); + free(prev_print); fputs(term, stdout); -- 2.20.1