home *** CD-ROM | disk | FTP | other *** search
- #define VERSION "1.0"
-
- /* FILDIF - SOURCE FILE DIFFERENCES LISTING */
-
- /*
- Author: Dennis B. Ruggles
-
- Orion Data Resources
- PO box 3110
- Manchester, NH 03105
- (603) 622-2865
-
- Original SRCDIF modified by B.Eiben DEC Marlboro
- to compare two FILES.IDX [single line per file directories]
- of the SIMTEL archives and generate the 'rough' command-files
- to 'delete' superceded and 'get' new files.
- Compilation via Turbo-C.
- */
-
- /*
- The following includes and defines are specifi-
- cally for Microsoft's C compiler and library
- */
-
- #include "stdio.h"
- #include "stdlib.h"
- #include "dos.h"
-
- #define index strchr
- #define alloc malloc
- /* #define coreleft _memavl */
- #define movcmdln( to ) { struct SREGS sregs;\
- segread( &sregs );\
- movedata( _psp, 0x80, sregs.ds, to, 128 );\
- }
-
- #define blockmv( dest, src, count ) (memcpy( dest, src, count ))
-
- /* -------------------- END Microsoft specifics -------------------- */
-
- #define TRUE 1
- #define FALSE 0
-
- char *USAGE[] ={
- "\n Simtel File-Compare (Version ", VERSION, ")\n"
- ,"\n\
- Usage: FILDIF FILES.IDX(old) FILES.NEW(new FILES.IDX)\n"
- ,"\n\
- Creates files DELFILES.CMD [Files to be first DELETED]\n\
- GETFILES.CMD [Files to be 'gotten']\n"
- ,"\n\
- Both .CMD files have to be edited for system specific commands!!\n"
- ,NULL
- };
- char CUR_DEFAULT[] = "\n Current defaults are /D%d /C%d /B%d /W -%s";
-
- char ON[] = "on";
- char OFF[] = "off";
-
- #define NUM_CMP 1 /* no. of equal lines ending a difference area */
- #define MIN_DISP 0 /* no. of lines to display prior to differences */
- #define MIN_BUF 64 /* min size of internal buffer in 128 byte units */
-
- int num_disp = MIN_DISP;
- int num_cmp = NUM_CMP;
- unsigned int num_buf = MIN_BUF;
- int white_space = FALSE;
-
- #define FORWARD 1 /* direction for stepping LINE pointers */
- #define BACKWARD -1
-
-
- /* error messages */
-
- char CANT_OPEN[] = " CANNOT BE OPENED";
-
- /* address of command buffer for parsing switches */
-
- char CMD_BUF[ 128 ];
-
- /* structure of a line in the line buffers */
-
- typedef struct{
- int num_prev; /* no. of chars in previous line */
- int num_this; /* no. of chars in this line */
- unsigned line_num; /* line counter */
- char line[1]; /* first char of variable length line */
- } LINE;
-
- /* typed functions */
-
- FILE *fopen();
- char *fgets();
- char *alloc();
- long int ftell();
- LINE *step_inx();
- char *p_non_white();
- unsigned int chrpos();
- unsigned int coreleft();
-
- /* LINE pointers */
-
- LINE *lines[2]; /* pointers to the two line arrays */
- LINE *l_end[2]; /* pointers to the ends of the two arrays */
- LINE *l_inx[2]; /* pointers to current last lines in the arrays */
- LINE *c_inx[2]; /* pointers to the two lines being compared */
- LINE *e_dif[2]; /* pointers to end of current difference area */
-
- /* flags and counters */
-
- char eof[2]= { FALSE, FALSE }; /* end of file flags for the two files */
-
- char differences = 0; /* count of number of difference areas found */
-
- /* command line arguments */
-
- int argc;
- char **argv;
-
- /* for readability of this program: */
-
- #define file1 0
- #define file2 1
-
- /* file pointers returned by C-library "fopen" */
-
- FILE *file[4];
-
- /* MAIN PROGRAM */
-
- /*-----------------------------------------*/
- main( c, v) int c; char *v[];
- /*-----------------------------------------*/
- {
- argc = c; /* move arguments to global definitions */
- argv = v;
- movcmdln( CMD_BUF );
-
- get_switches(); /* parse switches (if any) */
-
- open_files();
-
- /* Title line and statment of current option settings */
-
- printf( "\nFILDIF creating DELFILES.CMD and GETFILES.CMD from %s and %s\n"
- , argv[1]
- , argv[2]
- );
-
- /* printf( " (Option settings: /D%d /C%d /B%d /W -%s)\n"
- * , num_disp
- * , num_cmp
- * , num_buf
- * , (white_space ? ON : OFF)
- * );
- */
- printf( " Version %s\n\n", VERSION );
-
- assign_buffers(); /* grab memory for buffers */
- compare_files(); /* do the file comparisons */
-
- /* output a summary report */
-
- if( differences )
- printf( "\n%d DIFFERENCES FOUND BETWEEN %s AND %s\n"
- , differences
- , argv[ 1 ]
- , argv[ 2 ]
- );
- else
- printf( "\nFILES %s AND %s ARE THE SAME.\n"
- , argv[ 1 ]
- , argv[ 2 ]
- );
-
- if( white_space )
- printf( "(MULTIPLE SPACES, TABS, FORM-FEEDS, BLANK LINES IGNORED)\n" );
-
- exit(0);
- }
-
- /* COMPARE_FILES */
-
- /*---------------------*/
- compare_files()
- /*---------------------*/
- {
- /* keep going until we run completely out of text */
-
- while( more_lines( file1 ) /* fill buffer with file1 data */
- | more_lines( file2 ) /* fill buffer with file2 data */
- ){
-
- do{ /* compare the buffers line-by-line */
-
- check_abort(); /* Operator had enough of this ? */
-
- if( ! cmp_line( &c_inx[ file1 ]->line, &c_inx[ file2 ]->line ) ){
-
- /* if a line doesn't compare */
-
- find_differences(); /* find the difference area */
- display_differences(); /* and display it. */
- differences += 1; /* count the difference areas */
- }
- else{
-
- /* bump comparison index for each equal line */
-
- c_inx[ file1 ] = step_inx( c_inx[ file1 ], FORWARD );
- c_inx[ file2 ] = step_inx( c_inx[ file2 ], FORWARD );
- }
-
- /* until the end of one of the buffers comes up */
-
- }while( (c_inx[ file1 ] != l_inx[ file1 ])
- && (c_inx[ file2 ] != l_inx[ file2 ])
- );
- }
- }
-
- /* STEP_INX, MORE_LINES, COMPRESS */
-
- /*-------------------------------------------------------*/
- LINE *step_inx( l, direc ) register LINE *l; int direc;
- /*-------------------------------------------------------*/
- { static int add_amount;
-
- switch( direc ){
-
- case FORWARD: /* step a LINE pointer forward */
-
- add_amount = (l->num_this);
- add_amount += (add_amount ? /* don't step if NULL */
- (sizeof( LINE ) - 1)
- : 0
- );
- break;
-
- case BACKWARD: /* step a LINE pointer backward */
-
- add_amount = -(l->num_prev);
- add_amount -= (add_amount ? /* don't step if NULL */
- (sizeof( LINE ) - 1)
- : 0
- );
- break;
- }
- (char *)l = (char *)(l) + add_amount;
- return( l ); /* return new pointer */
- }
-
- /*--------------------------------*/
- more_lines( f ) register int f;
- /*--------------------------------*/
- { static int got_more;
-
- got_more = compress( f ); /* make room for more data */
- return (got_more | read_lines( f )); /* and read it in. */
- }
- /*------------------------------*/
- compress( f ) register int f;
- /*------------------------------*/
- { static LINE *mark;
- static int num_chars, move_distance;
- static int i;
-
- /* move data in buffer down to make room */
-
- mark = c_inx[ f ]; /* everything prior to c_inx is equal */
-
- /* also preserve the requested number of equal lines to display */
-
- for( i=0; i < num_disp; ++i )
- mark = step_inx ( mark, BACKWARD );
-
- /* now move the data down */
-
- num_chars = ( (char *)(l_inx[ f ]) - (char *)(mark) ) + sizeof( LINE );
- move_distance = ( (char *)(mark) - (char *)(lines[ f ]) );
- blockmv( lines[ f ], mark, num_chars );
-
- /* reset our pointers to our moved data */
-
- (char *)l_inx[ f ] = (char *)(l_inx[ f ]) - move_distance;
- (char *) c_inx[ f ] = (char *)(c_inx[ f ]) - move_distance;
-
- lines[ f ]->num_prev = 0; /* first line has no previous */
- return move_distance;
- }
-
- /* READ_LINES */
-
- /*--------------------------------*/
- read_lines( f ) register int f;
- /*--------------------------------*/
- { static LINE *next_line; static long file_pos; static int size_left;
- static int line_size; static int got_some; static int i;
- static unsigned line_num;
-
- line_num = l_inx[ f ]->line_num;
- got_some = FALSE;
-
- /*
- keep reading as long as there is input data and enough
- room left for a LINE structure containing two characters
- (e.g. "\n\0") followed by a LINE structure consisting
- of one null character (for l_inx)
- */
-
- while( (! eof[ f ])
- && ( (size_left = (char *)(l_end[ f ])
- - (char *)(&l_inx[ f ]->line)
- - sizeof( LINE )
- ) > 1
- )
- ){
-
- check_abort();
-
- /* remember where we are in case next line goes beyond end */
-
- file_pos = ftell( file[ f ] );
-
- /* get next line */
-
- if( eof[ f ] = ( (fgets( &l_inx[ f ]->line, size_left, file[ f ] )
- ) == NULL
- )
- )
- break; /* unless none */
-
- /* calculate the number of characters in the line */
-
- l_inx[ f ]->num_this
- = line_size
- = chrpos( &l_inx[ f ]->line, '\0' );
-
- /* make sure the line fit in the size_left */
-
- if( l_inx[ f ]->line[ --line_size ] != '\n' ){
- fseek( file[ f ], file_pos, 0 ); /* it didn't so reset */
- break; /* the file pointers */
- } /* to re-read it later */
-
- l_inx[ f ]->line[ line_size ] = '\0'; /* delete the '\n' at end */
- ++line_num; /* count the lines */
-
- /* If in the "ignore white space" mode - skip blank lines */
-
- if( ! ( (white_space)
- && (*p_non_white( &l_inx[ f ]->line ) == '\0')
- )
- ){
-
- /* We have a new source line */
-
- got_some = TRUE; /* set return flag to say we got data */
-
- /* construct partial new LINE structure marking the end */
-
- l_inx[ f ] = step_inx( l_inx[ f ], FORWARD );
- l_inx[ f ]->num_prev = line_size;
- }
- l_inx[ f ]->line_num = line_num; /* Update line number, if changed */
- }
- /* clean up final l_inx LINE structure and leave */
-
- l_inx[ f ]->num_this = 0;
- l_inx[ f ]->line[0] = '\0';
-
- return got_some;
- }
-
- /* FIND_DIFFERENCES */
-
- /*----------------------*/
- find_differences() /* determine boundaries of difference area */
- /*----------------------*/
- { static int i, k, swc_0_1;
- static int match;
- static LINE *c_inx1_init, *c_inx2_init;
- register LINE *inx1, *inx2;
-
- more_lines( file1 ); /* get as much data as possible for use */
- more_lines( file2 ); /* in determining the difference area */
-
- /*
- set a maximal difference area in case the cross compare loop is
- never entered (which happens repeatedly at the end of processing
- when one file is very much longer than the other)
- */
-
- e_dif[ file1 ] = l_inx[ file1 ];
- e_dif[ file2 ] = l_inx[ file2 ];
-
- /* initialize things */
-
- k = 1;
- c_inx1_init = c_inx[ file1 ];
- c_inx2_init = c_inx[ file2 ];
- match = FALSE;
- swc_0_1 = 0;
-
- /*
- The following loop performs a "cross-compare" on an ever-
- increasing number of lines between the two files. It does
- this until it gets "num_cmp" successive equal lines or
- runs out of data to compare.
- */
-
- while( ! match /* not got num_cmp equal */
- && (c_inx[ file1 ] != l_inx[ file1 ]) /* and more lines to com- */
- && (c_inx[ file2 ] != l_inx[ file2 ]) /* pare in both buffers */
- ){
-
- /*
- Step both c_inx's to widen the potential difference area. Also,
- now that we got into the loop, set a better maximal difference
- area in case we never find num_cmp equal ("match" never set TRUE)
- */
-
- e_dif[ file1 ]
- = c_inx[ file1 ]
- = step_inx( c_inx[ file1 ], FORWARD );
-
- e_dif[ file2 ]
- = c_inx[ file2 ]
- = step_inx( c_inx[ file2 ], FORWARD );
-
-
- /* The "cross-compare": */
-
- do{ /* twice, once with "swc_0_1" = 0, and again with it = 1 */
-
- switch( swc_0_1 ){
-
- case 0:
-
- /*
- set things up to compare all lines from original
- c_inx[ file1 ] down to, but not including the new
- c_inx[ file1 ] with the new line at c_inx[ file2]
- */
-
- i = k; /* leaving old "k" causes the exclusion */
- inx1 = c_inx1_init;
- inx2 = c_inx[ file2 ];
- break;
-
- case 1:
-
- /*
- set things up to compare all lines from original
- c_inx[ file2 ] down to, and this time including the
- new c_inx[ file2 ] with the new line at c_inx[ file1 ]
- */
-
- i = ++k; /* increasing "k" causes the inclusion */
- inx1 = c_inx[ file1 ];
- inx2 = c_inx2_init;
- break;
- }/* end switch( swc_0_1 ){ . . . */
-
- /* if any single line compares, try to get a "num_cmp" match */
-
- while( i-- ){
-
- if( (cmp_line( &inx1->line, &inx2->line ))
- && (match = try_num_cmp( inx1, inx2 ))
- )
- break; /* the difference area is finally defined */
- /*
- after each failure on a "num_cmp" match,
- step the appropriate index to the next line
- */
-
- switch( swc_0_1 ){
-
- case 0:
- inx1 = step_inx( inx1, FORWARD );
- break;
-
- case 1:
- inx2 = step_inx( inx2, FORWARD );
- break;
-
- }/* end switch( swc_0_1 ){ . . . */
- }/* end while( i-- ){ . . . */
- /*
- flip "swc_0_1" from 0 to 1 unless we got a
- "num_cmp" match or "swc_0_1" was already a 1
- */
- }/* end do{ . . .*/ while( ! match && (swc_0_1 ^= 1) );
-
- }/* end of while( ! match ){ . . . */
-
- /* see how we got out of the above loop */
-
- if( ! match ){ /* then we ran out of things to compare */
- c_inx[ file1 ] = e_dif[ file1 ];
- c_inx[ file2 ] = e_dif[ file2 ];
- }
- }
-
- /* TRY_NUM_CMP */
-
- /*---------------------------------------------------------*/
- try_num_cmp( x_file1, x_file2 ) LINE *x_file1, *x_file2;
- /*---------------------------------------------------------*/
- { static int i; register LINE *inx1, *inx2;
-
- inx1 = x_file1; inx2 = x_file2;
-
- /*
- since we got here by making one comparison, the following
- loop actually performs "num_cmp - 1" compares.
- */
- for( i = num_cmp; --i;){
- inx1 = step_inx( inx1, FORWARD );
- inx2 = step_inx( inx2, FORWARD );
- if( ! cmp_line( &inx1->line, &inx2->line ) )
- return FALSE;
- }
- c_inx[ file1 ] = step_inx( inx1, FORWARD );
- c_inx[ file2 ] = step_inx( inx2, FORWARD );
-
- e_dif[ file1 ] = x_file1;
- e_dif[ file2 ] = x_file2;
-
- return TRUE;
- }
-
- /* DISPLAY_DIFFERENCES */
-
- /*----------------------*/
- display_differences() /* display a difference area */
- /*----------------------*/
- { register LINE *inx;
- register unsigned int this_line;
- static int i;
-
- /* for "file1" (0) and "file2" (1) : */
-
- for( i = 0; i < 2; ++i){
-
- inx = lines[ i ];
- this_line = inx->line_num; /* Set counter to restore blank lines */
-
- /* output a title */
-
- /*
- * printf( ":----------- line %u of %s -----------:\n"
- * , this_line
- * , argv[ i+1 ]
- * );
- */
- /* then the difference area */
-
- for( ; inx != e_dif[ i ]; inx = step_inx( inx, FORWARD ) ){
- while( this_line++ != inx->line_num ) /* Restore any blank lines */
- printf( "\n" );
- check_abort();
- fprintf(file[i+3],"%s\n", &inx->line );
- }
- }
- /* mark the end of the difference area */
- /*
- * printf(">>****************************************<<\n\n");
- */
- }
-
- /* GET_SWITCHES */
-
- /*------------------------*/
- get_switches()
- /*------------------------*/
- { register char *swc; register int *val; char *index();
-
- swc = CMD_BUF;
-
- /* scan command line for slashes, and determine the switch */
-
- while( swc = index( swc, '/' ) ){
-
- switch( toupper(*++swc) ){
-
- case 'B': /* set internal buffer size */
- /* for reading the files */
- val = &num_buf;
- break;
-
- case 'C': /* set number of comparisons */
- /* defining a difference area */
- val = &num_cmp;
- break;
-
- case 'D': /* set number of lines to dis- */
- /* play prior to difference area */
- val = &num_disp;
- break;
-
- case 'W':
-
- white_space = TRUE; /* Ignore multiple white spaces */
- break;
-
- case 'H':
- help();
- break;
-
- default:
- err_exit("\nUnknown switch specified");
- }
- /* get value for the switch, and check minimums */
-
- if( val != NULL )
- sscanf( ++swc, "%d", val );
-
- if( num_buf < MIN_BUF )
- num_buf = MIN_BUF;
- if( num_cmp < NUM_CMP )
- num_cmp = NUM_CMP;
- if( num_disp < MIN_DISP )
- num_disp = MIN_DISP;
- }
- }
-
- /* OPEN_FILES, ASSIGN_BUFFERS */
-
- /*---------------*/
- open_files()
- /*---------------*/
- { register int i;
-
- if( argc < 3 ) /* if no files, show help message */
- help();
-
- /* open the files */
-
- for( i = 0; i < 2; ++i ){
- if( ! (file[ i ] = fopen( argv[i+1], "r" )) ){
- printf( "\n%s", argv[i+1] );
- err_exit( CANT_OPEN ); /* oh, s-s-sigh!! */
- }
- }
- if( ! (file[ 3 ] = fopen("DELFILES.CMD", "w" )) ){
- printf( "\n%s", "DELFILES.CMD");
- err_exit( CANT_OPEN );
- }
- if( ! (file[ 4 ] = fopen("GETFILES.CMD", "w" )) ){
- printf( "\n%s", "GETFILES.CMD");
- err_exit( CANT_OPEN );
- }
- }
-
- /*------------------------*/
- assign_buffers()
- /*------------------------*/
- { unsigned int i;
-
- /*
- divide available memory between "file1"
- and "file2" in 128 byte chunks
- */
-
- i = (coreleft() - 1000) / 2;
-
- if( i > (num_buf <<= 7) )
- i = num_buf;
-
-
- (char *) lines[ 0 ] = alloc( i );
- (char *) lines[ 1 ] = alloc( i );
-
- if( (lines[ 0 ] == NULL)
- || (lines[ 1 ] == NULL)
- || (i < ( MIN_BUF << 7 ))
- ){
- err_exit( "\nNot enough memory" );
- }
-
- /* initialize LINE pointers */
-
- (char *) l_end[ 0 ] = (char *)(lines[ 0 ]) + i;
- (char *) l_end[ 1 ] = (char *)(lines[ 1 ]) + i;
-
- for( i = 0; i < 2; ++i ){
-
- lines[i]->num_this
- = lines[i]->num_prev
- = 0;
-
- lines[i]->line_num = 1;
-
- c_inx[i]
- = l_inx[i]
- = lines[ i ];
-
- l_inx[i]->line[0] = '\0';
-
- }
- }
-
- /* ERR_EXIT, CHRPOS */
-
- /*-----------------------------*/
- err_exit( msg ) char *msg;
- /*-----------------------------*/
- {
- printf( msg ); /* tell 'm off */
- exit(0); /* and give up */
- }
-
- /*-------------------------------------------------*/
- unsigned int chrpos(str, c) char *str; char c;
- /*-------------------------------------------------*/
- /* give position of char 'c' in string "str" */
- /* return -1 if not found. Note: length of */
- /* "str" is returned if 'c' is '\0'. */
- {
- register unsigned int i = 0;
-
- do{
- if( str[i] == c )
- return(i);
- }while( str[ i++ ] != '\0' );
-
- return(-1);
- }
- /*---------------------*/
- check_abort()
- /*---------------------*/
- {
- if( (bdos( 6, 0xFF ) & 0xFF) == ('C' & 0x1F ) )
- exit( 0 );
- }
- /*----------------------------------------------*/
- cmp_line( s1, s2 ) register char *s1, *s2; /* Compare two lines */
- /*----------------------------------------------*/
- { static int s1_char, s2_char;
-
- if( strcmp( s1, s2 ) == 0 )
- return TRUE;
-
- if( ! white_space )
- return FALSE;
-
- s1 = p_non_white( s1 );
- s2 = p_non_white( s2 );
-
- while( ((s1_char = *s1) != '\0')
- && ((s2_char = *s2) != '\0')
- ){
- if( (is_white( s1_char ))
- && (is_white( s2_char ))
- ){
- s1 = p_non_white( s1 );
- s2 = p_non_white( s2 );
- }
- else{
- if( s1_char != s2_char )
- return FALSE;
- ++s1;
- ++s2;
- }
- }
- if( *p_non_white( s1 ) == *p_non_white( s2 ))
- return TRUE;
-
- return FALSE;
- }
- /*------------------------------*/
- is_white( c ) char c;
- /*------------------------------*/
- {
- switch( c ){
-
- case ' ':
- case '\t':
- case '\f':
-
- return TRUE;
- }
- return FALSE;
- }
- /*------------------------------------*/
- char *p_non_white( cp ) register char *cp;
- /*------------------------------------*/
- {
- while( is_white( *cp ) )
- ++cp;
- return cp;
- }
- /*------------------------*/
- help()
- /*------------------------*/
- { register char **usage = USAGE;
-
- while( *usage != NULL )
- printf( "%s", *usage++ );
-
- /* printf( CUR_DEFAULT
- * , num_disp
- * , num_cmp
- * , num_buf
- * , (white_space ? ON : OFF)
- * );
- */
- exit(0);
- }
-