The branch main has been updated by pstef:

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

commit e51aabf8cbb9b412c725c4c9c727ca6faa0630c6
Author:     Piotr Pawel Stefaniak <ps...@freebsd.org>
AuthorDate: 2021-09-05 14:54:07 +0000
Commit:     Piotr Pawel Stefaniak <ps...@freebsd.org>
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);
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to