home *** CD-ROM | disk | FTP | other *** search
- Date: Wed, 23 Jan 85 14:01:24 est
- From: john (John Nelson)
- Subject: contextual diff on Bell systems
-
- This is a program for all those poor slobs that have to deal with UNIX systems
- that don't have a -c option on their diff. This program eliminates the last
- excuse for bug fixes to be in standard diff format (especially since "patch"
- works so much more reliably on diffc format).
-
- Send bug reports to: John Nelson (decvax!genrad!john).
-
- ------------------- cut here -------------------------
- : Run this shell script with "sh" not "csh"
- PATH=:/bin:/usr/bin:/usr/ucb
- export PATH
- echo 'x - diffc.1'
- sed 's/^X//' <<'//go.sysin dd *' >diffc.1
- X.TH DIFFC l "22 January 1985"
- X.UC 4
- X.SH NAME
- diffc \- context diff for systems whose diff has no \-c option
- X.SH SYNOPSIS
- X.B diff
- [
- X.B \-options
- ] [
- X.B \-r
- ] [
- \fB\-c#
- ] file1 file2
- X.SH DESCRIPTION
- X.I Diffc
- is a front end for
- X.IR diff (1)
- which outputs contextual diff format like Berkeley system's "diff -c".
- X.I Diffc
- will actually run
- X.I diff
- as a subprocess, and will merge the "standard" diff format with lines from
- both files.
- As far as I can tell, the output is exactly the same as that of a diff with
- the -c option.
- X.PP
- The -c# option allows the amount of context to be specified.
- The default is 3 lines above and below the change.
- I find that -c1 works well for updates intended for use with patch(1).
- Any other options specified on the command line are passed along to
- X.IR diff .
- Note that most options to
- X.I diff
- should NOT be specified when using
- X.IR diffc ,
- but the capability is there, nevertheless.
- X.PP
- The output format begins with identification of the files involved and
- their creation dates and then each change is separated
- by a line with a dozen *'s.
- The lines removed from
- X.I file1
- are marked with `\(mi'; those added to
- X.I file2
- are marked `+'. Lines which are changed from one
- file to the other are marked in both files with `!'.
- X.PP
- No claim is made that the algoritm used is either fast or bulletproof.
- It was only intended for standard text files with lines shorter than
- BUFSIZ.
- XFseek is used extensively to move around in the files, precluding the
- use of standard input as one of the files to be diff'ed.
- X.SH "SEE ALSO"
- cmp(1), diff(1), comm(1), patch(1)
- X.SH DIAGNOSTICS
- Exit status is nonzero to indicate problems.
- X.SH BUGS
- This program is a hack, and should really be incorporated as part of "diff"
- by Bell.
- X.SH AUTHOR
- John P. Nelson
- //go.sysin dd *
- echo 'x - diffc.c'
- sed 's/^X//' <<'//go.sysin dd *' >diffc.c
- X/* diffc.c - provide diff -c output on non-berkeley systems
- **
- ** cc -o diffc diffc.c
- **
- ** or for V7 type systems
- **
- ** cc -o diffc -DV7 diffc.c
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef V7
- #define strchr index
- #include <string.h> /* BEZERKELY 4.2 is strings.h */
- #else
- #include <string.h>
- #endif
-
- #define WIDTH 3
- #define SEPERATE "***************"
- #define max(_a,_b) (((_a)>(_b))?(_a):(_b))
-
- XFILE *diff, *fd1, *fd2;
- int line1 = 1, line2 = 1;
- long off1, off2;
- char buffer[BUFSIZ];
- int width = WIDTH;
-
- char *ctime();
- XFILE *popen();
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int i;
- struct stat statbuf;
-
- strcpy(buffer, "diff");
- /* skip over minus args - they must be for diff */
- for (i = 1; i < argc; ++i)
- {
- if (argv[i][0] != '-')
- break;
- else if (!strncmp(argv[i], "-c", 2))
- {
- width = atoi(argv[i]+2);
- if (width < 1 || width > 20)
- width = WIDTH;
- }
- else
- {
- strcat(buffer, " ");
- strcat(buffer, argv[i]);
- }
- }
- if (argc - i != 2)
- {
- fprintf(stderr, "Usage: %s [-minusargs] file1 file2\n", argv[0]);
- exit(1);
- }
- strcat(buffer, " ");
- strcat(buffer, argv[i]);
- strcat(buffer, " ");
- strcat(buffer, argv[i+1]);
-
- fd1 = fopen(argv[i], "r");
- fd2 = fopen(argv[i+1], "r");
-
- if (!fd1 || !fd2)
- {
- fprintf(stderr, "%s: File not accessible\n", argv[0]);
- exit(1);
- }
-
- if ((diff = popen(buffer, "r")) == NULL)
- {
- fprintf(stderr, "%s: Cant find diff\n", argv[0]);
- exit(1);
- }
-
- stat(argv[i], &statbuf);
- printf("*** %s\t%s", argv[i], ctime(&(statbuf.st_mtime)));
- stat(argv[i+1], &statbuf);
- printf("--- %s\t%s", argv[i+1], ctime(&(statbuf.st_mtime)));
-
- dodiffs();
- }
-
- dodiffs()
- {
- char line[BUFSIZ];
- char type, disp;
- int from1, to1, from2, to2;
- int dfrom1, dto1, dfrom2, dto2;
- int i;
- int skip;
-
- while (fgets(line, sizeof(line), diff))
- {
- parse(line, &from1, &from2, &to1, &to2, &type);
-
- dfrom1 = max(from1 - width, 1);
- dfrom2 = max(from2 - width, 1);
-
- line1 = toline(fd1, line1, dfrom1);
- line2 = toline(fd2, line2, dfrom2);
-
- off1 = ftell(fd1);
- off2 = ftell(fd2);
-
- dto1 = checkline(fd1, line1, to1 + width);
- dto2 = checkline(fd2, line2, to2 + width);
-
- /* checkline moved the position, so seek back to last point */
- fseek(fd1, off1, 0);
- fseek(fd2, off2, 0);
-
- printf("*** %d,%d\n", dfrom1, dto1);
- for (i = dfrom1; i <= dto1; ++i)
- {
- if (!fgets(buffer, sizeof(buffer), fd1))
- break;
- disp = ' ';
- if (i >= from1 && i <= to1)
- disp = (type == 'c') ? '!': '-';
- printf("%c %s", disp, buffer);
- }
- printf("\n--- %d,%d -----\n", dfrom2, dto2);
- for (i = dfrom2; i <= dto2; ++i)
- {
- if (!fgets(buffer, sizeof(buffer), fd2))
- break;
- disp = ' ';
- if (i >= from2 && i <= to2)
- disp = (type == 'c') ? '!': '+';
- printf("%c %s", disp, buffer);
- }
-
- /* seek back because next diff may overlap */
- fseek(fd1, off1, 0);
- fseek(fd2, off2, 0);
-
- /* calculate the number of display lines generated by diff */
- skip = to1 - from1 + to2 - from2 + 2;
- if (type == 'c')
- skip++; /* add one for the seperator */
- toline(diff, 0, skip);
- }
- }
-
- parse(line, from1, from2, to1, to2, type)
- char *line, *type;
- int *from1, *from2, *to1, *to2;
- {
- char *part2, *ptr;
-
- /* expect a line range type range */
- if(!isdigit(line[0]))
- {
- fprintf(stderr, "Unknown junk from diff: %s\n", line);
- exit(2);
- }
- if ((part2 = strchr(line, 'a')) || (part2 = strchr(line, 'c')) || (part2 = strchr(line, 'd')))
- {
- *type = *part2;
- *part2++ = '\0';
- printf("%s\n", SEPERATE);
- }
- else
- {
- fprintf(stderr, "Unknown junk from diff: %s\n", line);
- exit(2);
- }
- X/* file 1 */
- *from1 = atoi(line);
- if (ptr = strchr(line, ','))
- *to1 = atoi(++ptr);
- else
- *to1 = *from1;
- X/* file 2 */
- *from2 = atoi(part2);
- if (ptr = strchr(part2, ','))
- *to2 = atoi(++ptr);
- else
- *to2 = *from2;
-
- if (*type == 'a')
- ++*from1;
-
- if (*type == 'd')
- ++*from2;
- }
-
-
- toline(fd, lineis, linenum)
- XFILE *fd;
- int lineis, linenum;
- {
- /* note: toline can seek to one more line than there actually is (EOF) */
- while (lineis < linenum)
- {
- if (fgets(buffer, sizeof(buffer), fd))
- ++lineis;
- else
- break;
- }
- return lineis;
- }
-
- checkline(fd, lineis, linenum)
- XFILE *fd;
- int lineis, linenum;
- {
- lineis = toline(fd, lineis, linenum);
- if (!fgets(buffer, sizeof(buffer), fd))
- --lineis;
- return lineis;
- }
- //go.sysin dd *
-