conslt32@ZEUS.UNL.EDU (Tim Russell) (08/04/89)
$! ................... Cut between dotted lines and save. ................... $!........................................................................... $! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989. $! $! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from $! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au). $! $! To unpack, simply save, concatinate all parts into one file and $! execute (@) that file. $! $! This archive was created by user CONSLT32 $! on 3-AUG-1989 14:22:05.97. $! $! ATTENTION: To keep each article below 31 blocks (15872 bytes), this $! program has been transmitted in 4 parts. You should $! concatenate ALL parts to ONE file and execute (@) that file. $! $! It contains the following 5 files: $! BUILD_DIFF.COM $! DIFF.C $! DIFF.DOC $! HOW-TO-DIFF.DOC $! README. $! $!============================================================================ $ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL ) $ VERSION = F$GETSYI( "VERSION" ) $ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK $ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", - "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher." $ EXIT 44 ! SS$_ABORT $VERSION_OK: $ GOTO START $! $UNPACK_FILE: $ WRITE SYS$OUTPUT "Creating ''FILE_IS'" $ DEFINE/USER_MODE SYS$OUTPUT NL: $ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION - VMS_SHARE_DUMMY.DUMMY b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) ) ; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE , b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors := 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN & "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION ( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail & LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP ; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK ( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 ) ; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF ; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT ) ; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip := MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip <> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ) ; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) ); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF ; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1 ; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF ; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors := i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT ( "The following line could not be unpacked properly:" ); SPLIT_LINE ; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL ( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH ( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 ); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP ; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION ( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO ( "The following !UL errors were detected while unpacking !AS", i_errors , s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" ) ; ENDIF; EXIT; $ DELETE VMS_SHARE_DUMMY.DUMMY;* $ CHECKSUM 'FILE_IS $ WRITE SYS$OUTPUT " CHECKSUM ", - F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." ) $ RETURN $! $START: $ FILE_IS = "BUILD_DIFF.COM" $ CHECKSUM_IS = 1179721811 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X$ cc diff X$ link/notrace diff,sys$input:/opt Xsys$share:vaxcrtl.exe/share $ GOSUB UNPACK_FILE $ FILE_IS = "DIFF.C" $ CHECKSUM_IS = 1142109466 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* X * diff.c - public domain context diff program X * X * This is pd-diff from comp.sources.misc. X */ X X#ifdef TURBO X#include <alloc.h> X#include <errno.h> X#include <process.h> X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X X#else /* !TURBO */ X#include <stdio.h> X#include <ctype.h> X#endif /* TURBO */ X X#ifdef VMS X#include `009<ssdef.h> X#include `009<stsdef.h> X#define IO_SUCCESS -1 X#define IO_ERROR 1 X#endif /* vms */ X X#define EOS `0090 X#ifdef unix Xchar temfile[L_tmpnam]; Xchar *tmpnam(); X#define TEMPFILE (temfile[0]? temfile: (tmpnam(temfile), temfile)) X#else /* unix */ X#define TEMPFILE "diff.tmp" X#endif /* unix */ X#define TRUE `0091 X#define FALSE `0090 X X#ifdef pdp11 X#define short int X#endif /* pdp11 */ X Xtypedef struct candidate `123 X`009int b;`009`009`009/* Line in fileB `009 */ X`009int a;`009`009`009/* Line in fileA `009 */ X`009int link;`009`009/* Previous candidate `009 */ X`125 CANDIDATE; X Xtypedef struct line `123 X`009unsigned short hash;`009`009/* Hash value etc. `009 */ X`009short serial;`009`009/* Line number `009 */ X`125 LINE; X XLINE *file[2];`009`009/* Hash/line for total file */ X#define fileA file[0] X#define fileB file[1] X XLINE *sfile[2];`009`009/* Hash/line after prefix */ X#define sfileA sfile[0] X#define sfileB sfile[1] X Xint len[2];`009`009`009/* Actual lines in each file */ X#define lenA len[0] X#define lenB len[1] X Xint slen[2];`009`009/* Squished lengths `009 */ X#define slenA slen[0] X#define slenB slen[1] X Xint prefix;`009`009`009/* Identical lines at start */ Xint suffix;`009`009`009/* Identical lenes at end */ X VFILE *infd[2] = `123NULL, NULL`125;`009/* Input file identifiers * X/ XFILE *tempfd;`009`009`009/* Temp for input redirection */ X Xextern long ftell(); Xextern FILE *fopen(); X X#ifdef TURBO Xextern void *malloc(); X#else /* !TURBO */ Xextern char *malloc(); X#endif /* TURBO */ X Xchar *fgetss(); Xunsigned short hash(); X X#ifdef`009AMIGA X/* Define these types for Amiga C */ Xchar *savptr; Xint savsiz; Xchar *wrk; Xchar *wrk2; Xint cpysiz; X#endif /* AMIGA */ X X/* X * The following vectors overlay the area defined by fileA X */ X Xshort *class;`009`009`009/* Unsorted line numbers */ Xint *klist;`009`009`009/* Index of element in clist */ XCANDIDATE *clist;`009`009`009/* Storage pool for candidates */ Xint clength = 0;`009/* Number of active candidates */ V#define`009CSIZE_INC 50`009`009`009/* How many to allocate each time we have X to */ Xint csize = CSIZE_INC;`009`009/* Current size of storage pool */ X Xint *match;`009`009`009/* Longest subsequence `009 */ Xlong *oldseek;`009`009/* Seek position in file A */ X X/* X * The following vectors overlay the area defined by fileB X */ X Xshort *member;`009`009`009/* Concatenated equiv. classes */ Xlong *newseek;`009`009/* Seek position in file B */ Xchar *textb;`009`009`009/* Input from file2 for check */ X X/* X * Global variables X */ X Xint eflag = FALSE;`009/* Edit script requested */ Xint bflag = FALSE;`009/* Blank supress requested */ Xint cflag = FALSE;`009/* Context printout `009 */ Xint iflag = FALSE;`009/* Ignore case requested */ Xchar text[257];`009`009/* Input line from file1 */ Xextern char *myalloc();`009`009/* Storage allocator `009 */ X Xextern char *compact();`009`009/* Storage compactor `009 */ X X#ifdef DEBUG X#ifndef OSK X#define TIMING X#endif /* OSK */ X#endif /* DEBUG */ X#ifdef TIMING Xextern long time(); Xextern char *4532mend; Xlong totaltime; Xlong sectiontime; Xchar *mstart; X#endif /* TIMING */ Xvoid`009`009`009free(); Xvoid`009`009`009exit(); X#ifndef OSK Xvoid`009`009`009perror(); X#endif /* OSK */ X X/* X * Diff main program X */ X Xmain(argc, argv) X`009int argc; X`009char **argv; X`123 X`009register int i; X`009register char *ap; X X#ifdef OSK X`009extern int _memmins; X`009_memmins = 16 * 1024;`009`009/* tell OSK we will malloc a lot */ X#endif /* OSK */ X#ifdef TIMING X`009sectiontime = time(&totaltime); X#endif /* TIMING */ X X`009while (argc > 1 && *(ap = argv[1]) == '-' && *++ap != EOS) `123 X`009`009while (*ap != EOS) `123 X`009`009`009switch ((*ap++)) `123 X`009`009`009case 'b': X`009`009`009`009bflag++; X`009`009`009`009break; X X`009`009`009case 'c': X`009`009`009`009if (*ap > '0' && *ap <= '9') X`009`009`009`009`009cflag = *ap++ - '0'; X`009`009`009`009else X`009`009`009`009`009cflag = 3; X`009`009`009`009break; X X`009`009`009case 'e': X`009`009`009`009eflag++; X`009`009`009`009break; X X`009`009`009case 'i': X`009`009`009`009iflag++; X`009`009`009`009break; X X`009`009`009default: X`009`009`009`009fprintf(stderr, X`009`009`009`009`009`009"Warning, bad option '%c'\n", X`009`009`009`009`009`009ap[-1]); X`009`009`009`009break; X`009`009`009`125 X`009`009`125 X`009`009argc--; X`009`009argv++; X`009`125 X X`009if (argc != 3) X`009`009error("Usage: diff [-options] file1 file2"); X`009if (cflag && eflag) `123 X`009`009fprintf(stderr, X`009`009`009`009"Warning, -c and -e are incompatible, -c supressed.\n"); X`009`009cflag = FALSE; X`009`125 X`009argv++; X`009for (i = 0; i <= 1; i++) `123 X`009`009if (argv[i][0] == '-' && argv[i][1] == EOS) `123 X`009`009`009infd[i] = stdin; X`009`009`009if ((tempfd = fopen(TEMPFILE, "w")) == NULL) X`009`009`009`009cant(TEMPFILE, "work", 1); X`009`009`125 else `123 X`009`009`009infd[i] = fopen(argv[i], "r"); X`009`009`009if (!infd[i]) X`009`009`009`009cant(argv[i], "input", 2);`009`009/* Fatal error */ X`009`009`125 X`009`125 X X`009if (infd[0] == stdin && infd[1] == stdin) X`009`009error("Can't diff two things both on standard input."); X X`009if (infd[0] == NULL && infd[1] == NULL) `123 X`009`009cant(argv[0], "input", 0); X`009`009cant(argv[1], "input", 1); X`009`125 X#ifdef VMS X`009else if (infd[1] == NULL) X`009`009opendir(1, &argv[1], infd[0]); X`009else if (infd[0] == NULL) X`009`009opendir(0, &argv[0], infd[1]); X#endif /* vms */ X X`009/* X`009 * Read input, building hash tables.`032 X`009 */ X`009input(0); X`009input(1); X`009squish(); X#ifdef DEBUG X`009printf("before sort\n"); X`009for (i = 1; i <= slenA; i++) X`009`009printf("sfileA[%d] = %6d %06o\n", X`009`009`009 i, sfileA[i].serial, sfileA[i].hash); X`009for (i = 1; i <= slenB; i++) X`009`009printf("sfileB[%d] = %6d %06o\n", X`009`009`009 i, sfileB[i].serial, sfileB[i].hash); X#endif /* DEBUG */ X`009sort(sfileA, slenA); X`009sort(sfileB, slenB); X#ifdef TIMING X`009ptime("input"); X#endif /* TIMING */ X#ifdef DEBUG X`009printf("after sort\n"); X`009for (i = 1; i <= slenA; i++) X`009`009printf("sfileA[%d] = %6d %06o\n", X`009`009`009 i, sfileA[i].serial, sfileB[i].hash); X`009for (i = 1; i <= slenB; i++) X`009`009printf("sfileB[%d] = %6d %06o\n", X`009`009`009 i, sfileB[i].serial, sfileB[i].hash); X#endif /* DEBUG */ X X`009/* X`009 * Build equivalence classes.`032 X`009 */ X`009member = (short *) fileB; X`009equiv(); X`009member = (short *) compact((char *) member, (slenB + 2) * sizeof(int), X`009`009`009`009`009`009`009 "squeezing member vector"); X X`009/* X`009 * Reorder equivalence classes into array class[]`032 X`009 */ X`009class = (short *) fileA; X`009unsort(); X`009class = (short *) compact((char *) class, (slenA + 2) * sizeof(int), X`009`009`009`009`009`009`009 "compacting class vector"); X#ifdef TIMING X`009ptime("equiv/unsort"); X#endif /* TIMING */ X X`009/* X`009 * Find longest subsequences`032 X`009 */ X`009klist = (int *) myalloc((slenA + 2) * sizeof(int), "klist"); X`009clist = (CANDIDATE *) myalloc(csize * sizeof(CANDIDATE), "clist"); X`009i = subseq(); X#ifndef OSK X`009free((char *) member); X`009free((char *) class); X#else /* OSK */ X`009free((char *) member - sizeof(int)); X`009free((char *) class - sizeof(int)); X#endif /* OSK */ X`009match = (int *) myalloc((lenA + 2) * sizeof(int), "match"); X`009unravel(klist[i]); X#ifndef OSK X`009free((char *) clist); X`009free((char *) klist); X#else /* OSK */ X`009free((char *) clist - sizeof(int)); X`009free((char *) klist - sizeof(int)); X#endif /* OSK */ X#ifdef TIMING X`009ptime("subsequence/unravel"); X#endif /* TIMING */ X X`009/* X`009 * Check for fortuitous matches and output differences`032 X`009 */ X`009oldseek = (long *) myalloc((lenA + 2) * sizeof(*oldseek), "oldseek"); X`009newseek = (long *) myalloc((lenB + 2) * sizeof(*newseek), "newseek"); X`009textb = myalloc(sizeof text, "textbuffer"); X`009if (check(argv[0], argv[1])) X`009`009fprintf(stderr, "Spurious match, output is not optimal\n"); X#ifdef TIMING X`009ptime("check"); X#endif /* TIMING */ X`009output(argv[0], argv[1]); X#ifdef TIMING X`009ptime("output"); X`009printf("%ld seconds required\n", sectiontime - totaltime); X#endif /* TIMING */ X`009if (tempfd != NULL) `123 X`009`009fclose(tempfd); X#ifdef unix X`009`009unlink(TEMPFILE); X#else /* !unix */ X#ifdef OSK X`009`009unlink(TEMPFILE); X#else /* OSK */ X#ifdef MSC`009`009`009`009`009`009/* MSC 4.0 does not understand disjunctive X`009`009`009`009`009`009`009`009 * #if's. */ X`009`009unlink(TEMPFILE); X#else /* MSC */ X`009`009remove(TEMPFILE); X#endif /* MSC */ X#endif /* OSK */ X#endif /* unxi */ X`009`125 X`009return(IO_SUCCESS); X`125 X X X/* X * Read the file, building hash table X */ X Xinput(which) X`009int which;`009`009/* 0 or 1 to redefine infd[] */ X`123 X`009register LINE *lentry; X`009register int linect = 0; X`009FILE *fd; X#define`009LSIZE_INC 200`009`009`009/* # of line entries to alloc at once */ X`009int lsize = LSIZE_INC; X X`009lentry = (LINE *) myalloc(sizeof(LINE) * (lsize + 3), "line"); X`009fd = infd[which]; X`009while (!getline(fd, text)) `123 X`009`009if (++linect >= lsize) `123 X`009`009`009lsize += 200; X`009`009`009lentry = (LINE *) compact((char *) lentry, X`009`009`009`009`009`009`009`009`009 (lsize + 3) * sizeof(LINE), X`009`009`009`009`009`009`009`009`009 "extending line vector"); X`009`009`125 X`009`009lentry[linect].hash = hash(text); X`009`125 X X`009/* X`009 * If input was from stdin ("-" command), finish off the temp file.`032 X`009 */ X`009if (fd == stdin) `123 X`009`009fclose(tempfd); X`009`009tempfd = infd[which] = fopen(TEMPFILE, "r"); X`009`125 X X`009/* X`009 * If we wanted to be stingy with memory, we could realloc lentry down to X`009 * its exact size (+3 for some odd reason) here. No need? `032 -+-+-+-+-+ End of part 1 +-+-+-+-+-
fritz@unocss.UUCP (Tim Russell) (08/27/89)
$! ................... Cut between dotted lines and save. ................... $!........................................................................... $! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989. $! $! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from $! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au). $! $! To unpack, simply save, concatinate all parts into one file and $! execute (@) that file. $! $! This archive was created by user CONSLT32 $! on 3-AUG-1989 14:22:05.97. $! $! ATTENTION: To keep each article below 31 blocks (15872 bytes), this $! program has been transmitted in 4 parts. You should $! concatenate ALL parts to ONE file and execute (@) that file. $! $! It contains the following 5 files: $! BUILD_DIFF.COM $! DIFF.C $! DIFF.DOC $! HOW-TO-DIFF.DOC $! README. $! $!============================================================================ $ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL ) $ VERSION = F$GETSYI( "VERSION" ) $ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK $ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", - "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher." $ EXIT 44 ! SS$_ABORT $VERSION_OK: $ GOTO START $! $UNPACK_FILE: $ WRITE SYS$OUTPUT "Creating ''FILE_IS'" $ DEFINE/USER_MODE SYS$OUTPUT NL: $ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION - VMS_SHARE_DUMMY.DUMMY b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) ) ; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE , b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors := 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN & "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION ( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail & LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP ; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK ( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 ) ; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF ; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT ) ; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip := MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip <> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ) ; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) ); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF ; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1 ; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF ; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors := i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT ( "The following line could not be unpacked properly:" ); SPLIT_LINE ; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL ( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH ( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 ); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP ; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION ( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO ( "The following !UL errors were detected while unpacking !AS", i_errors , s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" ) ; ENDIF; EXIT; $ DELETE VMS_SHARE_DUMMY.DUMMY;* $ CHECKSUM 'FILE_IS $ WRITE SYS$OUTPUT " CHECKSUM ", - F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." ) $ RETURN $! $START: $ FILE_IS = "BUILD_DIFF.COM" $ CHECKSUM_IS = 1179721811 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X$ cc diff X$ link/notrace diff,sys$input:/opt Xsys$share:vaxcrtl.exe/share $ GOSUB UNPACK_FILE $ FILE_IS = "DIFF.C" $ CHECKSUM_IS = 1142109466 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* X * diff.c - public domain context diff program X * X * This is pd-diff from comp.sources.misc. X */ X X#ifdef TURBO X#include <alloc.h> X#include <errno.h> X#include <process.h> X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X X#else /* !TURBO */ X#include <stdio.h> X#include <ctype.h> X#endif /* TURBO */ X X#ifdef VMS X#include `009<ssdef.h> X#include `009<stsdef.h> X#define IO_SUCCESS -1 X#define IO_ERROR 1 X#endif /* vms */ X X#define EOS `0090 X#ifdef unix Xchar temfile[L_tmpnam]; Xchar *tmpnam(); X#define TEMPFILE (temfile[0]? temfile: (tmpnam(temfile), temfile)) X#else /* unix */ X#define TEMPFILE "diff.tmp" X#endif /* unix */ X#define TRUE `0091 X#define FALSE `0090 X X#ifdef pdp11 X#define short int X#endif /* pdp11 */ X Xtypedef struct candidate `123 X`009int b;`009`009`009/* Line in fileB `009 */ X`009int a;`009`009`009/* Line in fileA `009 */ X`009int link;`009`009/* Previous candidate `009 */ X`125 CANDIDATE; X Xtypedef struct line `123 X`009unsigned short hash;`009`009/* Hash value etc. `009 */ X`009short serial;`009`009/* Line number `009 */ X`125 LINE; X XLINE *file[2];`009`009/* Hash/line for total file */ X#define fileA file[0] X#define fileB file[1] X XLINE *sfile[2];`009`009/* Hash/line after prefix */ X#define sfileA sfile[0] X#define sfileB sfile[1] X Xint len[2];`009`009`009/* Actual lines in each file */ X#define lenA len[0] X#define lenB len[1] X Xint slen[2];`009`009/* Squished lengths `009 */ X#define slenA slen[0] X#define slenB slen[1] X Xint prefix;`009`009`009/* Identical lines at start */ Xint suffix;`009`009`009/* Identical lenes at end */ X VFILE *infd[2] = `123NULL, NULL`125;`009/* Input file identifiers * X/ XFILE *tempfd;`009`009`009/* Temp for input redirection */ X Xextern long ftell(); Xextern FILE *fopen(); X X#ifdef TURBO Xextern void *malloc(); X#else /* !TURBO */ Xextern char *malloc(); X#endif /* TURBO */ X Xchar *fgetss(); Xunsigned short hash(); X X#ifdef`009AMIGA X/* Define these types for Amiga C */ Xchar *savptr; Xint savsiz; Xchar *wrk; Xchar *wrk2; Xint cpysiz; X#endif /* AMIGA */ X X/* X * The following vectors overlay the area defined by fileA X */ X Xshort *class;`009`009`009/* Unsorted line numbers */ Xint *klist;`009`009`009/* Index of element in clist */ XCANDIDATE *clist;`009`009`009/* Storage pool for candidates */ Xint clength = 0;`009/* Number of active candidates */ V#define`009CSIZE_INC 50`009`009`009/* How many to allocate each time we have X to */ Xint csize = CSIZE_INC;`009`009/* Current size of storage pool */ X Xint *match;`009`009`009/* Longest subsequence `009 */ Xlong *oldseek;`009`009/* Seek position in file A */ X X/* X * The following vectors overlay the area defined by fileB X */ X Xshort *member;`009`009`009/* Concatenated equiv. classes */ Xlong *newseek;`009`009/* Seek position in file B */ Xchar *textb;`009`009`009/* Input from file2 for check */ X X/* X * Global variables X */ X Xint eflag = FALSE;`009/* Edit script requested */ Xint bflag = FALSE;`009/* Blank supress requested */ Xint cflag = FALSE;`009/* Context printout `009 */ Xint iflag = FALSE;`009/* Ignore case requested */ Xchar text[257];`009`009/* Input line from file1 */ Xextern char *myalloc();`009`009/* Storage allocator `009 */ X Xextern char *compact();`009`009/* Storage compactor `009 */ X X#ifdef DEBUG X#ifndef OSK X#define TIMING X#endif /* OSK */ X#endif /* DEBUG */ X#ifdef TIMING Xextern long time(); Xextern char *4532mend; Xlong totaltime; Xlong sectiontime; Xchar *mstart; X#endif /* TIMING */ Xvoid`009`009`009free(); Xvoid`009`009`009exit(); X#ifndef OSK Xvoid`009`009`009perror(); X#endif /* OSK */ X X/* X * Diff main program X */ X Xmain(argc, argv) X`009int argc; X`009char **argv; X`123 X`009register int i; X`009register char *ap; X X#ifdef OSK X`009extern int _memmins; X`009_memmins = 16 * 1024;`009`009/* tell OSK we will malloc a lot */ X#endif /* OSK */ X#ifdef TIMING X`009sectiontime = time(&totaltime); X#endif /* TIMING */ X X`009while (argc > 1 && *(ap = argv[1]) == '-' && *++ap != EOS) `123 X`009`009while (*ap != EOS) `123 X`009`009`009switch ((*ap++)) `123 X`009`009`009case 'b': X`009`009`009`009bflag++; X`009`009`009`009break; X X`009`009`009case 'c': X`009`009`009`009if (*ap > '0' && *ap <= '9') X`009`009`009`009`009cflag = *ap++ - '0'; X`009`009`009`009else X`009`009`009`009`009cflag = 3; X`009`009`009`009break; X X`009`009`009case 'e': X`009`009`009`009eflag++; X`009`009`009`009break; X X`009`009`009case 'i': X`009`009`009`009iflag++; X`009`009`009`009break; X X`009`009`009default: X`009`009`009`009fprintf(stderr, X`009`009`009`009`009`009"Warning, bad option '%c'\n", X`009`009`009`009`009`009ap[-1]); X`009`009`009`009break; X`009`009`009`125 X`009`009`125 X`009`009argc--; X`009`009argv++; X`009`125 X X`009if (argc != 3) X`009`009error("Usage: diff [-options] file1 file2"); X`009if (cflag && eflag) `123 X`009`009fprintf(stderr, X`009`009`009`009"Warning, -c and -e are incompatible, -c supressed.\n"); X`009`009cflag = FALSE; X`009`125 X`009argv++; X`009for (i = 0; i <= 1; i++) `123 X`009`009if (argv[i][0] == '-' && argv[i][1] == EOS) `123 X`009`009`009infd[i] = stdin; X`009`009`009if ((tempfd = fopen(TEMPFILE, "w")) == NULL) X`009`009`009`009cant(TEMPFILE, "work", 1); X`009`009`125 else `123 X`009`009`009infd[i] = fopen(argv[i], "r"); X`009`009`009if (!infd[i]) X`009`009`009`009cant(argv[i], "input", 2);`009`009/* Fatal error */ X`009`009`125 X`009`125 X X`009if (infd[0] == stdin && infd[1] == stdin) X`009`009error("Can't diff two things both on standard input."); X X`009if (infd[0] == NULL && infd[1] == NULL) `123 X`009`009cant(argv[0], "input", 0); X`009`009cant(argv[1], "input", 1); X`009`125 X#ifdef VMS X`009else if (infd[1] == NULL) X`009`009opendir(1, &argv[1], infd[0]); X`009else if (infd[0] == NULL) X`009`009opendir(0, &argv[0], infd[1]); X#endif /* vms */ X X`009/* X`009 * Read input, building hash tables.`032 X`009 */ X`009input(0); X`009input(1); X`009squish(); X#ifdef DEBUG X`009printf("before sort\n"); X`009for (i = 1; i <= slenA; i++) X`009`009printf("sfileA[%d] = %6d %06o\n", X`009`009`009 i, sfileA[i].serial, sfileA[i].hash); X`009for (i = 1; i <= slenB; i++) X`009`009printf("sfileB[%d] = %6d %06o\n", X`009`009`009 i, sfileB[i].serial, sfileB[i].hash); X#endif /* DEBUG */ X`009sort(sfileA, slenA); X`009sort(sfileB, slenB); X#ifdef TIMING X`009ptime("input"); X#endif /* TIMING */ X#ifdef DEBUG X`009printf("after sort\n"); X`009for (i = 1; i <= slenA; i++) X`009`009printf("sfileA[%d] = %6d %06o\n", X`009`009`009 i, sfileA[i].serial, sfileB[i].hash); X`009for (i = 1; i <= slenB; i++) X`009`009printf("sfileB[%d] = %6d %06o\n", X`009`009`009 i, sfileB[i].serial, sfileB[i].hash); X#endif /* DEBUG */ X X`009/* X`009 * Build equivalence classes.`032 X`009 */ X`009member = (short *) fileB; X`009equiv(); X`009member = (short *) compact((char *) member, (slenB + 2) * sizeof(int), X`009`009`009`009`009`009`009 "squeezing member vector"); X X`009/* X`009 * Reorder equivalence classes into array class[]`032 X`009 */ X`009class = (short *) fileA; X`009unsort(); X`009class = (short *) compact((char *) class, (slenA + 2) * sizeof(int), X`009`009`009`009`009`009`009 "compacting class vector"); X#ifdef TIMING X`009ptime("equiv/unsort"); X#endif /* TIMING */ X X`009/* X`009 * Find longest subsequences`032 X`009 */ X`009klist = (int *) myalloc((slenA + 2) * sizeof(int), "klist"); X`009clist = (CANDIDATE *) myalloc(csize * sizeof(CANDIDATE), "clist"); X`009i = subseq(); X#ifndef OSK X`009free((char *) member); X`009free((char *) class); X#else /* OSK */ X`009free((char *) member - sizeof(int)); X`009free((char *) class - sizeof(int)); X#endif /* OSK */ X`009match = (int *) myalloc((lenA + 2) * sizeof(int), "match"); X`009unravel(klist[i]); X#ifndef OSK X`009free((char *) clist); X`009free((char *) klist); X#else /* OSK */ X`009free((char *) clist - sizeof(int)); X`009free((char *) klist - sizeof(int)); X#endif /* OSK */ X#ifdef TIMING X`009ptime("subsequence/unravel"); X#endif /* TIMING */ X X`009/* X`009 * Check for fortuitous matches and output differences`032 X`009 */ X`009oldseek = (long *) myalloc((lenA + 2) * sizeof(*oldseek), "oldseek"); X`009newseek = (long *) myalloc((lenB + 2) * sizeof(*newseek), "newseek"); X`009textb = myalloc(sizeof text, "textbuffer"); X`009if (check(argv[0], argv[1])) X`009`009fprintf(stderr, "Spurious match, output is not optimal\n"); X#ifdef TIMING X`009ptime("check"); X#endif /* TIMING */ X`009output(argv[0], argv[1]); X#ifdef TIMING X`009ptime("output"); X`009printf("%ld seconds required\n", sectiontime - totaltime); X#endif /* TIMING */ X`009if (tempfd != NULL) `123 X`009`009fclose(tempfd); X#ifdef unix X`009`009unlink(TEMPFILE); X#else /* !unix */ X#ifdef OSK X`009`009unlink(TEMPFILE); X#else /* OSK */ X#ifdef MSC`009`009`009`009`009`009/* MSC 4.0 does not understand disjunctive X`009`009`009`009`009`009`009`009 * #if's. */ X`009`009unlink(TEMPFILE); X#else /* MSC */ X`009`009remove(TEMPFILE); X#endif /* MSC */ X#endif /* OSK */ X#endif /* unxi */ X`009`125 X`009return(IO_SUCCESS); X`125 X X X/* X * Read the file, building hash table X */ X Xinput(which) X`009int which;`009`009/* 0 or 1 to redefine infd[] */ X`123 X`009register LINE *lentry; X`009register int linect = 0; X`009FILE *fd; X#define`009LSIZE_INC 200`009`009`009/* # of line entries to alloc at once */ X`009int lsize = LSIZE_INC; X X`009lentry = (LINE *) myalloc(sizeof(LINE) * (lsize + 3), "line"); X`009fd = infd[which]; X`009while (!getline(fd, text)) `123 X`009`009if (++linect >= lsize) `123 X`009`009`009lsize += 200; X`009`009`009lentry = (LINE *) compact((char *) lentry, X`009`009`009`009`009`009`009`009`009 (lsize + 3) * sizeof(LINE), X`009`009`009`009`009`009`009`009`009 "extending line vector"); X`009`009`125 X`009`009lentry[linect].hash = hash(text); X`009`125 X X`009/* X`009 * If input was from stdin ("-" command), finish off the temp file.`032 X`009 */ X`009if (fd == stdin) `123 X`009`009fclose(tempfd); X`009`009tempfd = infd[which] = fopen(TEMPFILE, "r"); X`009`125 X X`009/* X`009 * If we wanted to be stingy with memory, we could realloc lentry down to X`009 * its exact size (+3 for some odd reason) here. No need? `032 -+-+-+-+-+ End of part 1 +-+-+-+-+- -- ---------------------------------+-------------------------------------------- Tim Russell, Computer Operator | Internet: russell@zeus.unl.edu Campus Computing | Bitnet: russell@unoma1 University of Nebraska at Omaha | UUCP: uunet!zeus.unl.edu!russell