From harvard!uucp Mon Nov 18 19:39:15 1985 Received: from harvard.HARVARD.EDU by seismo.CSS.GOV with SMTP; Mon, 18 Nov 85 19:11:58 EST Received: by harvard.HARVARD.EDU; Mon, 18 Nov 85 19:13:48 EST From: harvard!uucp (Black Hole) Return-Path: Received: by panda.LOCAL on Mon, 18 Nov 85 18:37:53 est Date: Mon, 18 Nov 85 18:37:53 est Message-Id: <8511182337.AA22121@panda.LOCAL> To: talcott!seismo!rick Subject: diffc Status: R 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 #include #include #include #ifdef V7 #define strchr index #include /* BEZERKELY 4.2 is strings.h */ #else #include #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 *