[comp.os.minix] patch

erikb@cs.vu.nl (Erik Baalbergen) (05/29/87)

I've written the following 'patch' program, which combines a text file and
a diff listing (as produced by my diff, posted earlier to this newsgroup).
See the 'Notes' section below for more information.

Erik Baalbergen

--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----
/* patch file difflist -- combine diff output and old file to produce new file;
   author: Erik baalbergen <erikb@cs.vu.nl>
*/

/* Notes:
   * files old and old.patch are equal after the following commands
	   diff old new > difflist
	   patch old difflist > old.patch
   * the diff output is assumed to be produced by my diff program.
   * the difflist has the following form:
	   difflist ::= chunk*
	   chunk ::= append | delete | change ;
	   append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1)
	   delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1)
	   change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n'
		      ['< ' line '\n'](n2 - n1 + 1)
		      '---\n'
		      ['> ' line '\n'](n4 - n3 + 1)
	   where
	   - n[1234] is an unsigned integer
	   - "[pat](expr)" means "(expr) occurences of pat"
	   - "[pat]?" means "either pat or nothing"
   * the information in the diff listing is checked against the file to which
     it is applied; an error is printed if there is a conflict
*/

#include <stdio.h>

extern char *fgets();
extern FILE *fopen();
#define LINELEN	1024

char *prog = 0;

char *
getline(fp, b)
	FILE *fp;
	char *b;
{
	if (fgets(b, LINELEN, fp) == NULL)
		fatal("unexpected eof");
	return b;
}

#define copy(str) printf("%s", str)

main(argc, argv)
	char **argv;
{
	char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
	int o1, o2, n1, n2, here; 
	FILE *fpf, *fpd;

	prog = argv[0];
	if (argc != 3)
		fatal("use: %s original-file diff-list-file", prog);
	if ((fpf = fopen(argv[1], "r")) == NULL)
		fatal("can't read %s", argv[1]);
	if ((fpd = fopen(argv[2], "r")) == NULL)
		fatal("can't read %s", argv[2]);
	here = 0;
	while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) {
		while (here < o1 - 1) {
			here++;
			copy(getline(fpf, obuf));
		}
		switch (cmd) {
		case 'c':
		case 'd':
			if (cmd == 'd' && n1 != n2)
				fatal("delete count conflict");
			while (o1 <= o2) {
				fl = getline(fpf, obuf);
				here++;
				fd = getline(fpd, nbuf);
				if (strncmp(fd, "< ", 2))
					fatal("illegal delete line");
				if (strcmp(fl, fd + 2))
					fatal("delete line conflict");
				o1++;
			}
			if (cmd == 'd')
				break;
			if (strcmp(getline(fpd, nbuf), "---\n"))
				fatal("illegal separator in chunk");
			/*FALLTHROUGH*/
		case 'a':
			if (cmd == 'a') {
				if (o1 != o2)
					fatal("append count conflict");
				copy(getline(fpf, obuf));
				here++;
			}
			while (n1 <= n2) {
				if (strncmp(getline(fpd, nbuf), "> ", 2))
					fatal("illegal append line");
				copy(nbuf + 2);
				n1++;
			}
			break;
		}
	}
	while (fgets(obuf, LINELEN, fpf) != NULL)
		copy(obuf);
	exit(0);
}

isdigit(c)
	char c;
{
	return c >= '0' && c <= '9';
}

char *
range(s, p1, p2)
	char *s;
	int *p1, *p2;
{
	register int v1 = 0, v2;

	while (isdigit(*s))
		v1 = 10 * v1 + *s++ - '0';
	v2 = v1;
	if (*s == ',') {
		s++;
		v2 = 0;
		while (isdigit(*s))
			v2 = 10 * v2 + *s++ - '0';
	}
	if (v1 == 0 || v2 == 0 || v1 > v2)
		fatal("illegal range");
	*p1 = v1;
	*p2 = v2;
	return s;
}

getcommand(fp, o1, o2, pcmd, n1, n2)
	FILE *fp;
	int *o1, *o2, *n1, *n2;
	char *pcmd;
{
	char buf[LINELEN];
	register char *s;
	char cmd;
	
	if ((s = fgets(buf, LINELEN, fp)) == NULL)
		return 0;
	s = range(s, o1, o2);
	if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd')
		fatal("illegal command");
	s = range(s, n1, n2);
	if (*s != '\n' && s[1] != '\0')
		fatal("extra characters at end of command: %s", s);
	*pcmd = cmd;
	return 1;
}

fatal(s, a)
	char *s, *a;
{
	fprintf(stderr, "%s: fatal: ", prog);
	fprintf(stderr, s, a);
	fprintf(stderr, "\n");
	exit(1);
}

wall-rt@cscosl.ncsu.edu (Richard Todd Wall) (03/11/90)

     Could someone please post a man page for the patch program???  If there
isn't one, could someone explain how it is used???

o o ______           _     _____  _  _ o o          mcnc!bacchus!beretta!todd
' '   /       /   / ' )   /      // // ' '    or    wall-rt@cscosl.ncsu.edu
     / ______/ __/   / / / __.  // //   
   _/ (_) (_/_(_/_  (_(_/ (_/|_</_</_               Durham, North Carolina

paula@bcsaic.UUCP (Paul Allen) (03/13/90)

In article <1990Mar11.081127.7489@ncsuvx.ncsu.edu> wall-rt@cscosl.ncsu.edu (Richard Todd Wall) writes:
>
>     Could someone please post a man page for the patch program???  If there
>isn't one, could someone explain how it is used???

Well, patch has lots of options and the man page documements all of
them.  But for the particular case of using patch to apply Minix
upgrades, all you really need to know is that patch eats diff files
on stdin and figures out what file(s) to patch by parsing the diffs.
It looks for the file(s) to patch in the current directory.

For applying the latest bunch of patches, I unpacked each shar file
in the appropriate directory and then ran this little script:

	for n in *.cdif
	do
		patch <$n
	done

Patch makes a copy of each file it patches in filename~ and any rejected
diffs go in filename#.  So if the patch output scrolls by too fast, you
can just look for *# to see if patch had any trouble.  (If you're
patching on a Berkeley system, you get .orig and .rej files, instead.)

Hope this helps!

Paul Allen


-- 
------------------------------------------------------------------------
Paul L. Allen                       | pallen@atc.boeing.com
Boeing Advanced Technology Center   | ...!uw-beaver!bcsaic!pallen

ST7749%SIUCVMB.BITNET@cunyvm.cuny.edu (Your's truly.) (06/05/91)

I've heard a lot about this mythical patch utility to apply diff's to
the MINIX source.  However, I've been unable to locate the damned thing.
I've got a copy of the source for MINIX 1.5, but I'm missing four rather
important library routines I'd rather not take the time to write right
now.  Is this some sort of conspiracy - I mean, I need MINIX 1.5 to get
patch to compile, but I can't get MINIX 1.5 until I can get patch running
right.  Somebody, please help me!  I realize that this is probably a very
miniscule problem compared to the differences in memory managment techniques,
but if I ever want to put my $0.02 in those lofty conversations, I need
a good working copy of the latest MINIX.  It does me no good to discuss
some problem I've found in 1.1, only to find that it was fixed for the
1.3 release.  Where the hell is patch?  If it ain't anywhere, what do I
need to apply these damn diff.pattern files and finally join the club?

Jon Fincher, ST7749@SIUCVMB.CDALE.SIU.EDU

rhyde@sisler.ucr.edu (randy hyde) (06/26/91)

I'm trying to use patch to update 1.3 -> 1.5 (I actually own 1.5 on
the PC, this is on my PC532).

I noticed that the _cd file (input to patch) contains pathnames like
/HOME/ME/MINIX/glo.h.

Do I have to have this same directory structure on my disk?
Thanks,
*** Randy Hyde