@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             LIB121
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL

~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YLIB121
~M~OLIB IMPLEMENTATION DESCRIPTION
~
~M~OSection 12 Version 1
~S1~OSection 12.1 File  Processing Facilities
~S1~O1. General Description
~BThis module implements a set of utilities
for manipulating files and directories.
~S1~O2. Interfaces
~
Library procedures~
   COMPARE (FILE1, FILE2, MODE)~
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BThe operation of the procedures is straightforward.
~S1~O3.2 Data Structures
~
~T% 15
~S2~O3.2.1 COMPARE (FILE1, FILE2, MODE)
~
~BThe data structures for this procedure are all declared locally.
The main ones are:~
~
BUFF~IA character buffer into which lines from the two source
files are copied when a mismatch is encountered.~
LINE1~
LINE2~IVectors of pointers to the lines of the repective files
stored in BUFF.~
I.POS1~
I.POS2~IThe I.POS value at the start of the lines saved in BUFF.~
~
~S1~O3.3 Special Notes
~BNone.
~
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H                LIB121
~V9 -1
~F
@TITLE LIB12(1,11)

@COL 1S-2R-3R-4R-5R-6F

@FLOW 1-2-3-4-5-6

@BOX 1.0
FILE PROCESSING FACILITIES
@BOX 4.0
1 COMPARE
@BOX 6.0
END
@BOX 1.1
#LIB12/1
MODULE (COMPARE);
@BOX 3.1
LITERAL / INTEGER MAX.MISMATCH = 256, BUFFER.SIZE = 4096;
@BOX 4.1
*CODE 1;
LSPEC COMPARE (ADDR [LOGICAL8], ADDR [LOGICAL8], INTEGER);
   #LIB12.1
@BOX 6.1
*END
@END

@TITLE LIB12/1(1,11)

@COL 1S-2R-3R-4R

@FLOW 1-2-3-4

@BOX 1.0
OTHER MODULES USED
@BOX 4.0
BASIC SYSTEM LIBRARY
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 4.1
LSPEC CURRENT.INPUT () / INTEGER;
LSPEC DEFINE.INPUT (INTEGER, ADDR [LOGICAL8], INTEGER32) / INTEGER;
LSPEC SELECT.INPUT (INTEGER);
LSPEC I.ENQ () / INTEGER;
LSPEC I.POS () / INTEGER32;
LSPEC SET.IPOS (INTEGER32);
LSPEC IN.LINE (ADDR [LOGICAL8]) / INTEGER;
LSPEC SPACES (INTEGER);
LSPEC NEWLINES (INTEGER);
LSPEC CAPTION (ADDR [LOGICAL8]);
LSPEC IN.CH () / INTEGER;
LSPEC OUT.CH (INTEGER);
LSPEC END.INPUT (INTEGER, INTEGER);
@END

@TITLE LIB12.1(1,11)

@COL 9N-10R-11N
@COL 1S-2R-3N-4T-5R-6T-7R-8N
@COL 16T-12R-13R-14R-15F

@ROW 9-3
@ROW 10-7
@ROW 11-8
@ROW 5-16

@FLOW 1-2-3-4NO-5-6NO-7-8-11-9-3
@FLOW 4YES-16NO-12-13-14-15
@FLOW 16YES-14
@FLOW 6YES-10-11

@BOX 1.0
COMPARE (DOCUMENT1, DOCUMENT2, MODE)
@BOX 2.0
DEFINE INPUT STREAMS
@BOX 4.0
AT END OF ONE
OF THE DOCUMENTS ?
@BOX 5.0
GET A NEW LINE FOR
EACH DOCUMENT
@BOX 6.0
ARE THE LINES DIFFERENT ?
@BOX 7.0
PRINT LINE OF DOCUMENT 1
IF MARKING OF OUTPUT REQUIRED
@BOX 10.0
FIND MATCH AND
PRINT DIFFERENCES
[LIB12.1.1]
@BOX 12.0
MONITOR SURPLUS LINES
ON DOCUMENT 1
@BOX 13.0
MONITOR SURPLUS LINES
ON DOCUMENT 2
@BOX 14.0
SELECT INITIAL INPUT STREAM
AND RELEASE ADDITIONAL STREAMS
@BOX 15.0
END
@BOX 16.0
AT END OF BOTH DOCUMENTS?
@BOX 1.1
PROC COMPARE (DOC1, DOC2, MODE);
INTEGER SAVE.ISTR, I.STR1, I.STR2, EOD1, EOD2,
   CH, I, J, MATCH, DIF, LSIZE, LINE, E1, E2;
ADDR [LOGICAL8] BUFF;
ADDR [LOGICAL8] [MAX.MISMATCH] LINE1, LINE2;
LOGICAL32 [MAX.MISMATCH] I.POS1, I.POS2;
LOGICAL8 [BUFFER.SIZE] BUFFER;
PSPEC COMPARE.LINES (ADDR [LOGICAL8], ADDR [LOGICAL8]) / INTEGER;
PSPEC HEADING (ADDR [LOGICAL8]);
#LIB12.1.2
#LIB12.1.3
DATAVEC STARS (LOGICAL8)
   "******************"
END
@BOX 2.1
CURRENT.INPUT () => SAVE.ISTR;
DEFINE.INPUT (-1, DOC1, 0) => I.STR1;
DEFINE.INPUT (-1, DOC2, 0) => I.STR2;
0 => EOD1 => EOD2 => DIF;
@BOX 4.1
SELECT.INPUT (I.STR2);
I.ENQ () => E2 !> EOD2;
SELECT.INPUT (I.STR1);
I.ENQ () => E1 !> EOD1;
IF EOD1 ! EOD2 /= 0
@BOX 5.1
0 => LINE;
I.POS () => I.POS1 [0];
^BUFFER => BUFF;
MAKE (LOGICAL8, IN.LINE (BUFF) + 1 => LSIZE, BYTE (BUFF)) => LINE1 [0];
PART (BUFF, LSIZE, SIZE (BUFF)) => BUFF;
SELECT.INPUT (I.STR2);
I.POS () => I.POS2 [0];
MAKE (LOGICAL8, IN.LINE (BUFF) + 1 => LSIZE, BYTE (BUFF)) => LINE2 [0];
PART (BUFF, LSIZE, SIZE (BUFF)) => BUFF;
@BOX 6.1
IF COMPARE.LINES (LINE1 [0], LINE2 [0]) /= 0
@BOX 7.1
IF MODE /= 0 THEN
   SPACES (2);
   CAPTION (LINE1 [0]);
FI
@BOX 10.1
#LIB12.1.1
@BOX 12.1
1 +> DIF;
SELECT.INPUT (I.STR1);
IF MODE = 0 THEN
   HEADING (DOC1);
   WHILE I.ENQ () = 0 DO
      OUT.CH (IN.CH ());
   OD
ELSE
   CAPTION (%"! ");
   WHILE I.ENQ () = 0 DO
      OUT.CH (IN.CH () => CH);
      IF CH = "$L" THEN
         CAPTION (%"! ");
      FI
   OD
FI
@BOX 13.1
SELECT.INPUT (I.STR2);
IF MODE = 0 THEN
   HEADING (DOC2);
   WHILE I.ENQ () = 0 DO
      OUT.CH (IN.CH ());
   OD
   HEADING (^STARS);
ELSE
   HEADING (%"INSERTION");
FI
@BOX 14.1
IF DIF /= 0 THEN
   CAPTION (%"$LFILES ARE DIFFERENT$L");
ELSE
   IF DIF = 0 THEN
      CAPTION (%"$LFILES ARE THE SAME$L");
   FI
FI
SELECT.INPUT (SAVE.ISTR);
END.INPUT (I.STR1, 0);
END.INPUT (I.STR2, 0);
@BOX 15.1
END
@BOX 16.1
IF E1 /= 0 AND E2 /= 0
@END


@TITLE LIB12.1.1(1,11)

@COL 1S-2T-3T-4R-5T-6R-7T-8R-9N-10F
@COL 11R-14R-12R-13N

@ROW 3-11
@ROW 8-12
@ROW 9-13
@ROW 4-14

@FLOW 1-2NO-3-4-5NOT FOUND-6-7FOUND-8-9-10
@FLOW 2YES-11
@FLOW 3YES-14-13-9
@FLOW 5FOUND-12-13
@FLOW 7NOT FOUND-2

@BOX 1.0
FIND MATCH
@BOX 2.0
LINE BUFFER FULL
@BOX 3.0
AT END OF EITHER INPUT
@BOX 4.0
GET NEXT LINE FOR DOCUMENT 1
@BOX 5.0
SEARCH FOR MATCH WITH
LINES OF DOCUMENT 2
@BOX 6.0
GET NEXT LINE FOR DOCUMENT 2
@BOX 7.0
SEARCH FOR MATCH WITH
LINES OF DOCUMENT 1
@BOX 8.0
MONITOR ADDITIONAL LINES
IN DOCUMENT 1
@BOX 10.0
END
@BOX 11.0
MONITOR MISMATCH AND
ABANDON COMPARISON
@BOX 12.0
MONITOR ADDITIONAL LINES
IN DOCUMENT 2
@BOX 14.0
RESET TO BEGINNING
OF MISMATCH
@BOX 1.1
FIND.MATCH: BEGIN
1 +> DIF;
@BOX 2.1
IF SIZE (BUFF) = 0
@BOX 3.1
SELECT.INPUT (I.STR2);
I.ENQ () => EOD2;
SELECT.INPUT (I.STR1);
I.ENQ () => EOD1;
IF EOD1 ! EOD2 /= 0
@BOX 4.1
I.POS () => I.POS1 [1 +> LINE];
MAKE (LOGICAL8, IN.LINE (BUFF) + 1 => LSIZE, BYTE (BUFF)) => LINE1 [LINE];
PART (BUFF, LSIZE, SIZE (BUFF)) => BUFF;
@BOX 5.1
-1 => I => MATCH;
WHILE MATCH /= 0 AND
   1 +> I < LINE - 2 DO
   IF COMPARE.LINES (LINE1 [LINE - 2], LINE2 [I]) = 0 AND
      COMPARE.LINES (LINE1 [LINE - 1], LINE2 [I + 1]) = 0 AND
      COMPARE.LINES (LINE1 [LINE], LINE2 [I + 2]) = 0 THEN
      0 => MATCH;
   FI
OD
IF MATCH = 0
@BOX 6.1
SELECT.INPUT (I.STR2);
I.POS () => I.POS2 [LINE];
MAKE (LOGICAL8, IN.LINE (BUFF) + 1 => LSIZE, BYTE (BUFF)) => LINE2 [LINE];
PART (BUFF, LSIZE, SIZE (BUFF)) => BUFF;
@BOX 7.1
-1 => I => MATCH;
WHILE MATCH /= 0 AND
   1 +> I < LINE - 1 DO
   IF COMPARE.LINES (LINE1 [I], LINE2 [LINE - 2]) = 0 AND
      COMPARE.LINES (LINE1 [I + 1], LINE2 [LINE - 1]) = 0 AND
      COMPARE.LINES (LINE1 [I + 2], LINE2 [LINE]) = 0 THEN
      0 => MATCH;
   FI
OD
IF MATCH /= 0
@BOX 8.1
SET.I.POS (I.POS2 [LINE - 2]);
SELECT.INPUT (I.STR1);
SET.I.POS (I.POS1 [I]);
IF MODE = 0 THEN
   HEADING (DOC1);
   FOR J < I DO
      CAPTION (LINE1 [J]);
   OD
   HEADING (DOC2);
   FOR J < LINE - 2 DO
      CAPTION (LINE2 [J]);
   OD
   HEADING (^STARS);
   NEWLINES (2);
ELSE
   IF I = 0 THEN
      HEADING (%"INSERTION");
   ELSE
      FOR J < I DO
         CAPTION (%"! ");
         CAPTION (LINE1 [J]);
      OD
   FI
FI
@BOX 10.1
END
@BOX 11.1
CAPTION (%"$L**FILES TOO DIFFERENT TO COMPARE**$L");
SELECT.INPUT (SAVE.I.STR);
END.INPUT (I.STR1, 0);
END.INPUT (I.STR2, 0);
EXIT;
@BOX 12.1
SET.I.POS (I.POS1 [LINE - 2]);
SELECT.INPUT (I.STR2);
SET.I.POS (I.POS2 [I]);
IF MODE = 0 THEN
   HEADING (DOC1);
   FOR J < LINE - 2 DO
      CAPTION (LINE1 [J]);
   OD
   HEADING (DOC2);
   FOR J < I DO
      CAPTION (LINE2 [J]);
   OD
   HEADING (^STARS);
   NEWLINES (2);
ELSE
   FOR J < LINE - 2 DO
      CAPTION (%"! ");
      CAPTION (LINE1 [J]);
   OD
FI
@BOX 14.1
SELECT.INPUT (I.STR2);
SET.I.REC(0);
SET.I.POS (I.POS2 [0]);
SELECT.INPUT (I.STR1);
SET.I.REC(0);
SET.I.POS (I.POS1 [0]);
@END


@TITLE LIB12.1.2(1,11)

@COL 1S-2T-3T-4R-5F
@COL 6R

@ROW 4-6

@FLOW 1-2NO-3NO-4-5
@FLOW 2YES-6-5
@FLOW 3YES-6

@BOX 1.0
COMPARE LINES (LINE1, LINE2)
@BOX 2.0
ARE LINE SIZES DIFFERENT
@BOX 3.0
ARE THE LINES DIFFERENT
@BOX 4.0
RETURN "SAME" RESULT
@BOX 5.0
END
@BOX 6.0
RETURN "DIFFERENT" RESULT
@BOX 1.1
PROC COMPARE.LINES (LINE1, LINE2);
INTEGER LIMIT, I;
@BOX 2.1
IF SIZE (LINE1) => LIMIT /= SIZE (LINE2)
@BOX 3.1
-1 => I;
WHILE 1 +> I < LIMIT AND
   LINE1^ [I] = LINE2^ [I] DO OD
IF I /= LIMIT
@BOX 4.1
0 => COMPARE.LINES;
@BOX 5.1
END
@BOX 6.1
1 => COMPARE.LINES;
@END


@TITLE LIB12.1.3(1,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
HEADING (TITLE)
@BOX 2.0
PRINT HEADING
@BOX 3.0
END
@BOX 1.1
PROC HEADING (TITLE);
@BOX 2.1
CAPTION (%"********");
CAPTION (TITLE);
CAPTION (%"********$L");
@BOX 3.1
END
@END




