From owner-dev-commits-src-all@freebsd.org Wed Sep 15 23:59:57 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 5C153670BAA; Wed, 15 Sep 2021 23:59:57 +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 4H8xzK0sqfz3n2P; Wed, 15 Sep 2021 23:59:57 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 AFCB8173C1; Wed, 15 Sep 2021 23:59:56 +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 18FNxu08011245; Wed, 15 Sep 2021 23:59:56 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 18FNxuAB011244; Wed, 15 Sep 2021 23:59:56 GMT (envelope-from git) Date: Wed, 15 Sep 2021 23:59:56 GMT Message-Id: <202109152359.18FNxuAB011244@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Piotr Pawel Stefaniak Subject: git: e51aabf8cbb9 - main - diff: implement option -F (--show-function-line) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pstef X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e51aabf8cbb9b412c725c4c9c727ca6faa0630c6 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Sep 2021 23:59:57 -0000 The branch main has been updated by pstef: URL: https://cgit.FreeBSD.org/src/commit/?id=e51aabf8cbb9b412c725c4c9c727ca6faa0630c6 commit e51aabf8cbb9b412c725c4c9c727ca6faa0630c6 Author: Piotr Pawel Stefaniak AuthorDate: 2021-09-05 14:54:07 +0000 Commit: Piotr Pawel Stefaniak CommitDate: 2021-09-15 23:46:44 +0000 diff: implement option -F (--show-function-line) With unified and context diffs, show the last line that matches the provided pattern before the context. Reviewed by: bapt Differential Revision: https://reviews.freebsd.org/D31714 --- usr.bin/diff/diff.1 | 8 +++++++ usr.bin/diff/diff.c | 59 +++++++++++++++++++++++++++++++++----------------- usr.bin/diff/diff.h | 6 +++-- usr.bin/diff/diffreg.c | 14 +++++++++--- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1 index 6056ddd3ac76..dea01bf918f4 100644 --- a/usr.bin/diff/diff.1 +++ b/usr.bin/diff/diff.1 @@ -65,11 +65,13 @@ .Op Fl -text .Op Fl -unified .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern +.Op Fl F Ar pattern | Fl -show-function-line Ar pattern .Op Fl L Ar label | Fl -label Ar label .Ar file1 file2 .Nm diff .Op Fl aBbdilpTtw .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern +.Op Fl F Ar pattern | Fl -show-function-line Ar pattern .Op Fl L Ar label | Fl -label Ar label .Op Fl -brief .Op Fl -color Ns = Ns Ar when @@ -123,6 +125,7 @@ .Nm diff .Op Fl aBbdilpTtw .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern +.Op Fl F Ar pattern | Fl -show-function-line Ar pattern .Op Fl L Ar label | Fl -label Ar label .Op Fl -brief .Op Fl -color Ns = Ns Ar when @@ -180,6 +183,7 @@ .Op Fl -unidirectional-new-file .Op Fl -unified .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern +.Op Fl F Ar pattern | Fl -show-function-line Ar pattern .Bk -words .Op Fl L Ar label | Fl -label Ar label .Op Fl S Ar name | Fl -starting-file Ar name @@ -357,6 +361,10 @@ environment variable is set to a non-empty string. Try very hard to produce a diff as small as possible. This may consume a lot of processing power and memory when processing large files with many changes. +.It Fl F Ar pattern, Fl -show-function-line Ar pattern +Like +.Fl p, +but display the last line that matches provided pattern. .It Fl I Ar pattern Fl -ignore-matching-lines Ar pattern Ignores changes, insertions, and deletions whose lines match the extended regular expression diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c index 4fc3094035d9..8074261742ae 100644 --- a/usr.bin/diff/diff.c +++ b/usr.bin/diff/diff.c @@ -43,14 +43,15 @@ bool ignore_file_case, suppress_common, color; int diff_format, diff_context, status; int tabsize = 8, width = 130; static int colorflag = COLORFLAG_NEVER; -char *start, *ifdefname, *diffargs, *label[2], *ignore_pats; +char *start, *ifdefname, *diffargs, *label[2]; +char *ignore_pats, *most_recent_pat; char *group_format = NULL; const char *add_code, *del_code; struct stat stb1, stb2; struct excludes *excludes_list; -regex_t ignore_re; +regex_t ignore_re, most_recent_re; -#define OPTIONS "0123456789aBbC:cdD:efHhI:iL:lnNPpqrS:sTtU:uwW:X:x:y" +#define OPTIONS "0123456789aBbC:cdD:efF:HhI:iL:lnNPpqrS:sTtU:uwW:X:x:y" enum { OPT_TSIZE = CHAR_MAX + 1, OPT_STRIPCR, @@ -71,6 +72,7 @@ static struct option longopts[] = { { "minimal", no_argument, 0, 'd' }, { "ed", no_argument, 0, 'e' }, { "forward-ed", no_argument, 0, 'f' }, + { "show-function-line", required_argument, 0, 'F' }, { "speed-large-files", no_argument, NULL, 'H' }, { "ignore-blank-lines", no_argument, 0, 'B' }, { "ignore-matching-lines", required_argument, 0, 'I' }, @@ -105,6 +107,7 @@ static struct option longopts[] = { { NULL, 0, 0, '\0'} }; +static void checked_regcomp(char const *, regex_t *); static void usage(void) __dead2; static void conflicting_format(void) __dead2; static void push_excludes(char *); @@ -190,6 +193,12 @@ main(int argc, char **argv) case 'B': dflags |= D_SKIPBLANKLINES; break; + case 'F': + if (dflags & D_PROTOTYPE) + conflicting_format(); + dflags |= D_MATCHLAST; + most_recent_pat = xstrdup(optarg); + break; case 'I': push_ignore_pats(optarg); break; @@ -216,6 +225,8 @@ main(int argc, char **argv) diff_format = D_NREVERSE; break; case 'p': + if (dflags & D_MATCHLAST) + conflicting_format(); dflags |= D_PROTOTYPE; break; case 'P': @@ -359,19 +370,8 @@ main(int argc, char **argv) */ if (argc != 2) usage(); - if (ignore_pats != NULL) { - char buf[BUFSIZ]; - int error; - - if ((error = regcomp(&ignore_re, ignore_pats, - REG_NEWLINE | REG_EXTENDED)) != 0) { - regerror(error, &ignore_re, buf, sizeof(buf)); - if (*ignore_pats != '\0') - errx(2, "%s: %s", ignore_pats, buf); - else - errx(2, "%s", buf); - } - } + checked_regcomp(ignore_pats, &ignore_re); + checked_regcomp(most_recent_pat, &most_recent_re); if (strcmp(argv[0], "-") == 0) { fstat(STDIN_FILENO, &stb1); gotstdin = 1; @@ -426,6 +426,25 @@ main(int argc, char **argv) exit(status); } +static void +checked_regcomp(char const *pattern, regex_t *comp) +{ + char buf[BUFSIZ]; + int error; + + if (pattern == NULL) + return; + + error = regcomp(comp, pattern, REG_NEWLINE | REG_EXTENDED); + if (error != 0) { + regerror(error, comp, buf, sizeof(buf)); + if (*pattern != '\0') + errx(2, "%s: %s", pattern, buf); + else + errx(2, "%s", buf); + } +} + static void set_argstr(char **av, char **ave) { @@ -548,18 +567,18 @@ usage(void) (void)fprintf(stderr, "usage: diff [-aBbdilpTtw] [-c | -e | -f | -n | -q | -u] [--ignore-case]\n" " [--no-ignore-case] [--normal] [--strip-trailing-cr] [--tabsize]\n" - " [-I pattern] [-L label] file1 file2\n" + " [-I pattern] [-F pattern] [-L label] file1 file2\n" " diff [-aBbdilpTtw] [-I pattern] [-L label] [--ignore-case]\n" " [--no-ignore-case] [--normal] [--strip-trailing-cr] [--tabsize]\n" - " -C number file1 file2\n" + " [-F pattern] -C number file1 file2\n" " diff [-aBbdiltw] [-I pattern] [--ignore-case] [--no-ignore-case]\n" " [--normal] [--strip-trailing-cr] [--tabsize] -D string file1 file2\n" " diff [-aBbdilpTtw] [-I pattern] [-L label] [--ignore-case]\n" " [--no-ignore-case] [--normal] [--tabsize] [--strip-trailing-cr]\n" - " -U number file1 file2\n" + " [-F pattern] -U number file1 file2\n" " diff [-aBbdilNPprsTtw] [-c | -e | -f | -n | -q | -u] [--ignore-case]\n" " [--no-ignore-case] [--normal] [--tabsize] [-I pattern] [-L label]\n" - " [-S name] [-X file] [-x pattern] dir1 dir2\n" + " [-F pattern] [-S name] [-X file] [-x pattern] dir1 dir2\n" " diff [-aBbditwW] [--expand-tabs] [--ignore-all-blanks]\n" " [--ignore-blank-lines] [--ignore-case] [--minimal]\n" " [--no-ignore-file-name-case] [--strip-trailing-cr]\n" diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h index 5164fe22ace4..4a7d19ee8982 100644 --- a/usr.bin/diff/diff.h +++ b/usr.bin/diff/diff.h @@ -74,6 +74,7 @@ #define D_IGNOREBLANKS 0x200 /* Ignore white space changes */ #define D_STRIPCR 0x400 /* Strip trailing cr */ #define D_SKIPBLANKLINES 0x800 /* Skip blank lines */ +#define D_MATCHLAST 0x1000 /* Display last line matching provided regex */ /* * Status values for print_status() and diffreg() return values @@ -103,12 +104,13 @@ extern bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag; extern bool ignore_file_case, suppress_common, color; extern int diff_format, diff_context, status; extern int tabsize, width; -extern char *start, *ifdefname, *diffargs, *label[2], *ignore_pats; +extern char *start, *ifdefname, *diffargs, *label[2]; +extern char *ignore_pats, *most_recent_pat; extern char *group_format; extern const char *add_code, *del_code; extern struct stat stb1, stb2; extern struct excludes *excludes_list; -extern regex_t ignore_re; +extern regex_t ignore_re, most_recent_re; int diffreg(char *, char *, int, int); void diffdir(char *, char *, int); diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c index 47c1934a6a65..fc3c3406a073 100644 --- a/usr.bin/diff/diffreg.c +++ b/usr.bin/diff/diffreg.c @@ -1407,7 +1407,15 @@ match_function(const long *f, int pos, FILE *fp) continue; buf[nc] = '\0'; buf[strcspn(buf, "\n")] = '\0'; - if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$') { + if (most_recent_pat != NULL) { + int ret = regexec(&most_recent_re, buf, 0, NULL, 0); + + if (ret != 0) + continue; + strlcpy(lastbuf, buf, sizeof(lastbuf)); + lastmatchline = pos; + return (lastbuf); + } else if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$') { if (begins_with(buf, "private:")) { if (!state) state = " (private)"; @@ -1448,7 +1456,7 @@ dump_context_vec(FILE *f1, FILE *f2, int flags) upd = MIN(len[1], context_vec_ptr->d + diff_context); printf("***************"); - if ((flags & D_PROTOTYPE)) { + if (flags & (D_PROTOTYPE | D_MATCHLAST)) { f = match_function(ixold, lowa - 1, f1); if (f != NULL) printf(" %s", f); @@ -1555,7 +1563,7 @@ dump_unified_vec(FILE *f1, FILE *f2, int flags) printf(" +"); uni_range(lowc, upd); printf(" @@"); - if ((flags & D_PROTOTYPE)) { + if (flags & (D_PROTOTYPE | D_MATCHLAST)) { f = match_function(ixold, lowa - 1, f1); if (f != NULL) printf(" %s", f);