lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (07/26/88)
In article <150@ispi.UUCP> jbayer@ispi.UUCP writes: > I have Larry Wall's patch program (it works great), and have a > need to create some diffs for use with it. I have looked in several > different manuals and books, but cannot find out how to create the diffs > with the file names included. According to the patch documentation > context diffs create a header which specify the file names. However, the > normal diff command doesn't do that. Is there a PD diff which creates > diffs in the format that patch likes best? Thanks. Here's a little thing I whipped together a while back to do just what you want. It runs your normal diff for you and then turns that into a context diff. I apologize for posting source to d newsgroups, but this thing's so piddly small it isn't worth waiting the month for it to get through the moderated group. Larry Wall lwall@jpl-devvax.jpl.nasa.gov #! /bin/sh # Make a new directory for the cdiff sources, cd to it, and run kits 1 # thru 1 through sh. When all 1 kits have been run, read README. echo "This is cdiff 1.1 kit 1 (of 1). If kit 1 is complete, the line" echo '"'"End of kit 1 (of 1)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) mkdir 2>/dev/null echo Extracting README sed >README <<'!STUFFY!FUNK!' -e 's/X//' XThis program runs a normal diff as input to a pipe, and transforms that into Xa 4.3bsd-style context diff. X XTo compile, just type "cc -o cdiff cdiff.c". You might want to throw in Xa -Dvoid=int if your C compiler doesn't grok the void type. X XTo run, just say "cdiff file1 file2". Cdiff will run a "diff file1 file2" Xfor you, and modify that output to make the context diff. If you don't have Xa normal diff program, there is a PD version available from Erik Baalbergen Xat erikb@cs.vu.nl. !STUFFY!FUNK! echo Extracting cdiff.c sed >cdiff.c <<'!STUFFY!FUNK!' -e 's/X//' Xstatic char rcsid[] = "$Header: cdiff.c,v 1.1.1.2 87/06/04 11:21:43 lwall Exp $"; X X/* cdiff - turns a regular diff into a new-style context diff X * X * Usage: cdiff file1 file2 X * X * $Log: cdiff.c,v $ X * Revision 1.1.1.2 87/06/04 11:21:43 lwall X * Didn't do diffs with less than 3 lines of leading context. X * X * Revision 1.1.1.1 87/06/03 11:52:25 lwall X * Wasn't concatenating overlapping hunks right. X * X * Revision 1.1 87/06/01 16:05:57 lwall X * Initial revision X * X */ X X#include "patchlevel.h" X#include <stdio.h> X#include <sys/types.h> X#include <stat.h> X#include <ctype.h> X Xchar buf[512]; X XFILE *inputfp, *oldfp, *newfp; X Xint oldmin, oldmax, newmin, newmax; Xint oldbeg, oldend, newbeg, newend; Xint preoldmax, prenewmax; Xint preoldbeg, preoldend, prenewbeg, prenewend; Xint oldwanted, newwanted; X Xchar *oldhunk, *newhunk; Xunsigned oldsize, oldalloc, newsize, newalloc; X Xvoid dumphunk(); Xchar *getold(); Xchar *getnew(); Xchar *malloc(); Xchar *realloc(); Xchar *fgets(); XFILE *popen(); X X#define Nullfp (FILE*)0 X#define Nullch (char*)0 X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X char *old, *new; X int context = 3; X struct stat statbuf; X register char *s; X char op; X char *newmark, *oldmark; X int len; X char *line; X int i; X X oldalloc = 512; X oldhunk = malloc(oldalloc); X newalloc = 512; X newhunk = malloc(newalloc); X X for (argc--,argv++; argc; argc--,argv++) { X if (argv[0][0] != '-') X break; X if (argv[0][1] == 'v') { X printf("%s\n Patch level: %d\n",rcsid,PATCHLEVEL); X exit(0); X } X if (argv[0][1] == 'c') X context = atoi(argv[0]+2); X } X X if (argc != 2) { X fprintf(stderr,"cdiff old new\n"); X exit(1); X } X X old = argv[0]; X new = argv[1]; X X sprintf(buf,"diff %s %s", old, new); X inputfp = popen(buf, "r"); X if (!inputfp) { X fprintf(stderr, "Can't execute diff %s %s\n", old, new); X exit(1); X } X X oldfp = fopen(old,"r"); X if (!oldfp) { X fprintf(stderr, "Can't open %s\n", old); X exit(1); X } X newfp = fopen(new,"r"); X if (!newfp) { X fprintf(stderr, "Can't open %s\n", new); X exit(1); X } X X fstat(fileno(oldfp),&statbuf); X printf("*** %s\t%s", old, ctime(&statbuf.st_mtime)); X fstat(fileno(newfp),&statbuf); X printf("--- %s\t%s", new, ctime(&statbuf.st_mtime)); X X preoldend = -1000; X X while (fgets(buf, sizeof buf, inputfp) != Nullch) { X if (isdigit(*buf)) { X oldmin = atoi(buf); X for (s = buf; isdigit(*s); s++) ; X if (*s == ',') { X s++; X oldmax = atoi(s); X for ( ; isdigit(*s); s++) ; X } X else { X oldmax = oldmin; X } X if (*s != 'a' && *s != 'd' && *s != 'c') { X fprintf(stderr, "Unparseable input: %s", s); X exit(1); X } X op = *s; X s++; X newmin = atoi(s); X for ( ; isdigit(*s); s++) ; X if (*s == ',') { X s++; X newmax = atoi(s); X for ( ; isdigit(*s); s++) ; X } X else { X newmax = newmin; X } X if (*s != '\n' && *s != ' ') { X fprintf(stderr, "Unparseable input: %s", s); X exit(1); X } X X newmark = oldmark = "! "; X if (op == 'a') { X oldmin++; X newmark = "+ "; X } X if (op == 'd') { X newmin++; X oldmark = "- "; X } X X oldbeg = oldmin - context; X oldend = oldmax + context; X if (oldbeg < 1) X oldbeg = 1; X newbeg = newmin - context; X newend = newmax + context; X if (newbeg < 1) X newbeg = 1; X X if (preoldend < oldbeg - 1) { X if (preoldend >= 0) { X dumphunk(); X } X preoldbeg = oldbeg; X prenewbeg = newbeg; X oldwanted = newwanted = 0; X oldsize = newsize = 0; X } else { /* we want to append to previous hunk */ X oldbeg = preoldmax + 1; X newbeg = prenewmax + 1; X } X X for (i = oldbeg; i <= oldmax; i++) { X line = getold(i); X if (!*line) { X oldend = oldmax = i - 1; X break; X } X len = strlen(line) + 2; X if (oldsize + len + 1 >= oldalloc) { X oldalloc *= 2; X oldhunk = realloc(oldhunk, oldalloc); X } X if (i >= oldmin) { X strcpy(oldhunk+oldsize, oldmark); X oldwanted++; X } X else { X strcpy(oldhunk+oldsize, " "); X } X strcpy(oldhunk+oldsize+2,line); X oldsize += len; X } X preoldmax = oldmax; X preoldend = oldend; X X for (i = newbeg; i <= newmax; i++) { X line = getnew(i); X if (!*line) { X newend = newmax = i - 1; X break; X } X len = strlen(line) + 2; X if (newsize + len + 1 >= newalloc) { X newalloc *= 2; X newhunk = realloc(newhunk, newalloc); X } X if (i >= newmin) { X strcpy(newhunk+newsize, newmark); X newwanted++; X } X else { X strcpy(newhunk+newsize, " "); X } X strcpy(newhunk+newsize+2,line); X newsize += len; X } X prenewmax = newmax; X prenewend = newend; X } X } X X if (preoldend >= 0) { X dumphunk(); X } X} X Xvoid Xdumphunk() X{ X int i; X char *line; X int len; X X for (i = preoldmax + 1; i <= preoldend; i++) { X line = getold(i); X if (!line) { X preoldend = i - 1; X break; X } X len = strlen(line) + 2; X if (oldsize + len + 1 >= oldalloc) { X oldalloc *= 2; X oldhunk = realloc(oldhunk, oldalloc); X } X strcpy(oldhunk+oldsize, " "); X strcpy(oldhunk+oldsize+2, line); X oldsize += len; X } X for (i = prenewmax + 1; i <= prenewend; i++) { X line = getnew(i); X if (!line) { X prenewend = i - 1; X break; X } X len = strlen(line) + 2; X if (newsize + len + 1 >= newalloc) { X newalloc *= 2; X newhunk = realloc(newhunk, newalloc); X } X strcpy(newhunk+newsize, " "); X strcpy(newhunk+newsize+2, line); X newsize += len; X } X fputs("***************\n",stdout); X if (preoldbeg >= preoldend) { X printf("*** %d ****\n", preoldend); X } else { X printf("*** %d,%d ****\n", preoldbeg, preoldend); X } X if (oldwanted) { X fputs(oldhunk,stdout); X } X oldsize = 0; X *oldhunk = '\0'; X if (prenewbeg >= prenewend) { X printf("--- %d ----\n", prenewend); X } else { X printf("--- %d,%d ----\n", prenewbeg, prenewend); X } X if (newwanted) { X fputs(newhunk,stdout); X } X newsize = 0; X *newhunk = '\0'; X} X Xchar * Xgetold(targ) Xint targ; X{ X static int oldline = 0; X X while (fgets(buf, sizeof buf, oldfp) != Nullch) { X oldline++; X if (oldline == targ) X return buf; X } X return Nullch; X} X Xchar * Xgetnew(targ) Xint targ; X{ X static int newline = 0; X X while (fgets(buf, sizeof buf, newfp) != Nullch) { X newline++; X if (newline == targ) X return buf; X } X return Nullch; X} !STUFFY!FUNK! echo Extracting MANIFEST sed >MANIFEST <<'!STUFFY!FUNK!' -e 's/X//' XAfter all the cdiff kits are run you should have the following files: X XFilename Kit Description X-------- --- ----------- XMANIFEST 1 This file. XREADME 1 Instructions. Xcdiff.c 1 The program. Xpatchlevel.h 1 The patch level of cdiff. !STUFFY!FUNK! echo Extracting patchlevel.h sed >patchlevel.h <<'!STUFFY!FUNK!' -e 's/X//' X#define PATCHLEVEL 2 !STUFFY!FUNK! echo "" echo "End of kit 1 (of 1)" cat /dev/null >kit1isdone run='' config='' for iskit in 1; do if test -f kit${iskit}isdone; then run="$run $iskit" else todo="$todo $iskit" fi done case $todo in '') echo "You have run all your kits. Please read README." ;; *) echo "You have run$run." echo "You still need to run$todo." ;; esac : Someone might mail this, so... exit