[comp.sources.atari.st] v02i067: diff -- File difference utility

koreth%panarthea.ebay@sun.com (Steven Grimm) (08/08/89)

Submitted-by: Schutte@nikhefh.hep.nl (Klamer Schutte)
Posting-number: Volume 2, Issue 67
Archive-name: diff

Here is the source of a diff(1) program. I wrote it some time ago, but
decided to submit now because of questions of such in comp.sys.atari.st.

There is no other copyright on the program than mentioned in its header --
I am the writer myself.

Compile, enjoy!
Klamer.

-- 
________________________________________________________________________________
Klamer Schutte      mcvax!nikhefh!{n62,Schutte}     {Schutte,n62}@nikhefh.hep.nl

------------ cut here -------------

/*
 *	diff.c
 *	program to compare text files
 *	prelimary release:	- only limited testing performed.
 *				- no context command as in (BSD) U*IX.
 *	Compiled using megamax. Other compilers shouldn't present problems.
 *	Permission granted for using this source if:
 *		- Credit to my name is made in the resulting program.
 *		- No profit is made on the program.
 *		  When you want to use this in a commercial product 
 *		  please contact me.
 *	
 *	Klamer Schutte
 *	Tolstraat 46-3
 *	1073 SC  Amsterdam 
 *	The Netherlands
 *	tel: 31 20 714578
 *	Schutte@nikhefh.hep.nl   \
 *	schutte@thoff.uucp       - for the time being
 *	mcvax!nikhefh!Schutte    /
 */

#include	<stdio.h>
#include	<errno.h>

#define	MAXLINE	75	/* screen width - space for '>nnn ' */

struct line
{	char	data[MAXLINE];
	struct line	*next;
	int	line_nr;
}

main( argc, argv )
int	argc;
char	*argv[];
{	FILE	*fp1, *fp2;
	struct line	*top1 = NULL, *top2 = NULL, 
			*cur1, *cur2, *last1, *last2;
	int	linenr1 = 0, linenr2 = 0, inc1 = 1, inc2 = 1,
		eof = 0,	/* flag where eof is detected */
		len;		/* used in test on '\n' */
/* #[   init: check argc, open fp1, fp2 */
	if (argc != 3)
	{	fputs( "Usage: diff file1 file2" , stderr );
		exit( -1 );
	}
	if (fp1 = fopen( argv[1], "r" ), fp1 == NULL)
	{	fprintf( stderr, "Error opening %s\n", argv[1] );
		exit( errno );
	}
	if (fp2 = fopen( argv[2], "r" ), fp2 == NULL)
	{	fprintf( stderr, "Error opening %s\n", argv[2] );
		exit( errno );
	}
/* #]   init: */
	while( 1 )
/* #[	main loop: exit: function end on eof other file */
	{	
		if (eof != 1)
		{
			cur1 = (struct line * ) malloc( sizeof( struct line ));
cur1->next = NULL;		
			if (cur1 == NULL)
			{	fprintf( stderr, "diff: out of memory\n");
				exit( -39 );
			}
			if (fgets( cur1->data, MAXLINE, fp1 ) == NULL)
		        {	
		        	if (eof == 0)
		        	{	eof = 1;
		        		continue;
		        	}
		        	if (top1 != NULL)
					end1( top1, "< ");
				if (top2 != NULL)
					end1( top2, "> ");
				exit( 0 );
			}
			linenr1 += inc1;
		        if (cur1->data[ len = (strlen(cur1->data) - 1)] == '\n')
		        {	cur1->data[ len ] = 0;
	        		inc1 = 1;
		        } else
				inc1 = 0;
	        	for( cur2 = top2; cur2 != NULL; cur2 = cur2->next)
/* #[ 			check on match: if cur1 == NULL match */
		        {	
				if (strcmp( cur2->data, cur1->data ) == 0)
	        		{	
					pr_all( top1, last1, "< " );
	        			free( cur1 );
		        		cur1 = NULL;
		        		top1 = NULL;
	        			last1 = NULL;
	        			pr_upto( top2, cur2, "> ");
	        			if (last2 == cur2)
		        		{	last2 = NULL;
		        			top2 = NULL;
	        			} else
	        				top2 = cur2->next;
					free( cur2 );
					break;
				}
	        	}
/* #] 			check on match: */	        
			if (cur1 != NULL)
			{
				if (last1 != NULL)
					last1->next = cur1;
				else
					top1 = cur1;
				cur1->line_nr = linenr1;
				cur1->next == NULL;
				last1 = cur1;
			}
		}
		/* The linked list from	top1 to last1 has cur1 added now
		   No record in this list compares to a record in the top2 list
		   Read now a line from fp2 and compare this to the top1 list
		*/
		if (eof != 2)
		{
			cur2 = (struct line * ) malloc( sizeof( struct line ));
cur2->next = NULL;
			if (cur2 == NULL)
			{	fprintf( stderr, "diff: out of memory\n");
				exit( -39 );
			}
			if (fgets( cur2->data, MAXLINE, fp2 ) == NULL)
	        	{
				if (eof == 0)
				{	eof = 2;
					continue;
				}
				if (top2 != NULL)
					end1( top2, "> " );
				if (top1 != NULL)
					end1( top1, "< ");
				exit( 0 );
			}
			linenr2 += inc2;
	        	if (cur2->data[ len = (strlen(cur2->data) - 1)] == '\n')
		        {	cur2->data[ len ] = 0;
		        	inc2 = 1;
	        	} else
				inc2 = 0;
		        for( cur1 = top1; cur1 != NULL; cur1 = cur1->next )
/* #[ 			check on match: if cur2 == NULL match */
		        {
				if (strcmp( cur2->data, cur1->data ) == 0)
	        		{	
	        			pr_all( top2, last2, "> " );
	        			free( cur2 );
		        		cur2 = NULL;
		        		top2 = NULL;
	        			last2 = NULL;
	        			pr_upto( top1, cur1, "< ");
	        			if (last1 == cur1)
		        		{	last1 = NULL;
		        			top1 = NULL;
	        			} else
	        				top1 = cur1->next;
					free( cur1 );
					break;
		        	} 
	        	}
/* #] 			check on match: */	        
			if (cur2 != NULL)
			{
				if( last2 != NULL)
					last2->next = cur2;
				else
					top2 = cur2;
				cur2->line_nr = linenr2;
				cur2->next == NULL;
				last2 = cur2;
			}
		}
	}
/* #]	main loop: */
}

/* #[ end: end1( struct line *, char *) end2( FILE *, struct line *, char *) */
end1( top, prefix )
struct line	*top;
char	*prefix;
{	for( ; top != NULL; top = top->next)
		printf( "%3d%s%s\n", top->line_nr, prefix, top->data );
}

end2( fp, linenr, prefix )
FILE	*fp;
int	linenr;
char	*prefix;
{	int	len;	/* used for checking & correcting '\n' on eoln */
	char	line[MAXLINE];
	while( fgets( line, MAXLINE, fp) != NULL)
	{	if (line[ len = (strlen(line) - 1)] == '\n')
	        {	line[ len ] = 0;
	        	linenr++;
	        }
	        printf( "%3d%s%s\n", linenr, prefix, line );
	}
	exit( 0 );
}
/* #] end:*/

/* #[ pr_all: pr_all( struct line *, struct line *, char *) */
pr_all( top, last, prefix )
struct line	*top, *last;
char	*prefix;
{	struct line	*cur;
	if (last != NULL)
		last = last->next;
	for( cur = top; cur != last && cur != NULL; cur = top->next, free(top))
	{	printf( "%3d%s%s\n", cur->line_nr, prefix, cur->data );
		top = cur;
	}
	if (cur != last && cur == NULL)
		fputs( "Internal Error in pr_all\n", stderr );
}
/* #] pr_all: */

/* #[ pr_upto: pr_upto( struct line *, struct line*, char * ) */
pr_upto( top, upto, prefix )
struct line	*top, *upto;
char	*prefix;
{	struct line	*cur;
	for( cur = top; cur != upto; cur = cur->next, free( top ))
	{	printf( "%3d%s%s\n", cur->line_nr, prefix, cur->data );
		top = cur;
	}
}
/* #] pr_upto:*/