From owner-svn-src-stable-11@freebsd.org Wed Jun 27 21:03:06 2018 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6B6EF10111BD; Wed, 27 Jun 2018 21:03:06 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 1B0057318E; Wed, 27 Jun 2018 21:03:06 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EF970531; Wed, 27 Jun 2018 21:03:05 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5RL35Hh000640; Wed, 27 Jun 2018 21:03:05 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5RL35eU000639; Wed, 27 Jun 2018 21:03:05 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201806272103.w5RL35eU000639@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Wed, 27 Jun 2018 21:03:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r335739 - in stable/11/usr.bin/seq: . tests X-SVN-Group: stable-11 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/11/usr.bin/seq: . tests X-SVN-Commit-Revision: 335739 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jun 2018 21:03:06 -0000 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 + PROG= seq LIBADD= m + +HAS_TESTS= +SUBDIR.${MK_TESTS}+= tests .include 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);