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:*/