From: MERC::"uunet!crdgw1.ge.com!root" 20-APR-1992 00:33:44.91 To: everhart CC: Subj: Announcing DX v2.3, a VAX/VMS directory browser/editor From: RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2 To: Everhart@Arisia@MRGATE Received: by crdgw1.ge.com (5.57/GE 1.139) id AA12157; Sun, 19 Apr 92 16:33:46 EDT Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Sun, 19 APR 92 11:52:03 PDT Received: by ucbvax.Berkeley.EDU (5.63/1.43) id AA06445; Sun, 19 Apr 92 11:07:16 -0700 Received: from USENET by ucbvax.Berkeley.EDU with netnews for info-vax@kl.sri.com (info-vax@kl.sri.com) (contact usenet@ucbvax.Berkeley.EDU if you have questions) Date: 17 Apr 92 05:54:24 GMT From: oracle!unrepliable!bounce@decwrl.dec.com (Chau-Kuang Hung) Organization: Oracle Corporation, Belmont, CA Subject: Announcing DX v2.3, a VAX/VMS directory browser/editor Message-Id: Sender: info-vax-request@kl.sri.com To: info-vax@kl.sri.com DX (Directory eXtension) is a VAX/VMS utility that performs various file operations on a VT100 or upper terminals. It allows you to delete, type, copy, set protection, compare, and edit one or many of the files in a single directory at once. DX is an customizable, flexible, real-time directory browser/editor. You can also open multiple windows on the the same or different directories. DX provides the following main features: o Flexible display and sorting o Pull-down menu for point-and-shoot interface o Display sub-directories and directory contents with flexible "filters" o Multiple inclusion/exclusion patterns in file operations o Multiple windows provides different views o Display a tree-like directory structure in a scrollable window Please direct all comments, suggestions, and bugs to Chau-Kuang Hung (chung@appseq.us.oracle.com) Oracle Corporation 300 Oracle Parkway BOX 659304 Redwood Shores, CA 94065 $! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 16-APR-1992 14:38:21.40 By user HWU $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 25 PARTS, TO KEEP EACH PART $! BELOW 60 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. AAAREAD.ME;23 $! 2. DIFF.C;23 $! 3. DIFF.H;23 $! 4. DIRECT.C;23 $! 5. DIRECT.H;23 $! 6. DIRECTKPD.C;23 $! 7. DIRECTKPD.H;23 $! 8. DIRECTQUE.C;23 $! 9. DIRECTQUE.H;23 $! 10. DX$BUILD.COM;23 $! 11. DX$STARTUP.DAT;23 $! 12. DX.C;23 $! 13. DX.CLD;23 $! 14. DX.H;23 $! 15. ENDECODE.C;23 $! 16. ENDECODE.H;23 $! 17. FILER.C;23 $! 18. FILER.H;23 $! 19. FILERAPP.C;23 $! 20. FILERAPP.H;23 $! 21. FILERCPY.C;23 $! 22. FILERCPY.H;23 $! 23. FILERCUS.C;23 $! 24. FILERCUS.H;23 $! 25. FILERDEC.C;23 $! 26. FILERDEC.H;23 $! 27. FILERDEL.C;23 $! 28. FILERDEL.H;23 $! 29. FILERDIF.C;23 $! 30. FILERDIF.H;23 $! 31. FILEREDT.C;23 $! 32. FILEREDT.H;23 $! 33. FILERENC.C;23 $! 34. FILERENC.H;23 $! 35. FILEREXE.C;23 $! 36. FILEREXE.H;23 $! 37. FILERFLT.C;23 $! 38. FILERFLT.H;23 $! 39. FILERFND.C;23 $! 40. FILERFND.H;23 $! 41. FILERKPD.C;23 $! 42. FILERKPD.H;23 $! 43. FILERLAU.C;23 $! 44. FILERLAU.H;23 $! 45. FILEROPT.C;23 $! 46. FILEROPT.H;23 $! 47. FILERPRO.C;23 $! 48. FILERPRO.H;23 $! 49. FILERPRT.C;23 $! 50. FILERPRT.H;23 $! 51. FILERPUR.C;23 $! 52. FILERPUR.H;23 $! 53. FILERQUE.C;23 $! 54. FILERQUE.H;23 $! 55. FILERREN.C;23 $! 56. FILERREN.H;23 $! 57. FILERSRT.C;23 $! 58. FILERSRT.H;23 $! 59. FILERSTA.C;23 $! 60. FILERSTA.H;23 $! 61. FILERTYP.C;23 $! 62. FILERTYP.H;23 $! 63. FILERWIN.C;23 $! 64. FILERWIN.H;23 $! 65. FINDFILE.C;23 $! 66. FINDFILE.H;23 $! 67. GLOBAL.H;23 $! 68. INQUIRE.C;23 $! 69. INQUIRE.H;23 $! 70. MENUNAVI.C;23 $! 71. MENUNAVI.H;23 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' XPRODUCT NAME XDX (Directory eXtension), Version 2.3 X X XGENERAL DESCRIPTION XDX is a VAX/VMS utility that performs many file operations on a VT100`20 Xor upper type terminal. It can be used to delete, edit, or rename Xfiles in the current directory. DX can also create a hardcopy listing`20 Xof all the files displayed. X X XFEATURES X Xo Flexible display and sorting X Xo Pull-down menu for point-and-shoot interface X Xo Display sub-directories and directory contents with flexible "filters" X Xo Multiple inclusion/exclusion patterns in file operations X Xo Multiple windows provides different views X Xo Display a tree-like directory structure in a scrollable window X X XSOURCE FILES XThis directory holds the latest distribution version of DX. It includes Xthe following files: X X`09AAAREAD.ME`09DX_BUILD.COM`09DX.COM`09`09DX.CLD X`09DX.HLP`09`09DIRECT.C`09DIRECT.H`09DIRECTKPD.C X`09DIRECTKPD.H`09DIRECTQUE.C`09DIRECTQUE.H`09DIFF.C X`09DIFF.H`09`09DX.C`09`09DX.H`09`09ENDECODE.C X`09ENDECODE.H`09FILER.C`09`09FILER.H`09`09FILERAPP.C X`09FILERAPP.H`09FILERCPY.C`09FILERCPY.H`09FILERCUS.C X`09FILERCUS.H`09FILERDEC.C`09FILERDEC.H`09FILERDEL.C X`09FILERDEL.H`09FILERDIF.C`09FILERDIF.H`09FILEREDT.C X`09FILEREDT.H`09FILERENC.C`09FILERENC.H`09FILEREXE.C X`09FILEREXE.H`09FILERFLT.C`09FILERFLT.H`09FILREFND.C X`09FILREFND.H`09FILERKPD.C`09FILERKPD.H`09FILERLAU.C X`09FILERLAU.H`09FILERPRO.C`09FILERPRO.H`09FILERPRT.C X`09FILERPRT.H`09FILERPUR.C`09FILERPUR.H`09FILEROPT.C X`09FILEROPT.H`09FILERQUE.C`09FILERQUE.H`09FILERREN.C X`09FILERREN.H`09FILERSTA.C`09FILERSTA.H`09FILERSRT.C X`09FILERSRT.H`09FILERTYP.C`09FILERTYP.H`09FILERWIN.C X`09FILERWIN.H`09FINDFILE.C`09FINDFILE.H`09INQUIRE.C X`09INQUIRE.H`09MENUNAVI.C`09MENUNAVI.H`09GLOBAL.H X`09DX$STARTUP.DAT X XThe file `60dx_build.com' helps automate the process of building and`20 Xinstalling DX. `20 X XThe file `60dx.com' in this directory defines logical names and commands`20 Xsuch as `60DX', so you must edit it to specify the file and directory names` V20 Xused. This file must be executed in each session to enable you to run Xthe installed DX. Also, `60dx.com' use the file `60dx.cld' which contains t Vhe`20 Xcommand definitions (i.e. command parameters and qualifiers) for DX. X XThe file `60dx$startup.dat' is an init file that is loaded from your home Xdirectory when DX starts. It is a text file that can be viewed or changed Xusing any editor. `20 X XPlease direct all comments, suggestions, and bugs to X X Chau-Kuang Hung (chung@us.oracle.com) X Oracle Corporation X 300 Oracle Parkway X BOX 659304 X Redwood Shores, CA 94065 X $ CALL UNPACK AAAREAD.ME;23 2914859 $ create 'f' X/* X**++ X** FACILITY: DIFF.C X** X** MODULE DESCRIPTION: X** X** This module compares two arrays of lines (representing X**`09files) and reports the sequences of consecutive matching X**`09lines between them using the "recursive longest matching X**`09sequence" algorithm. `20 X** X** AUTHORS: X**`09Steppe, Tom. "File Comparison Algorithms." Dr. Dobb's`20 X**`09Journal, #131 (Sep 1987): 54-60. X** X** CREATION DATE: 2-21-1991 X** X** X** MODIFICATION HISTORY: X** X** `7B@tbs@`7D... X**-- X*/ X X X/* X** X** INCLUDE FILES X** X*/ X#ifdef vax11c X#include stdio X#include ctype X#include string X#include stdlib X#include rms X#include descrip X#include "diff.h" X#else X#include X#include X#include X#include X#include "diff.h" X#endif X X X/* X** X** MACRO DEFINITIONS X** X*/ X X#define TRUE`091 X#define FALSE`090 X X/** Maximum and Minimum macro **/ X#define max(x, y)`09(((x) > (y)) ? (x) : (y)) X#define min(x, y)`09(((x) < (y)) ? (x) : (y)) X X/** Value to indicate identical strings with strcmp **/ X#define ALIKE`090 X X/** Mask for number of bits in hash code (12 bits) **/ X#define MASK`09(unsigned int) 0x0FFFF X X/** Number of possible hash codes **/ X#define HASHSIZ`09(MASK+1) X X/* X** X** GLOBAL DECLARATIONS X** X**/ X Xint diff_sec, `09`09 /** Number of diff sections **/ X diff_line; `09`09 /** Number of diff lines **/ X Xint diff_beg1, `09`09 /** First line# for diff sec in file 1 **/ X diff_beg2; `09`09 /** First line# for diff sec in file 2 **/ X X/* X** X** INTERNAL FUNCTION PROTOTYPE DECLARATIONS X** X**/ X Xstatic BOOLEAN get_inf (char *, TXTINF *, int, FILEINF *); Xstatic HASH calc_hash (TXTINF); Xstatic void fnd_seq (FILEINF *, int, int, FILEINF *, int, int, int); Xstatic BOOLEAN chk_hashes (LINEINF *, LINEINF *, int); Xstatic int cnt_matches (TXTINF *, TXTINF *, int); Xstatic void rpt_seq (FILEINF *, int, FILEINF *, int, int); Xstatic void rpt_seq_1 (FILEINF *, int, int, FILEINF *, int, int); X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** compare() compares two arrays of lines and reports the X**`09sequences of consecutive matching lines. The zeroth X**`09element of each array is unused so that the index into X**`09the array is identical to the associated line number. X** X** RETURN VALUE: X** X** TRUE if comparison succeeded. X**`09FALSE if not enough memory. X** X**-- X*/ XBOOLEAN compare (r1, a1, n1, r2, a2, n2, lngval) Xchar *r1;`09/** File name for #1 **/ XTXTINF *a1;`09/** Array of lines of text in #1 **/ Xint n1;`09`09/** Number of lines in a1 (does not count 0th element) **/ Xchar *r2;`09/** File name for #2 **/ XTXTINF *a2;`09/** Array of lines of text in #2 **/ Xint n2;`09`09/** Number of lines in a2 (does not count 0th element) **/ Xint lngval;`09/** "Long enough" value **/ X`7B X FILEINF f1,`09`09/** File info for #1 **/ X`09 f2;`09`09/** File info for #2 **/ X BOOLEAN rtn;`09/** Return value **/ X X /** Initialize **/ X diff_sec = diff_line = 0; X diff_beg1 = diff_beg2 = 0; X X /** Gather info for each file, then compare **/ X if (rtn = (get_inf (r1, a1, n1, &f1) && get_inf (r2, a2, n2, &f2))) X `7B X fnd_seq (&f1, 1, n1, &f2, 1, n2, lngval); X `7D X X /** Output remaining difference lines **/ X if (!(diff_beg1 == n1 && diff_beg2 == n2)) X `7B X `09rpt_seq_1 (&f1, n1, n1-diff_beg1, &f2, n2, n2-diff_beg2); X`09diff_line++; X `7D X `20 X /** Output summary report **/ X fprintf (stdout, "\nNumber of difference sections found: %d\n", diff_sec V); X fprintf (stdout, "Number of difference records found: %d\n", diff_line); X X /** Return dynamic memory to pool **/ X free (f1.line);`09free (f1.hashtbl); X free (f2.line);`09free (f2.hashtbl); X X return rtn; X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** get_inf() calculates hash codes and builds a hash table X** X** X** RETURN VALUE: X** X** TRUE if get_inf() succeeded. X**`09FALSE if not enough memory. X** X**-- X*/ Xstatic BOOLEAN get_inf (r, a, n, f) Xchar *r;`09 /** File name **/ XTXTINF *a;`09 /** Array of lines of text **/ Xint n;`09`09 /** Number of lines in a **/ XFILEINF *f;`09 /** File info **/ X`7B X unsigned int size;`09`09/** Size of hash table **/ X register int i;`09`09/** Counter **/ X TBLENTRY *entry;`09`09/** Entry in hash table **/ X X f->filename = r;`09/** Assign the file name **/ X f->txt = a;`09`09/** Assign the array of text **/ X `20 X /** Allocate and initialize a hash table **/ X size = HASHSIZ * sizeof (TBLENTRY); X if (f->hashtbl = (TBLENTRY *) malloc (size)) X `7B X memset ((char *) f->hashtbl, '\0', size); X `7D X else X `7B X return (FALSE); X `7D X if (n <= 0) X `7B`09/** There is no lines **/ X f->line = NULL; X `7D X else X `7B X /** Allocate an array of line structs **/ X if ((f->line =`20 X`09`09(LINEINF *) malloc ((n+1) * sizeof (LINEINF))) == NULL) X `7B X return (FALSE); X `7D X for (i = 1; i <= n; i++) X `7B /** Loop through the lines **/ X f->line`5Bi`5D.hash = calc_hash (f->txt`5Bi`5D);`09/** Calculat Ve hash **/ X`09 entry = f->hashtbl + f->line`5Bi`5D.hash;`09/** Locate entry **/ X X`09 /** Update the linked list of lines iwth the same hash code **/ X`09 f->line`5Bentry->last`5D.nxtln = i; X`09 f->line`5Bi`5D.nxtln = 0; X X`09 /** Update the first and last line info in the hash table **/ X if (entry->frst == 0) X `7B X entry->frst = i; X `7D X entry->last = i; X `7D X `7D X return (TRUE); X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** calc_hash() calculates a hash code for a line of text. X** X** RETURN VALUE: X** X** a hash code value. X** X**-- X*/ Xstatic HASH calc_hash (buf) XTXTINF buf;`09/** Line of text **/ X`7B X register unsigned int chksum; /** Checksum **/ X register int`09 i;`09 /** Counter **/ X char`09`09 *s;`09 /** Pointer **/ X HASH`09`09 hash;`09 /** Hash code value **/ X X /** Build up a checksum of the characters in the text **/ X for (chksum = 0, s = buf.content, i = 0; i < buf.len; chksum `5E= *s++ V, i++) X `7B X ; X `7D X X /** Combine the 7-bit checksum and as much of the length as is possible V **/ X hash = ((chksum & 0x7F) `7C ((s - buf.content) << 7)) & MASK; X `20 X return (hash); X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** fnd_seq() finds a "good sequence" of lines within the given X**`09starting and ending line numbers. fnd_seq() then recursively X**`09finds "good sequences" in the sections of lines above the X**`09"good sequence" and below it. X** X** RETURN VALUE: X** X** none X** X**-- X*/ Xstatic void fnd_seq (f1, beg1, end1, f2, beg2, end2, lngval) XFILEINF`09 *f1;`09/** File info for #1 **/ Xint`09 beg1;`09/** First line # to compare in #1 **/ Xint`09 end1;`09/** Last line # to compare in #1 **/ XFILEINF *f2; /** File info for #2 **/ Xint beg2; /** First line # to compare in #2 **/ Xint end2; /** Last line # to compare in #2 **/ Xint`09 lngval;`09/** "Long enough" value **/ X`7B X LINEINF *line1,`09/** Line info ptr in #1 **/ X`09 *line2;`09/** Line info ptr in #2 **/ X register int limit;`09/** Looping limit **/ X int`09 ln1,`09/** Line number in #1 **/ X`09 ln2;`09/** Line number in #2 **/ X register int ln;`09/** Working line number **/ X BOOLEAN go;`09`09/** Continue to loop? **/ X int most,`09`09/** Longest possible seq **/ X`09most1,`09`09/** Longest possible due to #1 **/ X`09most2;`09`09/** Longest possible due to #2 **/ X int cnt,`09`09/** Length of longest seq **/ X`09oldcnt,`09`09/** Length of prev longest seq **/ X`09n,`09`09/** Length of cur longest seq **/ X`09m1,`09`09/** Line of longest seq in #1 **/ X m2; /** Line of longest seq in #2 **/ X X /** Initialize **/ X go = TRUE; X line1 = f1->line; X line2 = f2->line; X `20 X /** Initialize longest sequence info **/ X cnt = 0;`09`09/** Length of longest seq **/ X m1 = beg1 - 1;`09/** Line # of longest seq in #1 **/ X m2 = beg2 - 1; /** Line # of longest seq in #2 **/ X oldcnt = 0;`09`09/** Length of prev longest seq **/ X `20 X /* X ** Calculate max possible number of consecutive lines that X **`09can match (based on line # range) X **/ X most1 = end1 - beg1 + 1; X most2 = end2 - beg2 + 1; X `20 X /* X **`09Scan lines looking for a "good sequence". X **`09Compare lines in the following order of line numbers: X ** X **`09`09`09 (1, 1) X **`09`09 (1, 2), (2, 1), (2, 2) X **`09 (1, 3), (2, 3), (3, 1), (3, 2), (3, 3) X **`09`09`09 ... X **/ X for (ln1 = beg1, ln2 = beg2; TRUE; ln1++, ln2++) X `7B X if (ln2 <= end2 - cnt) X`09 /* X`09 **`09There are enough lines left in #2 such that it X`09 **`09is possible to find a longer sequence. X`09 **/ X`09`7B X /* X`09 ** Determine the limit in #1 that both X`09 **`09enforces the order scheme and still makes X`09 **`09it possible to find a longer sequence. X`09 **/ X`09 limit = min (ln1 - 1, end1 - cnt); X`09 `20 X`09 /** Calculate first potential match in #1 **/ X for (ln = f1->hashtbl`5Bline2`5Bln2`5D.hash`5D.frst; `20 X`09`09 ln && ln < beg1; ln = line1`5Bln`5D.nxtln) X `7B X ; X `7D X`09 `20 X`09 /** Loop through the lines in #1 **/ X for (; ln && ln <= limit; ln = line1`5Bln`5D.nxtln) X `7B X if (line1`5Bln`5D.hash == line2`5Bln2`5D.hash && X`09`09 line1`5Bln+cnt`5D.hash == line2`5Bln2+cnt`5D.hash && X`09`09 !(ln-m1 == ln2-m2 && ln < m1+cnt && m1 != beg1-1)) X `7B /* X`09`09 ** A candidate for a longer sequence has been found`20 X`09`09 ** The current lines match, the currents + cnt match, X`09`09 **`09and this sequence is not a subset of the longest X`09`09 ** sequence so far. X`09`09 **/ X X /** Calculate most possible matches **/ X most = min (end1-ln+1, most2);`20 X`09`09 `20 X`09`09 /* X`09`09 **`09First compare hash codes. If the number of matches X`09`09 **`09exceeds the longest sequence so far, then compare X`09`09 **`09the actual text. X`09`09 **/ X if (chk_hashes(line1+ln, line2+ln2, cnt) && X`09`09`09(n = cnt_matches (f1->txt+ln, f2->txt+ln2, most)) > cnt) X `7B`09/** This is the longest seq. so far **/ X /** Update longest seq info **/ X`09`09`09oldcnt = cnt; X`09`09`09cnt = n; X`09`09`09m1 = ln; X`09`09`09m2 = ln2; X X`09`09`09/** If it's long enough, end the search **/ X if (cnt >= lngval) X `7B X break; X `7D X`09`09`09 X`09`09`09/** Update limit, using new count **/ X`09`09`09limit = min (ln1 - 1, end1 - cnt); X `7D X `7D X `7D X`09 /** If it's long enough, end the search **/ X if (cnt >= lngval) X `7B X break; X `7D X`09 most2--; X `7D X else X `7B X go = FALSE;`09 /** EOF of this is reached **/ X `7D X`09 X`09/** Repeat the process for the other file **/ X if (ln1 <= end1 - cnt) X `7B X limit = min (ln2, end2 - cnt); X for (ln = f2->hashtbl`5Bline1`5Bln1`5D.hash`5D.frst; `20 X`09`09 ln && ln < beg2; ln = line2`5Bln`5D.nxtln) X `7B X ; X `7D X for (; ln && ln <= limit; ln = line2`5Bln`5D.nxtln) X `7B X if (line1`5Bln1`5D.hash == line2`5Bln`5D.hash && X`09`09 line1`5Bln1+cnt`5D.hash == line2`5Bln+cnt`5D.hash && X`09`09 !(ln1-m1 == ln-m2 && ln1 < m1+cnt && m2 != beg2-1)) X `7B X most = min (end2 - ln + 1, most1); X if (chk_hashes (line1 + ln1, line2 + ln, cnt) && X`09`09`09(n = cnt_matches (f1->txt + ln1, X`09`09`09`09`09 f2->txt + ln, most)) > cnt) X `7B X oldcnt = cnt; X`09`09`09cnt = n; X`09`09`09m1 = ln1; X`09`09`09m2 = ln; X`09`09`09 X if (cnt >= lngval) X `7B X break; X `7D X`09`09`09limit = min (ln2, end2 - cnt); X `7D X `7D X `7D X if (cnt >= lngval) X `7B X break; X `7D X`09 most1--; X `7D X else if (!go) X `7B X break;`09/** EOF of this file is reached **/ X `7D X `7D X `20 X /* X ** If the longest seq is shorter than the "long engoug" value, X **`09the "long enough" value can be adjusted for the rest of X **`09the comparison process. X **/ X if (cnt < lngval) X `7B X lngval = cnt; X `7D X `20 X if (cnt >= 1)`09/** Longest seq exceeds min necessary size **/ X `7B X if (m1 != beg1 && m2 != beg2 && oldcnt > 0) X`09 /* X`09 **`09There is still something worgh comparing previous to X`09 **`09the seq. X`09 **/ X `7B X /** Use knowledge of the previous longest seq **/ X`09 fnd_seq (f1, beg1, m1 - 1, f2, beg2, m2 - 1, oldcnt); X `7D X`09 X`09/** Report the seq **/ X`09rpt_seq (f1, m1, f2, m2, cnt); X`09 X if (m1 + cnt - 1 != end1 && m2 + cnt - 1 != end2) X`09 /** There is still someghing worth comparing subseq to the seq **/ X `7B X fnd_seq (f1, m1 + cnt, end1, f2, m2 + cnt, end2, lngval); X `7D X `7D X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** chk_hashes() determines whether this seq of matching X**`09hash codes is longer than cnt. It knows that the first X**`09pair of hash codes is guaranteed to match. X** X** RETURN VALUE: X** X** TRUE if this seq is longer than cnt. X**`09FALSE if this seq is not longer than cnt. X** X**-- X*/ Xstatic BOOLEAN chk_hashes (line1, line2, cnt) XLINEINF`09 *line1,`09 /** Line info for #1 **/ X`09 *line2;`09 /** Line info for #2 **/ Xregister int cnt;`09 /** Counter to try to exceed **/ X`7B X register int n;`09 /** Counter of consecutive matches **/ X X for (n = 1; n <= cnt && (++line1)->hash == (++line2)->hash; n++) X `7B X ; X `7D X return (n > cnt); X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** cnt_matches() counts the numbner of consecutive matching X**`09lines of text. X** X** RETURN VALUE: X** X** Number of consecutive matching lines. X** X**-- X*/ Xstatic int cnt_matches (s1, s2, most) XTXTINF *s1,`09`09/** Starting line in file #1 **/ X *s2;`09`09/** Starting line in file #2 **/ Xregister int most;`09/** Most matching lines possible **/ X`7B X register int n;`09/** Count of consecutive matches **/ X X /** Count the consecutive matches **/ X for (n = 0; n < most && txtcmp (*s1++, *s2++) == ALIKE; n++) X `7B X ; X `7D X return (n); X`7D X Xint txtcmp (s, t) XTXTINF s, X t; X`7B X register int i; X int c; X X if (s.len > t.len) X `7B X `09return 1; X `7D else if (s.len < t.len) X `7B X`09return -1; X `7D else`20 X `7B X`09for (i = 0; i < s.len; i++) X`09`7B X`09 if ((c = s.content`5Bi`5D-t.content`5Bi`5D)) X`09 `7B X`09 `09 return (c > 0? 1 : -1); X`09 `7D X`09`7D X `7D X return 0; X`7D X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** rpt_seq() reports a matching seq of lines X** X** RETURN VALUE: X** X** None X** X**-- X*/ Xstatic void rpt_seq (f1, m1, f2, m2, cnt) XFILEINF`09 *f1;`09/** File info for #1 **/ Xint`09 m1;`09`09/** Location of matching seq in #1 **/ XFILEINF *f2; /** File info for #2 **/ Xint`09 m2;`09`09/** Location of matching seq in #2 **/ Xint`09 cnt;`09/** Number of lines in matching seq **/ X`7B X if (!(m1 == 1 && m2 == 1)) X `7B X`09rpt_seq_1 (f1, m1, cnt, f2, m2, cnt); X `7D X X diff_beg1 = m1+cnt-1; X diff_beg2 = m2+cnt-1; X`7D X X X`0C X/* X**++ X** FUNCTIONAL DESCRIPTION: X** X** rpt_seq_1() ouputs diff report for a section X** X** RETURN VALUE: X** X** None X** X**-- X*/ Xstatic void rpt_seq_1 (f1, m1, cnt1, f2, m2, cnt2) XFILEINF`09 *f1;`09/** File info for #1 **/ Xint`09 m1;`09`09/** Location of matching seq in #1 **/ Xint`09 cnt1;`09/** Number of lines in matching seq in #1 **/ XFILEINF *f2; /** File info for #2 **/ Xint`09 m2;`09`09/** Location of matching seq in #2 **/ Xint`09 cnt2;`09/** Number of lines in matching seq in #2 **/ X`7B X struct FAB fab; X struct RAB rab; X X unsigned long retcode; X static char linebuf`5BMAXCHARS+1`5D; X $DESCRIPTOR (linebuf_descriptor, linebuf); X char *filename = "SYS$OUTPUT"; X int i; X int len; X X /* X **`09Initialize FAB X **/ X X fab = cc$rms_fab; X fab.fab$l_fna = filename; X fab.fab$b_fns = strlen(filename); X `20 X /* X **`09 Initialize Source File RAB X **/ X X rab = cc$rms_rab; X rab.rab$l_fab = &fab; X X /* X **`09Report difference X **/ X X if (sys$open (&fab, 0, 0) != RMS$_NORMAL)`20 X `7B X`09fprintf(stderr, "Insufficient privilege for write operation"); X`09return; X `7D X X rab.rab$b_rac = RAB$C_SEQ; X rab.rab$l_rbf = linebuf; X X if ((retcode = sys$connect (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09sys$close(&fab, 0, 0); X`09fprintf(stderr, "Insufficient privilege for connect operation"); X`09return; X `7D X X strcpy (linebuf, "************\r\n"); X rab.rab$w_rsz = strlen(linebuf); X if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09sys$close(&fab, 0, 0); X`09fprintf(stderr, "Insufficient privilege for write operation"); X`09return; X `7D X X sprintf (linebuf, "File %s\r\n", f1->filename); X rab.rab$w_rsz = strlen(linebuf); X if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09sys$close(&fab, 0, 0); X`09fprintf(stderr, "Insufficient privilege for write operation"); X`09return; X `7D X X X for (i = diff_beg1+1; i <= m1; i++) X `7B X`09sprintf (linebuf, "%6.6d ", i); X`09len = strlen (linebuf); X`09memcpy (linebuf+len, f1->txt`5Bi`5D.content, f1->txt`5Bi`5D.len); X`09memcpy (linebuf+len+f1->txt`5Bi`5D.len, "\r\n", 2); X`09rab.rab$w_rsz = f1->txt`5Bi`5D.len+len+2; X`09if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X`09`7B X`09 sys$close(&fab, 0, 0); X`09 fprintf(stderr, "Insufficient privilege for write operation"); X`09 return; X`09`7D X `7D X X strcpy (linebuf, "******\r\n"); X rab.rab$w_rsz = strlen(linebuf); X if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09sys$close(&fab, 0, 0); X`09fprintf(stderr, "Insufficient privilege for write operation"); X`09return; X `7D X X sprintf (linebuf, "File %s\r\n", f2->filename); X rab.rab$w_rsz = strlen(linebuf); X if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09sys$close(&fab, 0, 0); X`09fprintf(stderr, "Insufficient privilege for write operation"); X`09return; X `7D X X for (i = diff_beg2+1; i <= m2; i++) X `7B X`09sprintf (linebuf, "%6.6d ", i); X`09len = strlen (linebuf); X`09memcpy (linebuf+len, f2->txt`5Bi`5D.content, f2->txt`5Bi`5D.len); X`09memcpy (linebuf+len+f2->txt`5Bi`5D.len, "\r\n", 2); X`09rab.rab$w_rsz = f2->txt`5Bi`5D.len+len+2; X`09if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X`09`7B X`09 sys$close(&fab, 0, 0); X`09 fprintf(stderr, "Insufficient privilege for write operation"); X`09 return; X`09`7D X `7D X X strcpy (linebuf, "************\r\n"); X rab.rab$w_rsz = strlen(linebuf); X if ((retcode = sys$put (&rab, 0, 0)) != RMS$_NORMAL)`20 X `7B X`09fprintf(stderr, "Insufficient privilege for write operation"); X `7D X X diff_sec++; X diff_line += max (m1-diff_beg1-1, m2-diff_beg2-1); X X sys$close (&fab, 0, 0); X`7D $ CALL UNPACK DIFF.C;23 609991365 $ create 'f' X/* X**++ X** FACILITY: X** X**`09 DIFF.H X** X** ABSTRACT: X** X** This module contains macro definitions for DIFF.C X** X** AUTHORS: X** X**`09Steppe, Tom. "File Comparison Algorithms." Dr. Dobb's`20 X**`09Journal, #131 (Sep 1987): 54-60. X** X** X** CREATION DATE: 1-MAR-1991 X** X** MODIFICATION HISTORY: X** X**-- X*/ X X/* X** MACRO DEFINITIONS X**/ X X/** Long enough value for DIFF`09`09`09**/ X#define LNGVAL`09`09`09`09`0925 X X/** Maximum lines and chars in a line for DIFF **/ X#define MAXLINES`09`09`09`0965535 X#define MAXCHARS`09`09`09`0965535 X X/* X** X** GLOBAL DECLARATIONS X** X**/ X Xtypedef int`09`09BOOLEAN; /** Boolean type and values **/ +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+-