From nobody Wed Nov 16 05:20:51 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NBrwz5dq7z4dFfX; Wed, 16 Nov 2022 05:20:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NBrwz56hxz3JL7; Wed, 16 Nov 2022 05:20:51 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668576051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VzeZa8ypW95Lxsgw7WJM/ovWARTPdvsxiN+E9Fu+9XM=; b=SeEtBrucJc+qKu7WQNJWTc4li+vF7ZK5dqwhO5urDzxfJhNa9+dZy6HZODqhcB9y177XaA 2yDVZ9mJ5st7q/2FQ/APZCi/MSLTnZZ4fUVI58upGENIuOgzDO1fiZPIZ9RK7ed3INmYzi JjBqJjTzKZzFY/hgeis/oSTw4wbVUf3YpCOeNz4oyLlnLfflKZur2nuH9E8AXnkIcFLVT/ Un7ILU790mHxJxFQoN9heHBy4ZCMluGkmC6CFMdnddt03k8AhiyyWVhxC8nQWKTPiFcwiD AmDzqrosz+m0FcCiibcqiVrnbBtrymXtjrgSvEG/EjNtEh7uVAB8FQrJ2HkCHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668576051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VzeZa8ypW95Lxsgw7WJM/ovWARTPdvsxiN+E9Fu+9XM=; b=yKZZa06LDm/5C43wNVeZNGYBODK7Mx70T7ZrG7p2duwumO/IiVsBYXZpaYTKBlICIoWKty DEwhfDB+QREzH3epAgdUD0wAcIFyf4hzgvnXKJEjpsfmXla8/KetvFhfUurboAqRnUwmWk pEwr/WmMZRxcU8kIlI2ccB3lCXaWtyEBFUn7sBVMcGuK8ROpYmZoimDrc4rvQTVYiW3fdp dXZe6xCGJhMfZxAxW/PBJ1B3SC82pu3C8BUsHpGtzD4+QveIkAJEBSOcRt0woQuiWMBhNM ZTzvxfXfD3Xyyu1cZqzcYYsUAdy1zA05RRPCeLf1liVDcs3Fy9H7yS+i5fJkOA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1668576051; a=rsa-sha256; cv=none; b=KM6jfFa1n6JRvTBSxWSDy0nJGWvBz/8a3U5ZEAvo3NZJPEkhIPtITxVPadL70MP1NJwIbH Ci3RfGxn1yt7q0HJeKg6aDZXYeOPPBl/zICf3kjLKAzLFlM3WEwBJMfPcY++3IHcRK5Eg7 HT68JPBNX3mtP+B9ofECwOO8Y4ANw9XUui35YyvMuu6YEsiCyFW63UzQGNe3nyf3aOAg1Z wPPqwUWFMFAFuXWBERPATl7pcJv6RmBKanhd1p5Io8cmXqVg0a0hruejlo5mxNOt/xHJsL HoV31BFPhH7KoJY2+qlyWxe/3nPto85s9MaMw/Z9eK5G+hikbKQg36yXDwKcSw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NBrwz49V8zqdP; Wed, 16 Nov 2022 05:20:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2AG5Kp2P021419; Wed, 16 Nov 2022 05:20:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2AG5Kp9K021418; Wed, 16 Nov 2022 05:20:51 GMT (envelope-from git) Date: Wed, 16 Nov 2022 05:20:51 GMT Message-Id: <202211160520.2AG5Kp9K021418@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: afb4998dd4de - main - rs: Use getopt() and strtol() instead of mannual parsing. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: afb4998dd4de03c2d635faf7db89f3d3f6c3a6ff Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=afb4998dd4de03c2d635faf7db89f3d3f6c3a6ff commit afb4998dd4de03c2d635faf7db89f3d3f6c3a6ff Author: John Baldwin AuthorDate: 2022-11-16 05:19:35 +0000 Commit: John Baldwin CommitDate: 2022-11-16 05:19:35 +0000 rs: Use getopt() and strtol() instead of mannual parsing. This uses the "::" extension to getopt() to handle options which take an optional argument. The updated flag tests were all wrong before and only passed because the manual parser failed to raise errors when a required argument was missing. The invalid argument test now gets a better error message. Reviewed by: brooks, imp, emaste Differential Revision: https://reviews.freebsd.org/D36834 --- usr.bin/rs/rs.cc | 247 ++++++++++++++++++-------------------------- usr.bin/rs/tests/rs_test.sh | 11 +- 2 files changed, 104 insertions(+), 154 deletions(-) diff --git a/usr.bin/rs/rs.cc b/usr.bin/rs/rs.cc index c20956b3b5e1..8989288e3ec7 100644 --- a/usr.bin/rs/rs.cc +++ b/usr.bin/rs/rs.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include static long flags; @@ -63,9 +64,6 @@ static long flags; #define NOARGS 0200000 static short *colwidths; -static short *cord; -static short *icbd; -static short *ocbd; static std::vector elem; static char *curline; static size_t curlen; @@ -76,13 +74,12 @@ static int skip; static int propgutter; static char isep = ' ', osep = ' '; static char blank[] = ""; -static int owidth = 80, gutter = 2; +static size_t owidth = 80, gutter = 2; static void getargs(int, char *[]); static void getfile(void); static int get_line(void); -static char *getlist(short **, char *); -static char *getnum(int *, char *, int); +static long getnum(const char *); static void prepfile(void); static void prints(char *, int); static void putfile(void); @@ -120,7 +117,7 @@ getfile(void) return; } get_line(); - if (flags & NOARGS && curlen < (size_t)owidth) + if (flags & NOARGS && curlen < owidth) flags |= ONEPERLINE; if (flags & ONEPERLINE) icols = 1; @@ -226,7 +223,7 @@ prepfile(void) else if (orows == 0 && ocols == 0) { /* decide rows and cols */ ocols = owidth / colw; if (ocols == 0) { - warnx("display width %d is less than column width %zu", + warnx("display width %zu is less than column width %zu", owidth, colw); ocols = 1; } @@ -338,101 +335,95 @@ static void getargs(int ac, char *av[]) { long val; - char *p; + int ch; if (ac == 1) { flags |= NOARGS | TRANSPOSE; } - while (--ac && **++av == '-') - for (p = *av+1; *p; p++) - switch (*p) { - case 'T': - flags |= MTRANSPOSE; - /* FALLTHROUGH */ - case 't': - flags |= TRANSPOSE; - break; - case 'c': /* input col. separator */ - flags |= ONEISEPONLY; - /* FALLTHROUGH */ - case 's': /* one or more allowed */ - if (p[1]) - isep = *++p; - else - isep = '\t'; /* default is ^I */ - break; - case 'C': - flags |= ONEOSEPONLY; - /* FALLTHROUGH */ - case 'S': - if (p[1]) - osep = *++p; - else - osep = '\t'; /* default is ^I */ - break; - case 'w': /* window width, default 80 */ - p = getnum(&owidth, p, 0); - if (owidth <= 0) - errx(1, "width must be a positive integer"); - break; - case 'K': /* skip N lines */ - flags |= SKIPPRINT; - /* FALLTHROUGH */ - case 'k': /* skip, do not print */ - p = getnum(&skip, p, 0); - if (!skip) - skip = 1; - break; - case 'm': - flags |= NOTRIMENDCOL; - break; - case 'g': /* gutter space */ - p = getnum(&gutter, p, 0); - break; - case 'G': - p = getnum(&propgutter, p, 0); - break; - case 'e': /* each line is an entry */ - flags |= ONEPERLINE; - break; - case 'E': - flags |= ONEPERCHAR; - break; - case 'j': /* right adjust */ - flags |= RIGHTADJUST; - break; - case 'n': /* null padding for missing values */ - flags |= NULLPAD; - break; - case 'y': - flags |= RECYCLE; - break; - case 'H': /* print shape only */ - flags |= DETAILSHAPE; - /* FALLTHROUGH */ - case 'h': - flags |= SHAPEONLY; - break; - case 'z': /* squeeze col width */ - flags |= SQUEEZE; - break; - /*case 'p': - ipagespace = atoi(++p); (default is 1) - break;*/ - case 'o': /* col order */ - p = getlist(&cord, p); - break; - case 'b': - flags |= ICOLBOUNDS; - p = getlist(&icbd, p); - break; - case 'B': - flags |= OCOLBOUNDS; - p = getlist(&ocbd, p); - break; - default: - usage(); - } + + while ((ch = getopt(ac, av, "C::EG:HK:S::Tc::eg:hjk:mns::tw:yz")) != -1) + switch (ch) { + case 'T': + flags |= MTRANSPOSE; + /* FALLTHROUGH */ + case 't': + flags |= TRANSPOSE; + break; + case 'c': /* input col. separator */ + flags |= ONEISEPONLY; + /* FALLTHROUGH */ + case 's': /* one or more allowed */ + if (optarg != NULL) + isep = *optarg; + else + isep = '\t'; /* default is ^I */ + break; + case 'C': + flags |= ONEOSEPONLY; + /* FALLTHROUGH */ + case 'S': + if (optarg != NULL) + osep = *optarg; + else + osep = '\t'; /* default is ^I */ + break; + case 'w': /* window width, default 80 */ + val = getnum(optarg); + if (val <= 0) + errx(1, "width must be a positive integer"); + owidth = val; + break; + case 'K': /* skip N lines */ + flags |= SKIPPRINT; + /* FALLTHROUGH */ + case 'k': /* skip, do not print */ + skip = getnum(optarg); + if (skip < 1) + skip = 1; + break; + case 'm': + flags |= NOTRIMENDCOL; + break; + case 'g': /* gutter space */ + gutter = getnum(optarg); + break; + case 'G': + propgutter = getnum(optarg); + break; + case 'e': /* each line is an entry */ + flags |= ONEPERLINE; + break; + case 'E': + flags |= ONEPERCHAR; + break; + case 'j': /* right adjust */ + flags |= RIGHTADJUST; + break; + case 'n': /* null padding for missing values */ + flags |= NULLPAD; + break; + case 'y': + flags |= RECYCLE; + break; + case 'H': /* print shape only */ + flags |= DETAILSHAPE; + /* FALLTHROUGH */ + case 'h': + flags |= SHAPEONLY; + break; + case 'z': /* squeeze col width */ + flags |= SQUEEZE; + break; + /*case 'p': + ipagespace = atoi(optarg); (default is 1) + break;*/ + default: + usage(); + } + + av += optind; + ac -= optind; + /*if (!osep) osep = isep;*/ switch (ac) { @@ -458,56 +449,14 @@ getargs(int ac, char *av[]) } } -static char * -getlist(short **list, char *p) +static long +getnum(const char *p) { - int count = 1; - char *t; - - for (t = p + 1; *t; t++) { - if (!isdigit((unsigned char)*t)) - errx(1, - "option %.1s requires a list of unsigned numbers separated by commas", t); - count++; - while (*t && isdigit((unsigned char)*t)) - t++; - if (*t != ',') - break; - } - if (!(*list = (short *) malloc(count * sizeof(short)))) - errx(1, "no list space"); - count = 0; - for (t = p + 1; *t; t++) { - (*list)[count++] = atoi(t); - printf("++ %d ", (*list)[count-1]); - fflush(stdout); - while (*t && isdigit((unsigned char)*t)) - t++; - if (*t != ',') - break; - } - (*list)[count] = 0; - return(t - 1); -} - -/* - * num = number p points to; if (strict) complain - * returns pointer to end of num - */ -static char * -getnum(int *num, char *p, int strict) -{ - char *t = p; + char *ep; + long val; - if (!isdigit((unsigned char)*++t)) { - if (strict || *t == '-' || *t == '+') - errx(1, "option %.1s requires an unsigned integer", p); - *num = 0; - return(p); - } - *num = atoi(t); - while (*++t) - if (!isdigit((unsigned char)*t)) - break; - return(--t); + val = strtol(p, &ep, 10); + if (*ep != '\0') + errx(1, "invalid integer %s", p); + return (val); } diff --git a/usr.bin/rs/tests/rs_test.sh b/usr.bin/rs/tests/rs_test.sh index 1960f9bb0019..1047a6557ae4 100644 --- a/usr.bin/rs/tests/rs_test.sh +++ b/usr.bin/rs/tests/rs_test.sh @@ -100,7 +100,7 @@ k_flag_head() k_flag_body() { - atf_check -s exit:0 -o empty rs -k < /dev/null + atf_check -s exit:0 -o empty rs -k 1 < /dev/null } atf_test_case K_flag @@ -112,7 +112,7 @@ K_flag_head() K_flag_body() { atf_check -s exit:0 -o inline:" -" rs -K < /dev/null +" rs -K 1 < /dev/null } atf_test_case g_flag @@ -123,7 +123,7 @@ g_flag_head() g_flag_body() { - atf_check -s exit:0 -o empty rs -g < /dev/null + atf_check -s exit:0 -o empty rs -g 1 < /dev/null } atf_test_case G_flag @@ -134,7 +134,7 @@ G_flag_head() G_flag_body() { - atf_check -s exit:0 -o empty rs -G < /dev/null + atf_check -s exit:0 -o empty rs -G 10 < /dev/null } atf_test_case e_flag @@ -237,7 +237,8 @@ invalid_usage_head() invalid_usage_body() { - atf_check -s not-exit:0 -e inline:"rs: width must be a positive integer + atf_check -s not-exit:0 -e inline:"rs: option requires an argument -- w +usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]] " rs -w }