[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

diff -I support + fix



This patch is the same as the last with the addition of a fix from Otto
(thanks) in readline()'s parsing.  Apologies for all the noise.

Comments?

Index: diff.1
===================================================================
RCS file: /cvs/src/usr.bin/diff/diff.1,v
retrieving revision 1.25
diff -u -r1.25 diff.1
--- diff.1	2004/03/16 00:40:34	1.25
+++ diff.1	2004/06/16 23:34:06
@@ -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
@@ -97,7 +102,7 @@
 The lines removed from
 .Ar file1
 are marked with
-.Sq \-\ \& ;
+.Sq \&-\ \& ;
 those added to
 .Ar file2
 are marked
@@ -179,7 +184,8 @@
 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 +193,18 @@
 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 +303,9 @@
 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 +391,11 @@
 .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 +437,7 @@
 .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 +461,8 @@
 .Xr diff3 1 ,
 .Xr ed 1 ,
 .Xr pr 1 ,
-.Xr fnmatch 3
+.Xr fnmatch 3 ,
+.Xr re_format 7
 .Sh STANDARDS
 The
 .Nm
Index: diff.c
===================================================================
RCS file: /cvs/src/usr.bin/diff/diff.c,v
retrieving revision 1.45
diff -u -r1.45 diff.c
--- diff.c	2004/03/16 00:40:34	1.45
+++ diff.c	2004/06/16 23:34:07
@@ -43,11 +43,12 @@
 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 @@
 	{ "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 @@
 
 __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 @@
 		case 'h':
 			/* silently ignore for backwards compatibility */
 			break;
+		case 'I':
+			push_ignore_pats(optarg);
+			break;
 		case 'i':
 			iflag = 1;
 			break;
@@ -216,6 +222,16 @@
 	 */
 	if (argc != 2)
 		usage();
+	if (ignore_pats) {
+		char buf[BUFSIZ];
+		int error;
+
+		if ((error = regcomp(&ignore_re, ignore_pats,
+				     REG_EXTENDED)) != 0) {
+			regerror(error, &ignore_re, buf, sizeof(buf));
+			errx(2, "%s: %s", ignore_pats, buf);
+		}
+	}
 	if (strcmp(argv[0], "-") == 0) {
 		fstat(STDIN_FILENO, &stb1);
 		gotstdin = 1;
@@ -340,6 +356,25 @@
 	entry->pattern = pattern;
 	entry->next = excludes_list;
 	excludes_list = entry;
+}
+
+void
+push_ignore_pats(char *pattern)
+{
+	size_t len;
+
+	if (ignore_pats) {
+		/* 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);
+	} else {
+		/* XXX: estrdup */
+		len = strlen(pattern) + 1;
+		ignore_pats = emalloc(len);
+		strlcpy(ignore_pats, pattern, len);
+	}
 }
 
 void
Index: diff.h
===================================================================
RCS file: /cvs/src/usr.bin/diff/diff.h,v
retrieving revision 1.27
diff -u -r1.27 diff.h
--- diff.h	2004/03/16 00:40:34	1.27
+++ diff.h	2004/06/16 23:34:07
@@ -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 @@
 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);
Index: diffreg.c
===================================================================
RCS file: /cvs/src/usr.bin/diff/diffreg.c,v
retrieving revision 1.55
diff -u -r1.55 diffreg.c
--- diffreg.c	2004/01/07 17:18:32	1.55
+++ diffreg.c	2004/06/16 23:34:08
@@ -214,6 +214,8 @@
 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 void readline(FILE *, char **, long *, long);
+static int  ignoreline(char **);
 static int  asciifile(FILE *);
 static int  fetch(long *, int, int, FILE *, int, int);
 static int  newcand(int, int, int);
@@ -965,6 +967,30 @@
 		printf("%d,0", b);
 }
 
+static void
+readline(FILE *fp, char **line, long *f, long lineno)
+{
+	long len;
+
+	len = f[lineno] - f[lineno - 1];
+	*line = emalloc(len + 1);
+	len = fread(*line, sizeof(char), len, fp);
+	if (ferror(fp))
+		err(1, "readline");
+	(*line)[len] = '\0';
+}
+
+static int
+ignoreline(char **line)
+{
+	int ret;
+
+	ret = regexec(&ignore_re, *line, 0, NULL, 0);
+	free(*line);
+	/* If it matched, it should be ignored. */
+	return ret == 0;
+}
+
 /*
  * 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 +1007,34 @@
 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. */
+			i = a;
+			fseek(f1, ixold[i - 1], SEEK_SET);
+			for (; i <= b; i++) {
+				readline(f1, &line, ixold, i);
+				if (!ignoreline(&line))
+					goto proceed;
+			}
+		}
+		if (a > b || c <= d) {	/* Changes and inserts. */
+			i = c;
+			fseek(f2, ixnew[i - 1], SEEK_SET);
+			for (; i <= d; i++) {
+				readline(f2, &line, ixnew, i);
+				if (!ignoreline(&line))
+					goto proceed;
+			}
+		}
+		return;
+	}
+proceed:
 	if (format == D_CONTEXT || format == D_UNIFIED) {
 		/*
 		 * Allocate change records as needed.