[news.software.anu-news] diff part 1 of 4

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