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