home *** CD-ROM | disk | FTP | other *** search
- /* DIFF - File Comparator */
-
- /*
- Copyright (c) 1983 by Kevin B. Kenny
-
- This medium and the information contained herein are confidential to
- and the property of Kevin B. Kenny (the author) and are not to be disclosed
- to any third party without the written permission of the author or his
- designate. The author also claims copyright to the material as an
- "unregistered unpublished work" under USC 13, Section 105 of the United
- States Copyright Act of 1976.
-
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
- #include "cmdutil.h"
-
- /* Command line options */
-
- int dispmode; /* Display mode */
- #define DM_NORM 0 /* Normal display */
- #define DM_ALTER 1 /* Display alterations only */
- #define DM_MATCH 2 /* Display matching lines */
- #define MAXLINE 135
-
- int resync; /* Resynchronization count */
- char *header; /* Header for display */
- int blanksf; /* Flag = 1 if blanks s/b compressed */
- int single; /* Flag = 1 to ignore case differences */
- char * file1; /* Name of first file */
- char * file2; /* Name of second file */
-
- /* Input file status */
-
- FILE * file [2]; /* IObuf's of input files */
-
- struct file_line {
- struct file_line *next, *prev; /* Chain linkage */
- int line_no; /* Line number in file */
- char * line_text; /* Text of the line */
- };
-
- struct file_line * first_line [2]; /* First line from file in memory */
- struct file_line * last_line [2]; /* Last line from file in memory */
- struct file_line * cur_line [2]; /* Current line in memory */
- int linenumb [2]; /* Last line read from each file */
- int eofhit [2]; /* EOF read in from file */
-
- /* Status of resynchronizer */
-
- int equal; /* Flag to indicate equality */
- int match; /* Flag to indicate match reached */
- int left; /* File being read backwards */
- int right; /* FIle being read forwards */
- int loffset; /* Number of mismatches in "left" */
- int roffset; /* Number of mismatches in "right" */
- int difflen [2]; /* Number of mismatches by file */
- int hold; /* Working word for pointer switches */
-
- /* Procedures to be defined below */
-
- extern char *curline ();
-
- main (argc, argv)
- int argc;
- char ** argv;
- {
-
- fprintf(stderr, "K**2 DIFF MS-DOS version 85-05-09\n");
- fprintf (stderr, "copyright (c) 1983, 1984, 1985 by Kevin Kenny.\n");
- getopts(argc, argv);
- setup();
- rundiff();
- }
-
- /* Read an process the options from the command line */
-
- static struct option optable [8] = { /* Option descriptions for procarg */
- #define FILE_OPT -1
- "Alterations", NAKED_KWD,
- #define ALTER_OPT 0 /* Flag to show just changed text */
- "Matching", NAKED_KWD,
- #define MATCH_OPT 1 /* Flag to show just matching text */
- "Resynchronize", NVAL_KWD,
- #define RESYN_OPT 2 /* Line count for resynchronization */
- "Header", SVAL_KWD,
- #define HEAD_OPT 3 /* Header for output lines */
- "Blanks", NAKED_KWD,
- #define BLANK_OPT 4 /* Ignore multiple blanks */
- "Singlecase", NAKED_KWD,
- #define SINGLE_OPT 5
- EOF};
-
- getopts (argc, argv)
- int argc;
- char ** argv;
- {
-
- int info; /* Information item returned from procarg */
- int error; /* Error flag */
-
- dispmode = DM_NORM; /* Set default options */
- resync = 3;
- header = "-------------------------------------------------- ";
- blanksf = FALSE;
- single = FALSE;
- file1 = NULL;
- file2 = NULL;
-
- ++argv; --argc; /* Discard command name from argv */
-
- error = FALSE; /* No error has occurred yet */
-
- while (argc) { /* Process one command option */
- switch(procarg (&argc, &argv, optable, &info)) {
- case ALTER_OPT:
- dispmode = DM_ALTER; break;
- case MATCH_OPT:
- dispmode = DM_MATCH; break;
- case RESYN_OPT:
- resync = info; break;
- case HEAD_OPT:
- header = info; break;
- case BLANK_OPT:
- blanksf = TRUE; break;
- case SINGLE_OPT:
- single = TRUE; break;
- case FILE_OPT:
- if (file1 == NULL) file1 = info;
- else if (file2 == NULL) file2 = info;
- else error = TRUE;
- break;
- default:
- error = TRUE;
- }
- }
-
- if (file2 == NULL || error) {
- showsyntax("diff <file1> <file2>", optable);
- exit();
- }
- }
-
- /* Set up the DIFF process */
-
- setup () {
-
- if ((file [0] = fopen(file1, "r")) == NULL) {
- fprintf (stderr, "%s: can't open file.\n", file1);
- exit();
- }
- if ((file [1] = fopen(file2, "r")) == NULL) {
- fprintf(stderr, "%s: can't open file.\n", file2);
- exit();
- }
- first_line[0] = first_line[1] =
- last_line[0] = last_line[1] =
- cur_line[0] = cur_line[1] = NULL;
- linenumb[0] = linenumb[1] = 0;
- eofhit[0] = eofhit[1] = FALSE;
- equal = TRUE; /* Initially, files are assumed equal */
- fflush(stderr);
- }
-
- /* Do the DIFF process */
-
- rundiff () {
- while (!ateof(0) || !ateof(1)) { /* Run until end of files */
- domatch(); /* Handle matching lines */
- if (ateof(0) && ateof(1)) break;
- equal = FALSE; /* We've found a difference */
- synch(); /* Get us back in sync */
- dodiff(); /* Handle changed lines */
- }
- if (equal) fprintf(stderr,"\nThe files are equal\n");
- }
-
- /* Do matching lines */
-
- domatch () {
- if (!atmatch()) return; /* Handle non-match at start */
-
- if (dispmode == DM_MATCH) /* Displaying matches? */
- printf("%s%d, %d\n", header, lineno (0), lineno (1));
-
- while (atmatch() && !ateof(0)) {
- if (dispmode == DM_MATCH) /* Display matching lines */
- printf("%s", curline (0));
- advance(0); advance(1); /* Bump past matching lines */
- discard(0); discard(1); /* Throw away matched lines */
- }
- }
-
- /* Resynchronize comparison when mismatched lines found */
-
- synch () {
- left = 0; /* Move pointer leftward from
- current position in first file */
- right = 1; /* Move pointer rightward in second
- file. */
- loffset = roffset = 0; /* Both pointers at current line */
-
- do {
- ++roffset; advance(right); /* Move pointer rightward */
- if (--loffset >= 0) backup (left); /* Back leftward pointer up */
- else { /* Pointer reached divergence point */
- chkabrt();
- hold = right; right = left; left = hold; /* Swap input files */
- loffset = roffset; roffset = 0; /* Switch pointers */
- }
-
- match = TRUE; /* Innocent until proven guilty */
- for (hold = 0; hold < resync; ++hold) {
- if (!atmatch()) { /* Test if at least "resync" */
- match = FALSE; /* consecutive lines match */
- break;
- }
- advance(0); advance(1); /* Advance over matched lines*/
- }
- while (hold) {
- backup(0); backup(1); /* Back up over matched lines*/
- --hold;
- }
- } while (!match); /* Repeat synch until match found */
- difflen [left] = loffset;
- difflen [right] = roffset;
- while (loffset) {
- backup(left); --loffset; /* Back up over unmatched data */
- }
- while (roffset) {
- backup(right); --roffset;
- }
- }
-
- /* Process differences */
-
- dodiff () {
-
- if (dispmode != DM_MATCH) printf("%s %d", header, lineno (0));
- if (dispmode == DM_ALTER && difflen[0] != 0)
- printf(", %d", lineno (0) + difflen [0] - 1);
- if (dispmode != DM_MATCH) printf("\n");
-
- for (hold = 0; hold < difflen[0]; ++hold) {
- if (dispmode == DM_NORM)
- printf("%s", curline (0));
- advance(0);
- }
-
- if (dispmode == DM_NORM) printf("%s%d\n", header, lineno (1));
-
- for (hold = 0; hold < difflen [1]; ++hold) {
- if (dispmode != DM_MATCH)
- printf("%s", curline (1));
- advance(1);
- }
- }
-
- /* Test if a file is at EOF */
-
- int ateof (f)
- int f;
- {
- prepbuf(f);
- return(cur_line[f]->line_text == EOF);
- }
-
- /* Return the current line of a file */
-
- char * curline (f)
- int f;
- {
-
- prepbuf(f);
- return(cur_line[f]->line_text);
- }
-
- /* Return the current line number within file */
-
- int lineno (f)
- int f;
- {
-
- prepbuf(f);
- return(cur_line[f]->line_no);
- }
-
- /* Test if the current lines of the two files match */
-
- int atmatch () {
- char *s1, *s2;
-
- prepbuf(0); prepbuf(1);
- if (ateof(0) && ateof(1)) return (TRUE);
- if (ateof(0) || ateof(1)) return (FALSE);
-
- s1 = curline(0); s2 = curline(1);
- while (*s1 == *s2
- || (blanksf && isspace(*s1) && isspace(*s2))
- || (single && tolower(*s1) == tolower(*s2))) {
- if (*s1 == 0) return (TRUE);
- if (blanksf && isspace(*s1)) {
- while (isspace(*++s1));
- while (isspace(*++s2));
- }
- else {
- ++s1; ++s2;
- }
- }
- return(FALSE);
- }
-
- /* Advance to the next line of a file */
-
- advance (f)
- int f;
- {
-
- cur_line[f] = cur_line[f]->next;
- prepbuf(f);
- }
-
- /* Back up to the previous line in a file */
-
- backup (f)
- int f;
- {
-
- if ((cur_line[f] = cur_line[f]->prev) == NULL) {
- fprintf(stderr, "\nin backup: can't happen");
- exit();
- }
- }
-
- /* Discard all lines in memory up to the present point */
-
- discard (f)
- int f;
- {
-
- while (first_line[f] != cur_line[f]) {
- if (first_line[f]->line_text != EOF) free (first_line[f]->line_text);
- hold = first_line[f]->next;
- free(first_line[f]);
- first_line[f] = hold;
- }
- if (first_line[f] == NULL) {
- last_line[f] = NULL;
- }
- }
-
- /* Bring the current line to memory if it isn't there */
-
- prepbuf (f)
- int f;
- {
-
- struct file_line *newl;
- char *txt;
- char text[MAXLINE];
-
- if (cur_line[f] != NULL) return;
- newl = malloc(sizeof(*newl));
- if (!newl) punt();
- if (!eofhit[f] && (fgets(text, MAXLINE, file [f]) != NULL)) {
- txt = malloc(strlen(text) + 1);
- if (!txt) punt();
- strcpy(txt, text);
- newl->line_text = txt;
- }
- else {
- newl->line_text = EOF;
- eofhit[f] = TRUE;
- }
- newl->line_no = ++linenumb[f];
- if (last_line[f] != NULL) {
- last_line[f]->next = newl;
- }
- else {
- first_line[f] = newl;
- }
-
- newl->prev = last_line[f];
- newl->next = NULL;
- last_line[f] = cur_line[f] = newl;
- return;
-
- }
-
- punt () {
-
- fprintf(stderr, "Files have too many differences to compare.");
- exit();
- }
-
- chkabrt () {
- struct reg r;
-
- r.r_ax = CONDIO; r.r_dx = 0xFF;
- intcall(&r, &r, DOSINT);
- if (r.r_ax & 0xFF == 0x03) {
- printf(stderr, "\nDIFF aborted by operator\n");
- exit();
- }
- }