idiff port

This commit is contained in:
ian 1998-09-29 20:45:56 +00:00
parent 6d882c47ca
commit 9430d10206
8 changed files with 386 additions and 0 deletions

15
textproc/idiff/Makefile Normal file
View File

@ -0,0 +1,15 @@
# $OpenBSD: Makefile,v 1.1.1.1 1998/09/29 20:45:56 ian Exp $
#
PKGNAME= idiff-1.0
DISTNAME= idiff-1.0
CATEGORIES= textproc
MASTER_SITES= http://www.darwinsys.com/freeware
MAINTAINER= ian@openbsd.org
do-install:
${INSTALL_PROGRAM} ${WRKSRC}/idiff ${PREFIX}/bin
${INSTALL_MAN} ${WRKSRC}/idiff.0 ${PREFIX}/man/cat1
.include <bsd.port.mk>

1
textproc/idiff/files/md5 Normal file
View File

@ -0,0 +1 @@
MD5 (idiff-1.0.tar.gz) = f999adc8246e1166d269fe73610f0ce4

View File

@ -0,0 +1,14 @@
--- Makefile.orig Wed Sep 16 15:56:29 1998
+++ Makefile Tue Sep 29 16:33:05 1998
@@ -1,7 +1,10 @@
-all: idiff
+all: idiff idiff.0
idiff: idiff.c
$(CC) idiff.c -o idiff
+
+idiff.0: idiff.1
+ nroff -man $? > $@
clean:
rm -f *.o a.out

View File

@ -0,0 +1,79 @@
--- idiff.1.orig Tue Sep 29 16:33:05 1998
+++ idiff.1 Thu Sep 13 18:15:40 1990
@@ -0,0 +1,76 @@
+.TH IDIFF Local
+.SH NAME
+idiff \- interactive diff of two files
+.SH SYNOPSIS
+.B idiff
+file1 file2
+.SH DESCRIPTION
+.I Idiff
+runs
+.IR diff (1)
+on the specified files and then
+presents each chunk of
+.I diff
+output and offers the user the option of
+choosing the ``from'' part or the ``to'' part,
+or editing the parts.
+.I Idiff
+produces the selected pieces in the proper order in a file called
+.IR idiff.out .
+.LP
+After each chunk is presented,
+.I idiff
+will prompt the user (with a `? ')
+for a command.
+The valid commands are:
+.TP
+.B <
+Take the ``from'' portion of the displayed chunk.
+This is the portion which
+was extracted from the first file specified.
+.TP
+.B >
+Take the ``to'' portion of the displayed chunk.
+This corresponds to that
+extracted from the second file specified.
+.TP
+.B e
+Invoke an editor on the chunk.
+The contents of shell variable EDITOR select the editor to be used.
+The default is
+.IR /bin/ed .
+Whatever is written out from
+.I ed
+will be placed into the final output.
+.TP
+.B q<
+Take all the rest of the '<' choices automatically.
+Think of this as ``quit from''.
+.TP
+.B q>
+Take all the rest of the '>' choices automatically.
+Think of this as ``quit to''.
+.TP
+.B !
+Pass the command buffer to the shell for processing.
+.LP
+All code that
+.I diff
+considers identical in both input files
+is automatically put into the output file.
+.SH FILES
+.I idiff.out
+\- merged output
+.SH BUGS
+It is not possible to pass any options to
+.I diff
+through
+.I idiff.
+Giving a file and a directory for
+.I diff
+to search for the second file will fail in strange ways.
+.SH HISTORY
+.I Idiff
+appears in the book
+.I ``The UNIX Programming Environment''
+by Brian Kernighan and Rob Pike.

View File

@ -0,0 +1,267 @@
--- idiff.c.orig Wed Sep 16 15:58:16 1998
+++ idiff.c Tue Sep 29 16:33:05 1998
@@ -1,45 +1,94 @@
-/* idiff: interactive diff */
+/*
+ * idiff - interactive diff
+ */
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
#include <ctype.h>
-char *progname;
-#define HUGE 10000 /* large number of lines */
+#include <signal.h>
+#include <assert.h>
-main(argc, argv)
- int argc;
- char *argv[];
-{
- FILE *fin, *fout, *f1, *f2, *efopen();
- char buf[BUFSIZ], *mktemp();
- char *diffout = "idiff.XXXXXX";
+#define HUGE 1000000L
+
+char *progname; /* for error messages */
+const char *diffout = "/tmp/idiff.XXXXXX";
+const char *tempfile = "/tmp/idiff.XXXXXX";
+
+FILE *efopen(const char *fname, const char *fmode);
+void onintr(const int signum);
+void idiff(FILE *f1, FILE *f2, FILE *fin, FILE *fout);
+void parse(char *s, int* pfrom1, int* pto1, int* pcmd, int* pfrom2, int* pto2);
+void nskip(FILE *fin, int n);
+void ncopy(FILE *fin, int n, FILE *fout);
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fin, *fout, *f1, *f2;
+ char cmdBuf[1024], *inname1, *inname2;
+ int c, errflg = 0;
+ extern int optind;
+ extern char *optarg;
+ int use_b = 0; /* true --> use diff -b */
progname = argv[0];
- if (argc != 3) {
- fprintf(stderr, "Usage: idiff file1 file2\n");
+
+ while ((c = getopt(argc, argv, "b")) != EOF)
+ switch (c) {
+ case 'b':
+ use_b = 1;
+ break;
+ case '?':
+ default:
+ errflg++;
+ break;
+ }
+ if (errflg) {
+ (void) fprintf(stderr, "usage: %s xxx [file] ...\n", progname);
+ exit(2);
+ }
+ if (argc-optind != 2) {
+ fprintf(stderr, "usage: idiff file1 file2\n");
exit(1);
}
- f1 = efopen(argv[1], "r");
- f2 = efopen(argv[2], "r");
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void) signal(SIGINT, onintr);
+ inname1 = argv[optind+0];
+ inname2 = argv[optind+1];
+ f1 = efopen(inname1, "r");
+ f2 = efopen(inname2, "r");
fout = efopen("idiff.out", "w");
- mktemp(diffout);
- sprintf(buf,"diff %s %s >%s",argv[1],argv[2],diffout);
- system(buf);
+ (void) mkstemp(strdup(diffout));
+ (void) sprintf(cmdBuf, "diff %s %s %s >%s",
+ use_b ? "-b" : "",
+ inname1, inname2, diffout);
+ (void) system(cmdBuf);
fin = efopen(diffout, "r");
idiff(f1, f2, fin, fout);
- unlink(diffout);
+ (void) unlink(diffout);
printf("%s output in file idiff.out\n", progname);
exit(0);
}
-idiff(f1, f2, fin, fout) /* process diffs */
- FILE *f1, *f2, *fin, *fout;
+/* process diffs */
+void
+idiff(FILE *f1, FILE *f2, FILE *fin, FILE *fout)
{
- char *tempfile = "idiff.XXXXXX";
- char buf[BUFSIZ], buf2[BUFSIZ], *mktemp();
- FILE *ft, *efopen();
+ char buf[BUFSIZ], buf2[BUFSIZ], *ed, *getenv();
+ FILE *ft;
int cmd, n, from1, to1, from2, to2, nf1, nf2;
- mktemp(tempfile);
+ assert(f1 != NULL);
+ assert(f2 != NULL);
+ assert(fin != NULL);
+ assert(fout != NULL);
+
+ (void) mkstemp(strdup(tempfile));
+ if ((ed=getenv("EDITOR")) == NULL)
+ ed = "/bin/ed";
+
nf1 = nf2 = 0;
while (fgets(buf, sizeof buf, fin) != NULL) {
parse(buf, &from1, &to1, &cmd, &from2, &to2);
@@ -52,13 +101,13 @@
from2++;
printf("%s", buf);
while (n-- > 0) {
- fgets(buf, sizeof buf, fin);
+ (void) fgets(buf, sizeof buf, fin);
printf("%s", buf);
}
do {
printf("? ");
- fflush(stdout);
- fgets(buf, sizeof buf, stdin);
+ (void) fflush(stdout);
+ (void) fgets(buf, sizeof buf, stdin);
switch (buf[0]) {
case '>':
nskip(f1, to1-nf1);
@@ -75,34 +124,57 @@
ncopy(f1, to1+1-from1, ft);
fprintf(ft, "---\n");
ncopy(f2, to2+1-from2, ft);
- fclose(ft);
- sprintf(buf2, "ed %s", tempfile);
- system(buf2);
+ (void) fclose(ft);
+ (void) sprintf(buf2, "%s %s", ed, tempfile);
+ (void) system(buf2);
ft = efopen(tempfile, "r");
ncopy(ft, HUGE, fout);
- fclose(ft);
+ (void) fclose(ft);
break;
case '!':
- system(buf+1);
+ (void) system(buf+1);
printf("!\n");
break;
+ case 'q':
+ switch (buf[1]) {
+ case '>' :
+ nskip(f1, HUGE);
+ ncopy(f2, HUGE, fout);
+ /* this can fail on immense files */
+ goto out;
+ break;
+ case '<' :
+ nskip(f2, HUGE);
+ ncopy(f1, HUGE, fout);
+ /* this can fail on immense files */
+ goto out;
+ break;
+ default:
+ fprintf(stderr,
+ "%s: q must be followed by a < or a >!\n", progname);
+ break;
+ }
+ break;
default:
- printf("< or > or e or !\n");
+ fprintf(stderr,
+ "%s: >, q>, <, q<, ! or e only!\n",
+ progname);
break;
}
- } while (buf[0]!='<' && buf[0]!='>' && buf[0]!='e');
+ } while (buf[0] != '<' && buf[0] != '>'
+ && buf[0] != 'q' && buf[0] != 'e');
nf1 = to1;
nf2 = to2;
}
- ncopy(f1, HUGE, fout); /* can fail on very long files */
- unlink(tempfile);
+out:
+ ncopy(f1, HUGE, fout); /* can fail on very large files */
+ (void) unlink(tempfile);
}
-parse(s, pfrom1, pto1, pcmd, pfrom2, pto2)
- char *s;
- int *pcmd, *pfrom1, *pto1, *pfrom2, *pto2;
+void
+parse(char *s, int* pfrom1, int* pto1, int* pcmd, int* pfrom2, int* pto2)
{
-#define a2i(p) while (isdigit(*s)) p = 10*(p) + *s++ - '0'
+#define a2i(p) while (isdigit(*s)) p = 10 * (p) + *s++ - '0'
*pfrom1 = *pto1 = *pfrom2 = *pto2 = 0;
a2i(*pfrom1);
@@ -120,20 +192,25 @@
*pto2 = *pfrom2;
}
-nskip(fin, n) /* skip n lines of file fin */
- FILE *fin;
+void
+nskip(FILE *fin, int n) /* skip n lines of file fin */
{
char buf[BUFSIZ];
while (n-- > 0)
- fgets(buf, sizeof buf, fin);
+ /* check for EOF in case called with HUGE */
+ if (fgets(buf, sizeof buf, fin) == NULL)
+ return;
}
-ncopy(fin, n, fout) /* copy n lines from fin to fout */
- FILE *fin, *fout;
+void
+ncopy(FILE *fin, int n, FILE *fout) /* copy n lines from fin to fout */
{
char buf[BUFSIZ];
+ assert(fin != NULL);
+ assert(fout != NULL);
+
while (n-- > 0) {
if (fgets(buf, sizeof buf, fin) == NULL)
return;
@@ -141,4 +218,25 @@
}
}
-#include "efopen.c"
+/* Interrupt handler */
+void
+onintr(const int signum)
+{
+#ifndef DEBUG
+ (void) unlink(tempfile);
+ (void) unlink(diffout);
+#endif /* DEBUG */
+ exit(1);
+}
+
+FILE *
+efopen(const char *file, const char *mode) /* fopen file, die if can't */
+{
+ FILE *fp;
+
+ if ((fp = fopen(file, mode)) != NULL)
+ return fp;
+ fprintf(stderr, "%s: can't open file %s mode %s\n",
+ progname, file, mode);
+ exit(1);
+}

View File

@ -0,0 +1 @@
A powerful command-line front end to diff: manually merge two versions into one.

7
textproc/idiff/pkg/DESCR Normal file
View File

@ -0,0 +1,7 @@
This is idiff, a front-end to diff that lets you manually merge
two versions of a file. It runs diff for you, and presents the
results one "chunk" at a time.
Idiff was written by Kernighan and Pike, and first appeared in their
1984 book The UNIX Programming Environment (Prentice-Hall).
Source code is used by permission.

2
textproc/idiff/pkg/PLIST Normal file
View File

@ -0,0 +1,2 @@
bin/idiff
man/cat1/idiff.0