summaryrefslogtreecommitdiff
path: root/usr.bin/diff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2004-06-20 18:47:46 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2004-06-20 18:47:46 +0000
commit8908ae08ec12426bf0c946b2bb67e4b6a8825518 (patch)
tree8bc32c7daf63de0bcb851ad6fd382c2b3aea622f /usr.bin/diff
parent27aab8e947ae47e5ef251b626c74f07b90c6d431 (diff)
Implement -I option: ignore changes matching a set of regexes. From
Jared Yanovich, with twists from millert@ and me. Testing by brad@, sturm@ and pval@. ok millert@
Diffstat (limited to 'usr.bin/diff')
-rw-r--r--usr.bin/diff/diff.149
-rw-r--r--usr.bin/diff/diff.c60
-rw-r--r--usr.bin/diff/diff.h8
-rw-r--r--usr.bin/diff/diffreg.c55
4 files changed, 144 insertions, 28 deletions
diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1
index 633c2f435c0..48668dfd229 100644
--- a/usr.bin/diff/diff.1
+++ b/usr.bin/diff/diff.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: diff.1,v 1.25 2004/03/16 00:40:34 millert Exp $
+.\" $OpenBSD: diff.1,v 1.26 2004/06/20 18:47:45 otto Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -38,31 +38,36 @@
.Sh SYNOPSIS
.Nm diff
.Op Fl abdilpqtTw
+.Op Fl I Ar pattern
.Oo
-.Fl c | Fl e | Fl f |
-.Fl n | Fl u
+.Fl c | e | f |
+.Fl n | u
.Oc
.Op Fl L Ar label
.Ar file1 file2
.Nm diff
.Op Fl abdilpqtTw
+.Op Fl I Ar pattern
.Op Fl L Ar label
.Fl C Ar number
.Ar file1 file2
.Nm diff
.Op Fl abdilqtw
+.Op Fl I Ar pattern
.Fl D Ar string
.Ar file1 file2
.Nm diff
.Op Fl abdilpqtTw
+.Op Fl I Ar pattern
.Op Fl L Ar label
.Fl U Ar number
.Ar file1 file2
.Nm diff
.Op Fl abdilNPpqtTw
+.Op Fl I Ar pattern
.Oo
-.Fl c | Fl e | Fl f |
-.Fl n | Fl u
+.Fl c | e | f |
+.Fl n | u
.Oc
.Bk -words
.Op Fl L Ar label
@@ -93,11 +98,12 @@ With
the output format is modified slightly:
the output begins with identification of the files involved and
their creation dates and then each change is separated
-by a line with fifteen *'s.
+by a line with fifteen
+.Li * Ns 's .
The lines removed from
.Ar file1
are marked with
-.Sq \-\ \& ;
+.Sq \&-\ \& ;
those added to
.Ar file2
are marked
@@ -179,7 +185,8 @@ lines of context.
Comparison options:
.Bl -tag -width Ds
.It Fl a
-Treat all files as ASCII.
+Treat all files as
+.Tn ASCII .
.It Fl b
Causes trailing blanks (spaces and tabs) to be ignored, and other
strings of blanks to compare equal.
@@ -187,6 +194,18 @@ strings of blanks to compare equal.
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 I Ar pattern
+Ignores changes, insertions, and deletions whose lines match the
+extended regular expression
+.Ar pattern .
+Multiple
+.Fl I
+patterns may be specified.
+All lines in the change must match some pattern for the change to be
+ignored.
+See
+.Xr re_format 7
+for more information on regular expression patterns.
.It Fl i
Ignores the case of letters.
E.g.,
@@ -285,8 +304,9 @@ Binary files which differ,
common subdirectories, and files which appear in only one directory
are described as such.
In directory mode only regular files and directories are compared.
-If a non-regular file such as a device special file or FIFO is
-encountered, a diagnostic message is printed.
+If a non-regular file such as a device special file or
+.Tn FIFO
+is encountered, a diagnostic message is printed.
.Pp
If only one of
.Ar file1
@@ -372,11 +392,11 @@ Replace the range of specified lines with the line
.Va ZZ .
.It Li XX,YY Ns Ic c Ns Li ZZ,QQ
Replace the range
-.Va XX , Ns YY
+.Va XX , Ns Va YY
from
.Ar file1
with the range
-.Va ZZ , Ns QQ
+.Va ZZ , Ns Va QQ
from
.Ar file2 .
.El
@@ -418,7 +438,7 @@ as the temporary directory.
.El
.Sh FILES
.Bl -tag -width /tmp/diff.XXXXXXXX -compact
-.It Pa /tmp/diff.XXXXXXXX
+.It Pa /tmp/diff. Ns Ar XXXXXXXX
Temporary file used when comparing a device or the standard input.
Note that the temporary file is unlinked as soon as it is created
so it will not show up in a directory listing.
@@ -442,7 +462,8 @@ An error occurred.
.Xr diff3 1 ,
.Xr ed 1 ,
.Xr pr 1 ,
-.Xr fnmatch 3
+.Xr fnmatch 3 ,
+.Xr re_format 7
.Sh STANDARDS
The
.Nm
diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c
index 134cb37c0f3..b32ee897861 100644
--- a/usr.bin/diff/diff.c
+++ b/usr.bin/diff/diff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert Exp $ */
+/* $OpenBSD: diff.c,v 1.46 2004/06/20 18:47:45 otto Exp $ */
/*
* Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -21,7 +21,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert Exp $";
+static const char rcsid[] = "$OpenBSD: diff.c,v 1.46 2004/06/20 18:47:45 otto Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -43,11 +43,12 @@ static const char rcsid[] = "$OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert
int aflag, bflag, dflag, iflag, lflag, Nflag, Pflag, pflag, rflag;
int sflag, tflag, Tflag, wflag;
int format, context, status;
-char *start, *ifdefname, *diffargs, *label;
+char *start, *ifdefname, *diffargs, *label, *ignore_pats;
struct stat stb1, stb2;
struct excludes *excludes_list;
+regex_t ignore_re;
-#define OPTIONS "0123456789abC:cdD:efhiL:lnNPpqrS:sTtU:uwX:x:"
+#define OPTIONS "0123456789abC:cdD:efhI:iL:lnNPpqrS:sTtU:uwX:x:"
static struct option longopts[] = {
{ "text", no_argument, 0, 'a' },
{ "ignore-space-change", no_argument, 0, 'b' },
@@ -56,6 +57,7 @@ static struct option longopts[] = {
{ "minimal", no_argument, 0, 'd' },
{ "ed", no_argument, 0, 'e' },
{ "forward-ed", no_argument, 0, 'f' },
+ { "ignore-matching-lines", required_argument, 0, 'I' },
{ "ignore-case", no_argument, 0, 'i' },
{ "paginate", no_argument, 0, 'l' },
{ "label", required_argument, 0, 'L' },
@@ -78,6 +80,7 @@ static struct option longopts[] = {
__dead void usage(void);
void push_excludes(char *);
+void push_ignore_pats(char *);
void read_excludes_file(char *file);
void set_argstr(char **, char **);
@@ -139,6 +142,9 @@ main(int argc, char **argv)
case 'h':
/* silently ignore for backwards compatibility */
break;
+ case 'I':
+ push_ignore_pats(optarg);
+ break;
case 'i':
iflag = 1;
break;
@@ -216,6 +222,19 @@ 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);
+ }
+ }
if (strcmp(argv[0], "-") == 0) {
fstat(STDIN_FILENO, &stb1);
gotstdin = 1;
@@ -343,6 +362,25 @@ push_excludes(char *pattern)
}
void
+push_ignore_pats(char *pattern)
+{
+ size_t len;
+
+ if (ignore_pats == NULL) {
+ /* XXX: estrdup */
+ len = strlen(pattern) + 1;
+ ignore_pats = emalloc(len);
+ strlcpy(ignore_pats, pattern, len);
+ } else {
+ /* old + "|" + new + NUL */
+ len = strlen(ignore_pats) + strlen(pattern) + 2;
+ ignore_pats = erealloc(ignore_pats, len);
+ strlcat(ignore_pats, "|", len);
+ strlcat(ignore_pats, pattern, len);
+ }
+}
+
+void
print_only(const char *path, size_t dirlen, const char *entry)
{
if (dirlen > 1)
@@ -400,12 +438,14 @@ __dead void
usage(void)
{
(void)fprintf(stderr,
- "usage: diff [-abdilpqtTw] [-c | -e | -f | -n | -u] [-L label] file1 file2\n"
- " diff [-abdilpqtTw] [-L label] -C number file1 file2\n"
- " diff [-abdilqtw] -D string file1 file2\n"
- " diff [-abdilpqtTw] [-L label] -U number file1 file2\n"
- " diff [-abdilNPpqtTw] [-c | -e | -f | -n | -u ] [-L label] [-r] [-s]\n"
- " [-S name] [-X file] [-x pattern] dir1 dir2\n");
+ "usage: diff [-abdilpqtTw] [-I pattern] [-c | -e | -f | -n | -u]\n"
+ " [-L label] file1 file2\n"
+ " diff [-abdilpqtTw] [-I pattern] [-L label] -C number file1 file2\n"
+ " diff [-abdilqtw] [-I pattern] -D string file1 file2\n"
+ " diff [-abdilpqtTw] [-I pattern] [-L label] -U number file1 file2\n"
+ " diff [-abdilNPpqtTw] [-I pattern] [-c | -e | -f | -n | -u]\n"
+ " [-L label] [-r] [-s] [-S name] [-X file] [-x pattern] dir1\n"
+ " dir2\n");
exit(2);
}
diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h
index d9af1a94c0e..8d5e70813dd 100644
--- a/usr.bin/diff/diff.h
+++ b/usr.bin/diff/diff.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff.h,v 1.27 2004/03/16 00:40:34 millert Exp $ */
+/* $OpenBSD: diff.h,v 1.28 2004/06/20 18:47:45 otto Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -31,6 +31,9 @@
* @(#)diff.h 8.1 (Berkeley) 6/6/93
*/
+#include <sys/types.h>
+#include <regex.h>
+
/*
* Output format options
*/
@@ -73,9 +76,10 @@ struct excludes {
extern int aflag, bflag, dflag, iflag, lflag, Nflag, Pflag, pflag, rflag,
sflag, tflag, Tflag, wflag;
extern int format, context, status;
-extern char *start, *ifdefname, *diffargs, *label;
+extern char *start, *ifdefname, *diffargs, *label, *ignore_pats;
extern struct stat stb1, stb2;
extern struct excludes *excludes_list;
+extern regex_t ignore_re;
char *splice(char *, char *);
int diffreg(char *, char *, int);
diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c
index 6c5b36ce3ae..cccd4305353 100644
--- a/usr.bin/diff/diffreg.c
+++ b/usr.bin/diff/diffreg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diffreg.c,v 1.56 2004/06/18 07:23:50 otto Exp $ */
+/* $OpenBSD: diffreg.c,v 1.57 2004/06/20 18:47:45 otto Exp $ */
/*
* Copyright (C) Caldera International Inc. 2001-2002.
@@ -65,7 +65,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: diffreg.c,v 1.56 2004/06/18 07:23:50 otto Exp $";
+static const char rcsid[] = "$OpenBSD: diffreg.c,v 1.57 2004/06/20 18:47:45 otto Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -214,6 +214,7 @@ static void unravel(int);
static void unsort(struct line *, int, int *);
static void change(char *, FILE *, char *, FILE *, int, int, int, int);
static void sort(struct line *, int);
+static int ignoreline(char *);
static int asciifile(FILE *);
static int fetch(long *, int, int, FILE *, int, int);
static int newcand(int, int, int);
@@ -226,6 +227,7 @@ static int files_differ(FILE *, FILE *, int);
static __inline int min(int, int);
static __inline int max(int, int);
static char *match_function(const long *, int, FILE *);
+static char *preadline(int, size_t, off_t);
/*
@@ -965,6 +967,29 @@ uni_range(int a, int b)
printf("%d,0", b);
}
+static char *
+preadline(int fd, size_t len, off_t off)
+{
+ char *line;
+ ssize_t nr;
+
+ line = emalloc(len + 1);
+ if ((nr = pread(fd, line, len, off)) < 0)
+ err(1, "preadline");
+ line[nr] = '\0';
+ return (line);
+}
+
+static int
+ignoreline(char *line)
+{
+ int ret;
+
+ ret = regexec(&ignore_re, line, 0, NULL, 0);
+ free(line);
+ return (ret == 0); /* if it matched, it should be ignored. */
+}
+
/*
* Indicate that there is a difference between lines a and b of the from file
* to get to lines c to d of the to file. If a is greater then b then there
@@ -981,6 +1006,32 @@ change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d)
restart:
if (format != D_IFDEF && a > b && c > d)
return;
+ if (ignore_pats != NULL) {
+ char *line;
+ /*
+ * All lines in the change, insert, or delete must
+ * match an ignore pattern for the change to be
+ * ignored.
+ */
+ if (a <= b) { /* Changes and deletes. */
+ for (i = a; i <= b; i++) {
+ line = preadline(fileno(f1),
+ ixold[i] - ixold[i - 1], ixold[i - 1]);
+ if (!ignoreline(line))
+ goto proceed;
+ }
+ }
+ if (a > b || c <= d) { /* Changes and inserts. */
+ for (i = c; i <= d; i++) {
+ line = preadline(fileno(f2),
+ ixnew[i] - ixnew[i - 1], ixnew[i - 1]);
+ if (!ignoreline(line))
+ goto proceed;
+ }
+ }
+ return;
+ }
+proceed:
if (format == D_CONTEXT || format == D_UNIFIED) {
/*
* Allocate change records as needed.