/*
 *  bcom - binary compare utility.
 *
 *  usage: bcom (-option -option ... )  file1 file2
 *
 *  !! no options installed yet !!
 *
 *  Joe Majors - 11 Jan 88
 *
 *  Purpose:  Compares two binary files.  Prints locations when
 *  files differ and when files resume.  Location specification
 *  is sector/byte format that is compatible with 'NewZap' program.
 */

#include <stdio.h>
#include <fcntl.h>

/* Definitions to make life easier  */

#define TRUE 1
#define FALSE 0
#define abort exit(20)

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define ABS(x) ((x<0)?(-(x)):(x))

#define USAGE "Usage: bcom file1 file2"
#define BUFSIZE 512

char *malloc();  /* too avoid compiler warning */


/*  Declare file associated stuff */
 
char *name1, *name2; /* pointers to file names */
 
int   fd1,    fd2;   /* file descriptors (unit numbers) for files */

char *buf1,  *buf2;  /* pointers to dynamically allocated buffers */

/*
 *  Open a file with needed attributes in needed mode. Handle errors
 */

int myopen( filename ) /* returns file descriptor: int */
  char *filename; 
{
  int fd;

  if( (fd=open(filename,O_RDONLY)) < 0 ) {
    fprintf(stderr,"Can't Open %s\n",filename);
    abort;
  }
  return(fd);
}   

/*
 *  Function: hex - converts to formatted uppercase string 
 */

char *hex( i )
  short i;
  {
  static char str[] = "000";

  sprintf(str,"%03x",i);
  for(i=0;i<3;i++){
      if(str[i]<103 && str[i]>96) str[i] &= 0x5f;
  }
  return( (char *)&str);
}

/*
 *  Begin Main Program
 */

main(argc,argv)
  int argc;
  char *argv[];
{
  if(argc<3) {
    fprintf(stderr,"%s\n",USAGE); exit();
  }

  name1 = argv[1]; fd1 = myopen( name1 );
  name2 = argv[2]; fd2 = myopen( name2 );

  buf1 = malloc(BUFSIZE);
  buf2 = malloc(BUFSIZE);

  if( buf1==FALSE || buf2==FALSE ) {
    fprintf(stderr,"Can't Allocate Memory\n");
    abort;
  }

  printf("Comparison of  %s  vs  %s\n\n",name1,name2);

  /*  Main Processing Loop */
  {
    short length_diff = 0;
    short length;
    short len1, len2;
    short byte;
    int sector = 0;
    int numdifs = 0;
    unsigned char last_equal = TRUE;

    while( length_diff == 0 ) {

      len1 = read(fd1,buf1,BUFSIZE);  /* Get Data from Files */
      len2 = read(fd2,buf2,BUFSIZE);

      length_diff = len1 - len2;     /* length_diff < 0  file1 ends */
      length = MIN(len1,len2);       /* length_diff > 0  file2 ends */
      if(length==0) break;           /* one or more files ended */ 

      sector++;

      /*  Compare all bytes within this buffer (sector) */

      for( byte=0; byte<length; byte++) {
        if( buf1[byte] == buf2[byte] ) {
          if(!last_equal) {
            printf("Resume at %4d %s\n",sector,hex(byte));
            last_equal = TRUE;
          }
        } else {     /* bytes differ */
          if(last_equal) {
            printf("Differ at %4d %s ... ",sector,hex(byte));
            last_equal = FALSE;
          }
          numdifs++;
        }
      }

      if( length < BUFSIZE) break;  /* Didn't get full sector */

    }

    /* Determine and printout Final messages */

    if(length_diff == 0) {                          /* files same length */
      if(numdifs == 0) printf("Files Equivalent\n\n");
    } else {                                     /* files differ in length */
      char *fname;

      fname = (length_diff < 0 ) ? name1 : name2 ;
      if(!last_equal) printf("\n");
      printf("\nFile:  %s  ends first at %4d %s\n",fname,sector,hex(--byte));
    }
    if(numdifs>0) printf("\nTotal Differing Bytes: %d\n\n",numdifs);

  }
  /*  End of Main Processing Loop  */

  /*  Close up and de-allocate */

  free( buf1 ); close( fd1 );
  free( buf2 ); close( fd2 );
}

/*
 *  Null function - reduces code size by 212 bytes.
 *                  Can't run from WB now.
 */

_wb_parse()
{
}
