0 $SET $                                                                  00000050           
1 $SET HEAP = 20000                                                       00000100           
2 $SET AUTOBIND                                                           00000200           
3 $BIND = FROM OBJECT/PTOOLS/COMPARE/B6700                                00000300           
4 (**     COMPARE - COMPARE TWO TEXT FILES AND REPORT THEIR DIFFERENCES.  00001000           
5 *                                                                       00001100           
6 *       COPYRIGHT (C) 1977, 1978                                        00001200           
7 *       JAMES F. MINER                                                  00001300           
8 *       SOCIAL SCIENCE RESEARCH FACILITIES CENTER                       00001400           
9 *       UNIVERSITY OF MINNESOTA                                         00001500           
10 *                                                                       00001600           
11 *       GENERAL PERMISSION TO MAKE FAIR USE IN NON-PROFIT ACTIVITIES    00001700           
12 *       OF ALL OR PART OF THIS MATERIAL IS GRANTED PROVIDED THAT        00001800           
13 *       THIS NOTICE IS GIVEN.  TO OBTAIN PERMISSION FOR OTHER USES      00001900           
14 *       AND/OR MACHINE READABLE COPIES WRITE TO:                        00002000           
15 *                                                                       00002100           
16 *               THE DIRECTOR                                            00002200           
17 *               SOCIAL SCIENCE RESEARCH FACILITIES CENTER               00002300           
18 *               25 BLEGEN HALL                                          00002400           
19 *               269 19TH AVE. SO.                                       00002500           
20 *               UNIVERSITY OF MINNESOTA                                 00002600           
21 *               MINNEAPOLIS, MINNESOTA  55455                           00002700           
22 *               U S A                                                   00002800           
23 *)                                                                      00002900           
24                                                                         00003000           
25 (**     COMPARE IS USED TO DISPLAY ON "OUTPUT" THE DIFFERENCES          00003100           
26 *       BETWEEN TWO SIMILAR TEXTS ("FILEA" AND "FILEB"). COMPARE        00003200           
27 *       MAY ALSO BE USED TO GENERATE AN UPDATE SET OF DIRECTIVES.       00003300           
28 *       NOTABLE CHARACTERISTICS ARE:                                    00003400           
29 *                                                                       00003500           
30 *       - COMPARE IS LINE-ORIENTED. THE SMALLEST UNIT OF COMPARISON     00003600           
31 *         IS THE TEXT LINE (IGNORING TRAILING BLANKS).  THE PRESENT     00003700           
32 *         IMPLEMENTATION HAS A FIXED MAXIMUM LINE LENGTH.               00003800           
33 *                                                                       00003900           
34 *       - BY MANIPULATING A PROGRAM PARAMETER, THE USER CAN AFFECT      00004000           
35 *         COMPARE'S SENSITIVITY TO THE "LOCALITY" OF DIFFERENCES.       00004100           
36 *         MORE SPECIFICALLY THIS PARAMETER, "MINLINESFORMATCH",         00004200           
37 *         SPECIFIES THE NUMBER OF CONSECUTIVE LINES ON EACH FILE        00004300           
38 *         WHICH MUST MATCH IN ORDER THAT THEY BE CONSIDERED AS          00004400           
39 *         TERMINATING THE PRIOR MISMATCH.  A LARGE VALUE OF             00004500           
40 *         "MINLINESFORMATCH" TENDS TO PRODUCE FEWER BUT LARGER          00004600           
41 *         MISMATCHES THAN DOES A SMALL VALUE.  THE VALUE SIX APPEARS    00004700           
42 *         TO GIVE GOOD RESULTS ON PASCAL SOURCE FILES BUT MAY BE        00004800           
43 *         INAPPROPRIATE FOR OTHER APPLICATIONS.                         00004900           
44 *                                                                       00005000           
45 *       - ANOTHER PROGRAM PARAMETER (VARIABLE) SELECTS AMONG 3 OPTIONS  00005100           
46 *         FOR OUTPUT:  DIFFERENCES, MODIFICATIONS, AND FLAGS.           00005200           
47 *         "DIFFERENCES" DESCRIBES THE ACTION OF COMPARE AS BEFORE.      00005300           
48 *         "MODIFICATIONS" GENERATES A FILE OF UPDATE DIRECTIVES.        00005400           
49 *         "FLAGS" PRODUCES AN A/D DISPLAY OF ADDITIONS AND DELETIONS    00005500           
50 *         WHICH WOULD RESULT IF THE MODIFICATIONS FIEL WERE APPLIED.    00005600           
51 *                                                                       00005700           
52 *       - ANOTHER PROGRAM PARAMETER (CONSTANT), "MARKUNEQUALCOLUMNS",   00005800           
53 *         SPECIFIES THAT WHEN UNEQUAL LINES ARE FOUND, EACH LINE FROM   00005900           
54 *         FILEA IS PRINTED NEXT TO ITS CORRESPONDING LINE FROM FILEB,   00006000           
55 *         AND UNEQUAL COLUMNS ARE MARKED.  THIS OPTION IS PARTICULARLY  00006100           
56 *         USEFUL FOR FIXED-FORMAT DATA FILES.  NOTES:  LINE PAIRING IS  00006200           
57 *         NOT ATTEMPTED IF THE MISMATCHING SECTIONS ARE NOT THE SAME    00006300           
58 *         NUMBER OF LINES ON EACH FILE.                                 00006400           
59 *                                                                       00006500           
60 *       - COMPARE EMPLOYS A SIMPLE BACKTRACKING-SEARCH ALGORITHM TO     00006600           
61 *         ISOLATE MISMATCHES FROM THEIR SURROUNDING MATCHES.  THIS      00006700           
62 *         REQUIRES (HEAP) STORAGE ROUGHLY PROPORTIONAL THE THE SIZE     00006800           
63 *         OF THE LARGEST MISMATCH, AND TIME ROUGHLY PROPORTIONAL TO     00006900           
64 *         THE SQUARE OF THE SIZE OF THE MISMATCH FOR EACH MISMATCH.     00007000           
65 *         FOR THIS REASON IT MAY NOT BE FEASIBLE TO USE COMPARE ON      00007100           
66 *         FILES WITH VERY LONG MISMATCHES.                              00007200           
67 *                                                                       00007300           
68 *       - TO THE BEST OF THE AUTHOR'S KNOWLEDGE, COMPARE UTILIZES       00007400           
69 *         ONLY FEATURES OF STANDARD PASCAL.  SEE PASCAL NEWS #12,       00007500           
70 *         MAY, 1978, PAGES 20-23.                                       00007600           
71 *)                                                                      00007700           
72                                                                         00007800           
73 (**     MODIFICATION HISTORY.                                           00007900           
74 *                                                                       00008000           
75 *         JOHN P. STRAIT  77/07/10.                                     00008100           
76 *         UNIVERSITY COMPUTER CENTER                                    00008200           
77 *         UNIVERSITY OF MINNESOTA                                       00008300           
78 *         VERSION 2.0                                                   00008400           
79 *         GENERATE UPDATE DIRECTIVES (INSERTS AND DELETES).             00008500           
80 *                                                                       00008600           
81 *                                                                       00008700           
82 *         JOHN P. STRAIT  77/09/12.                                     00008800           
83 *         UNIVERSITY COMPUTER CENTER                                    00008900           
84 *         UNIVERSITY OF MINNESOTA                                       00009000           
85 *         VERSION 2.1                                                   00009100           
86 *         1. GENERATE FLAG-FORM OUTPUT.                                 00009200           
87 *         2. SELECT ONE OF THREE OUTPUT FORMS WITH AN OPTION.           00009300           
88 *                                                                       00009400           
89 *                                                                       00009500           
90 *         WILLETT KEMPTON  78/11/07.                                    00009600           
91 *         DEPARTMENT OF ANTHROPOLOGY                                    00009700           
92 *         UNIVERSITY OF CALIFORNIA - BERKELEY                           00009800           
93 *         VERSION 2.2                                                   00009900           
94 *         1. MARK UNEQUAL COLUMNS IN PAIRS OF LINES.                    00010000           
95 *         2. NOTE PRESENCE OF LINES LONGER THAN LINELENGTH.             00010100           
96 *                                                                       00010200           
97 *                                                                       00010300           
98 *         RICK L. MARCUS  78/12/19.                                     00010400           
99 *         UNIVERSITY COMPUTER CENTER                                    00010500           
100 *         UNIVERSITY OF MINNESOTA                                       00010600           
101 *         VERSION 3.0                                                   00010700           
102 *         1. MAKE MINOR EFFICIENCY IMPROVEMENTS.                        00010800           
103 *         2. CHANGE INDENTING OF SOURCE CODE.                           00010900           
104 *                                                                       00011000           
105 *                                                                       00011100           
106 *         RICK L. MARCUS,                                               00011200           
107 *         ANDY MICKEL      78/12/19.                                    00011300           
108 *         VERSION 3.0 CDC                                               00011400           
109 *         1. ADD CDC CONTROL STATEMENT PROCESSING                       00011500           
110 *            (BASED IN PART ON CODE BY JOHN STRAIT).                    00011600           
111 *         2. ADD LINELIMIT AND ACTUAL FILE NAME PROCEDURES FOR          00011700           
112 *            CDC-6000 PASCAL.                                           00011800           
113 *                                                                       00011805           
114 *         ROY FREAK     80/04/24                                        00011810           
115 *         DEPARTMENT OF INFORMATION SCIENCE                             00011820           
116 *         UNIVERSITY OF TASMANIA                                        00011830           
117 *         VERSION 3.0 B6700                                             00011840           
118 *         1. REMOVE CDC STUFF                                           00011850           
119 *         2. ADAPT FOR B6700                                            00011860           
120 *                                                                       00011870           
121 *)                                                                      00011900           
122                                                                         00012000           
123 PROGRAM COMPARE(FILEA, FILEB, OUTPUT, MODS);                            00012100           
124                                                                         00012200           
125   CONST                                                                 00012300           
126                                                                         00012400           
127     VERSION = '3.0 B6700';                                              00012500           
128     COMPILEDATE = '80/04/24';                                           00012600           
129                                                                         00012700           
130     MAXLENGTH = 150;                                                    00012800           
131     IDENTLENGTH = 8;                                                    00012900           
132     NOIDENT = '        '       (* SHOULD HAVE IDENTLENGTH BLANKS *);    00013000           
133                                                                         00013100           
134                                                                         00013200           
135   TYPE                                                                  00013300           
136                                                                         00013400           
137     ALFA30 = PACKED ARRAY [1..30] OF CHAR;                              00013410           
138                                                                         00013420           
139     LINEIDENTIFICATION =       (* FOR MODS OPTION *)                    00013500           
140       PACKED RECORD                                                     00013600           
141         IDENT: PACKED ARRAY [1..IDENTLENGTH] OF CHAR;                   00013700           
142         NUMBER: 0..99999                                                00013800           
143       END;                                                              00013900           
144                                                                         00014000           
145     LINEPOINTER = ^LINE;                                                00014100           
146     LINE =                     (* SINGLE LINE BUFFER *)                 00014200           
147       PACKED RECORD                                                     00014300           
148         NEXTLINE: LINEPOINTER;                                          00014400           
149         LENGTH: 0..MAXLENGTH;                                           00014500           
150         IMAGE: PACKED ARRAY [1..MAXLENGTH] OF CHAR;                     00014600           
151         LINEID: LINEIDENTIFICATION                                      00014700           
152       END;                                                              00014800           
153                                                                         00014900           
154     STREAM =                   (* BOOKKEEPING FOR EACH INPUT FILE *)    00015000           
155       RECORD                                                            00015100           
156         NAME:                                                           00015200           
157           RECORD                                                        00015300           
158             C: CHAR;                                                    00015400           
159             ACTUAL: ALFA30;                                             00015500           
160             LEN: 1..30                                                  00015600           
161           END;                                                          00015700           
162         CURSOR, CURSORPREVIOUS, HEAD, TAIL: LINEPOINTER;                00015800           
163         CURSORLINENO, HEADLINENO, TAILLINENO: INTEGER;                  00015900           
164         LINEIDPREVIOUS: LINEIDENTIFICATION;                             00016000           
165         ENDFILE: BOOLEAN                                                00016100           
166       END;                                                              00016200           
167                                                                         00016300           
168                                                                         00016400           
169   VAR                                                                   00016500           
170                                                                         00016600           
171     MODS: TEXT;                                                         00016700           
172     MINLINESFORMATCH: INTEGER  (* NUMBER OF CONSECUTIVE EQUIVALENT *)   00016800           
173                                (* LINES TO END A MISMATCH *);           00016900           
174     MARKUNEQUALCOLUMNS: BOOLEAN(* IF UNEQUAL LINES ARE TO PAIRED, *)    00017000           
175                                (* AND UNEQUAL COLUMNS MARKED *);        00017100           
176     LINELENGTH: 0..MAXLENGTH   (* MAX SIGNIFICANT INPUT LINELENGTH *);  00017200           
177     OPTIONS:                                                            00017300           
178       (DIFFERENCES, MODIFICATIONS, FLAGS);                              00017400           
179                                                                         00017500           
180     FILEA, FILEB: TEXT;                                                 00017600           
181     A, B: STREAM;                                                       00017700           
182     MATCH: BOOLEAN;                                                     00017800           
183     ENDOFFILE: BOOLEAN         (* SET IF END OF STREAM A OR B *);       00017900           
184                                                                         00018000           
185     TEMPLINE:                  (* USED BY READLINE *)                   00018100           
186       RECORD                                                            00018200           
187         LASTLINELENGTH: 0..MAXLENGTH;                                   00018300           
188         IMAGE: ARRAY [0..MAXLENGTH] OF CHAR                             00018400           
189       END;                                                              00018500           
190                                                                         00018600           
191     FREELINES: LINEPOINTER     (* FREE LIST OF LINE BUFFERS *);         00018700           
192                                                                         00018800           
193     SAME: BOOLEAN              (* FALSE IF MISMATCHES OCCUR *);         00018900           
194     LINESTOOLONG: BOOLEAN      (* TRUE IF SOME LINES > LINELENGTH *);   00019000           
195                                                                         00019100           
196                                                                         00019200           
197   PROCEDURE WRITETEXT(VAR X: STREAM; FLAG: CHAR);                       00019300           
198                                                                         00019400           
199     VAR                                                                 00019500           
200       L: INTEGER;                                                       00019600           
201                                                                         00019700           
202     PROCEDURE WRITELINE(VAR F: TEXT);                                   00019800           
203                                                                         00019900           
204     BEGIN (* WRITELINE *)                                               00020000           
205       WITH X.HEAD^ DO                                                   00020100           
206         BEGIN                                                           00020200           
207           IF LENGTH = 0                                                 00020300           
208           THEN                                                          00020400           
209             WRITELN(F)                                                  00020500           
210           ELSE                                                          00020600           
211             WRITELN(F, IMAGE: LENGTH);                                  00020700           
212           X.HEAD := NEXTLINE                                            00020800           
213         END;                                                            00020900           
214       L := L + 1                                                        00021000           
215     END (* WRITELINE *);                                                00021100           
216                                                                         00021200           
217   BEGIN (* WRITETEXT *)                                                 00021300           
218     WITH X DO                                                           00021400           
219       BEGIN                                                             00021500           
220         L := HEADLINENO;                                                00021600           
221         CASE OPTIONS OF                                                 00021700           
222           DIFFERENCES:                                                  00021800           
223             BEGIN (* WRITE FROM HEAD TO 1 LINE BEFORE CURSOR *)         00021900           
224               WHILE (HEAD <> NIL) AND (HEAD <> CURSOR) DO               00022000           
225                 BEGIN                                                   00022100           
226                   WRITE(NAME.C: 4, L: 5, '. ');                         00022200           
227                   WRITELINE(OUTPUT)                                     00022300           
228                 END;                                                    00022400           
229               IF HEAD = NIL THEN                                        00022500           
230                 WRITELN('     *** END OF FILE. ***');                   00022600           
231               WRITELN                                                   00022700           
232             END;                                                        00022800           
233           FLAGS:                                                        00022900           
234             BEGIN                                                       00023000           
235               IF FLAG = 'D' THEN                                        00023100           
236                 WRITELN;                                                00023200           
237               WHILE (HEAD <> NIL) AND (HEAD <> CURSOR) DO               00023300           
238                 BEGIN                                                   00023400           
239                   IF FLAG = 'D'                                         00023500           
240                   THEN                                                  00023600           
241                     WRITE('     D        ')                             00023700           
242                   ELSE                                                  00023800           
243                     WRITE(FLAG: 6, L: 6, '. ');                         00023900           
244                   WRITELINE(OUTPUT)                                     00024000           
245                 END;                                                    00024100           
246               IF FLAG = 'D' THEN                                        00024200           
247                 WRITELN                                                 00024300           
248             END;                                                        00024400           
249           MODIFICATIONS:                                                00024500           
250             WHILE (HEAD <> NIL) AND (HEAD <> CURSOR) DO                 00024600           
251               WRITELINE(MODS)                                           00024700           
252         END                                                             00024800           
253       END                                                               00024900           
254   END (* WRITETEXT *);                                                  00025000           
255                                                                         00025100           
256   PROCEDURE COMPAREFILES;                                               00025200           
257                                                                         00025300           
258     FUNCTION ENDSTREAM(VAR X: STREAM): BOOLEAN;                         00025400           
259                                                                         00025500           
260     BEGIN (* ENDSTREAM *)                                               00025600           
261       WITH X DO                                                         00025700           
262         ENDSTREAM := (CURSOR = NIL) AND ENDFILE                         00025800           
263     END (* ENDSTREAM *);                                                00025900           
264                                                                         00026000           
265     PROCEDURE MARK(VAR X: STREAM);                                      00026100           
266                                                                         00026200           
267      (* CAUSES BEGINNING OF STREAM TO BE POSITIONED BEFORE *)           00026300           
268      (* CURRENT STREAM CURSOR.  BUFFERS GET RECLAIMED, LINE *)          00026400           
269      (* COUNTERS RESET, ETC. *)                                         00026500           
270                                                                         00026600           
271       PROCEDURE COLLECT(VAR FWA, LWAPLUS1: LINEPOINTER);                00026700           
272                                                                         00026800           
273         VAR                                                             00026900           
274           P: LINEPOINTER;                                               00027000           
275                                                                         00027100           
276       BEGIN (* COLLECT *)                                               00027200           
277         WHILE FWA <> LWAPLUS1 DO                                        00027300           
278           WITH FWA^ DO                                                  00027400           
279             BEGIN                                                       00027500           
280               X.LINEIDPREVIOUS := LINEID;                               00027600           
281               P := NEXTLINE;                                            00027700           
282               NEXTLINE := FREELINES;                                    00027800           
283               FREELINES := FWA;                                         00027900           
284               FWA := P                                                  00028000           
285             END                                                         00028100           
286       END (* COLLECT *);                                                00028200           
287                                                                         00028300           
288     BEGIN (* MARK *)                                                    00028400           
289       WITH X DO                                                         00028500           
290         IF HEAD <> NIL                                                  00028600           
291         THEN                                                            00028700           
292           BEGIN                                                         00028800           
293             COLLECT(HEAD, CURSOR);                                      00028900           
294             CURSORPREVIOUS := NIL;                                      00029000           
295             HEADLINENO := CURSORLINENO;                                 00029100           
296             IF CURSOR = NIL THEN                                        00029200           
297               BEGIN                                                     00029300           
298                 TAIL := NIL;                                            00029400           
299                 TAILLINENO := CURSORLINENO                              00029500           
300               END                                                       00029600           
301           END                                                           00029700           
302     END (* MARK *);                                                     00029800           
303                                                                         00029900           
304     PROCEDURE MOVECURSOR(VAR X: STREAM; VAR FILEX: TEXT);               00030000           
305                                                                         00030100           
306      (* FILEX IS THE INPUT FILE ASSOCIATED WITH STREAM X.  THE *)       00030200           
307      (* CURSOR FOR X IS MOVED FORWARD ONE LINE, READING FROM X *)       00030300           
308      (* IF NECESSARY, AND INCREMENTING THE LINE COUNT.  ENDOFFILE *)    00030400           
309      (* IS SET IF EOF ENCOUNTERED ON EITHER STREAM. *)                  00030500           
310                                                                         00030600           
311       PROCEDURE READLINE;                                               00030700           
312                                                                         00030800           
313         VAR                                                             00030900           
314           NEWLINE: LINEPOINTER;                                         00031000           
315           C, C1, C2: 0..MAXLENGTH;                                      00031100           
316           C3: 1..IDENTLENGTH;                                           00031200           
317           N: 0..99999;                                                  00031300           
318                                                                         00031400           
319       BEGIN (* READLINE *)                                              00031500           
320         WITH X DO                                                       00031600           
321           IF NOT ENDFILE                                                00031700           
322           THEN                                                          00031800           
323             BEGIN                                                       00031900           
324               C := 0;                                                   00032000           
325               WITH TEMPLINE DO                                          00032100           
326                 BEGIN                                                   00032200           
327                   WHILE NOT EOLN(FILEX) AND (C < LINELENGTH) DO         00032300           
328                     BEGIN                                               00032400           
329                       C := C + 1;                                       00032500           
330                       READ(FILEX, IMAGE[C])                             00032600           
331                     END;                                                00032700           
332                   IF NOT EOLN(FILEX) THEN                               00032800           
333                     LINESTOOLONG := TRUE;                               00032900           
334                   C1 := C;                                              00033000           
335                   WHILE IMAGE[C] = ' ' DO                               00033100           
336                     C := C - 1;                                         00033200           
337                   FOR C2 := C1 + 1 TO LASTLINELENGTH DO                 00033300           
338                     IMAGE[C2] := ' ';                                   00033400           
339                   LASTLINELENGTH := C;                                  00033500           
340                   IF FREELINES = NIL                                    00033600           
341                   THEN                                                  00033700           
342                     NEW(NEWLINE)                                        00033800           
343                   ELSE                                                  00033900           
344                     BEGIN                                               00034000           
345                       NEWLINE := FREELINES;                             00034100           
346                       FREELINES := FREELINES^.NEXTLINE                  00034200           
347                     END;                                                00034300           
348                   PACK(IMAGE, 1, NEWLINE^.IMAGE)                        00034400           
349                 END;                                                    00034500           
350               WITH NEWLINE^, LINEID DO                                  00034600           
351                 BEGIN                                                   00034700           
352                   LENGTH := C;                                          00034800           
353                   NEXTLINE := NIL;                                      00034900           
354                   WHILE (FILEX^ = ' ') AND NOT EOLN(FILEX) DO           00035000           
355                     GET(FILEX);                                         00035100           
356                   FOR C3 := 1 TO IDENTLENGTH DO                         00035200           
357                     BEGIN                                               00035300           
358                       IDENT[C3] := FILEX^;                              00035400           
359                       IF FILEX^ <> ' ' THEN                             00035500           
360                         GET(FILEX)                                      00035600           
361                     END;                                                00035700           
362                   WHILE (FILEX^ = ' ') AND NOT EOLN(FILEX) DO           00035800           
363                     GET(FILEX);                                         00035900           
364                   N := 0;                                               00036000           
365                   IF FILEX^ IN ['0' .. '9'] THEN                        00036100           
366                     READ(FILEX, N);                                     00036200           
367                   NUMBER := N;                                          00036300           
368                   READLN(FILEX)                                         00036400           
369                 END;                                                    00036500           
370               IF TAIL = NIL                                             00036600           
371               THEN                                                      00036700           
372                 BEGIN                                                   00036800           
373                   HEAD := NEWLINE;                                      00036900           
374                   TAILLINENO := 1;                                      00037000           
375                   HEADLINENO := 1                                       00037100           
376                 END                                                     00037200           
377               ELSE                                                      00037300           
378                 BEGIN                                                   00037400           
379                   TAIL^.NEXTLINE := NEWLINE;                            00037500           
380                   TAILLINENO := TAILLINENO + 1                          00037600           
381                 END;                                                    00037700           
382               TAIL := NEWLINE;                                          00037800           
383               ENDFILE := EOF(FILEX);                                    00037900           
384             END                                                         00038000           
385       END (*READLINE*);                                                 00038100           
386                                                                         00038200           
387     BEGIN (* MOVECURSOR *)                                              00038300           
388       WITH X DO                                                         00038400           
389         IF CURSOR <> NIL                                                00038500           
390         THEN                                                            00038600           
391           BEGIN                                                         00038700           
392             IF CURSOR = TAIL THEN                                       00038800           
393               READLINE;                                                 00038900           
394             CURSORPREVIOUS := CURSOR;                                   00039000           
395             CURSOR := CURSOR^.NEXTLINE;                                 00039100           
396             IF CURSOR = NIL THEN                                        00039200           
397               ENDOFFILE := TRUE;                                        00039300           
398             CURSORLINENO := CURSORLINENO + 1                            00039400           
399           END                                                           00039500           
400         ELSE                                                            00039600           
401           IF NOT ENDFILE                                                00039700           
402           THEN (* BEGINNING OF STREAM *)                                00039800           
403             BEGIN                                                       00039900           
404               READLINE;                                                 00040000           
405               CURSOR := HEAD;                                           00040100           
406               CURSORLINENO := HEADLINENO;                               00040200           
407               CURSORPREVIOUS := NIL;                                    00040300           
408               LINEIDPREVIOUS.IDENT := NOIDENT;                          00040400           
409               LINEIDPREVIOUS.NUMBER := 1                                00040500           
410             END                                                         00040600           
411           ELSE (* END OF STREAM *)                                      00040700           
412             ENDOFFILE := TRUE;                                          00040800           
413     END (* MOVECURSOR *);                                               00040900           
414                                                                         00041000           
415     PROCEDURE BACKTRACK(VAR X: STREAM; VAR CURSORLIMIT: LINEPOINTER);   00041100           
416                                                                         00041200           
417      (* CAUSES THE CURRENT POSITION OF STREAM X TO BECOME THAT *)       00041300           
418      (* OF THE LAST MARK OPERATION.  I.E., THE CURRENT LINE   *)        00041400           
419      (* WHEN THE STREAM WAS MARKED LAST BECOMES THE NEW CURRENT. *)     00041500           
420      (* THE VALUE OF THE CURSOR BEFORE BACKTRACKING IS RETURNED *)      00041600           
421      (* IN CURSORLIMIT. *)                                              00041700           
422                                                                         00041800           
423                                                                         00041900           
424     BEGIN (* BACKTRACK *)                                               00042000           
425       WITH X DO                                                         00042100           
426         BEGIN                                                           00042200           
427           CURSORLIMIT := CURSOR;                                        00042300           
428           CURSOR := HEAD;                                               00042400           
429           CURSORPREVIOUS := NIL;                                        00042500           
430           CURSORLINENO := HEADLINENO;                                   00042600           
431           ENDOFFILE := ENDSTREAM(A) OR ENDSTREAM(B)                     00042700           
432         END                                                             00042800           
433     END (* BACKTRACK *);                                                00042900           
434                                                                         00043000           
435     PROCEDURE COMPARELINES(VAR MATCH: BOOLEAN);                         00043100           
436                                                                         00043200           
437      (* COMPARE THE CURRENT LINES OF STREAMS A AND B, RETURNING *)      00043300           
438      (* MATCH TO SIGNAL THEIR (NON-) EQUIVALENCE.  EOF ON BOTH *)       00043400           
439      (* STREAMS IS CONSIDERED A MATCH, BUT EOF ON ONLY ONE STREAM *)    00043500           
440      (* IS A MISMATCH. *)                                               00043600           
441                                                                         00043700           
442     BEGIN (* COMPARELINES *)                                            00043800           
443       IF (A.CURSOR = NIL) OR (B.CURSOR = NIL)                           00043900           
444       THEN                                                              00044000           
445         MATCH := ENDSTREAM(A) AND ENDSTREAM(B)                          00044100           
446       ELSE                                                              00044200           
447         BEGIN                                                           00044300           
448           MATCH := (A.CURSOR^.LENGTH = B.CURSOR^.LENGTH);               00044400           
449           IF MATCH THEN                                                 00044500           
450             MATCH := (A.CURSOR^.IMAGE = B.CURSOR^.IMAGE)                00044600           
451         END                                                             00044700           
452     END (* COMPARELINES *);                                             00044800           
453                                                                         00044900           
454     PROCEDURE FINDMISMATCH;                                             00045000           
455                                                                         00045100           
456     BEGIN (* FINDMISMATCH *)                                            00045200           
457       (* NOT ENDFILE AND MATCH *)                                       00045300           
458       MARK(A);                                                          00045400           
459       MARK(B);                                                          00045500           
460       REPEAT (* COMPARENEXTLINES *)                                     00045600           
461         MOVECURSOR(A, FILEA);                                           00045700           
462         MOVECURSOR(B, FILEB);                                           00045800           
463         IF OPTIONS = FLAGS THEN                                         00045900           
464           WRITETEXT(B, ' ');                                            00046000           
465         MARK(A);                                                        00046100           
466         MARK(B);                                                        00046200           
467         COMPARELINES(MATCH)                                             00046300           
468       UNTIL ENDOFFILE OR NOT MATCH;                                     00046400           
469     END (* FINDMISMATCH *);                                             00046500           
470                                                                         00046600           
471     PROCEDURE FINDMATCH;                                                00046700           
472                                                                         00046800           
473       VAR                                                               00046900           
474         ADVANCEB: BOOLEAN                                               00047000           
475                     (* TOGGLE ONE-LINE LOOKAHEAD BETWEEN STREAMS. *);   00047100           
476                                                                         00047200           
477       PROCEDURE SEARCH(VAR X: STREAM; (* STREAM TO SEARCH *)            00047300           
478                        VAR FILEX: TEXT;                                 00047400           
479                        VAR Y : STREAM; (* STREAM TO LOOKAHEAD *)        00047500           
480                        VAR FILEY : TEXT);                               00047600           
481                                                                         00047700           
482        (* LOOK AHEAD ONE LINE ON STREAM Y, AND SEARCH FOR THAT LINE *)  00047800           
483        (* BACKTRACKING ON STREAM X. *)                                  00047900           
484                                                                         00048000           
485         VAR                                                             00048100           
486           CURSORLIMIT: LINEPOINTER;                                     00048200           
487                                                                         00048300           
488         PROCEDURE CHECKFULLMATCH;                                       00048400           
489                                                                         00048500           
490          (* FROM THE CURRENT POSITIONS IN X AND Y, WHICH MATCH, *)      00048600           
491          (* MAKE SURE THAT THE NEXT MINLINESFORMATCH-1 LINES ALSO *)    00048700           
492          (* MATCH, OR ELSE SET MATCH := FALSE.  *)                      00048800           
493                                                                         00048900           
494           VAR                                                           00049000           
495             N: INTEGER;                                                 00049100           
496             SAVEXCUR, SAVEYCUR, SAVEXPREV, SAVEYPREV: LINEPOINTER;      00049200           
497             SAVEXLINE, SAVEYLINE: INTEGER;                              00049300           
498                                                                         00049400           
499         BEGIN (* CHECKFULLMATCH *)                                      00049500           
500           WITH X DO                                                     00049600           
501             BEGIN                                                       00049700           
502               SAVEXCUR := CURSOR;                                       00049800           
503               SAVEXLINE := CURSORLINENO;                                00049900           
504               SAVEXPREV := CURSORPREVIOUS                               00050000           
505             END;                                                        00050100           
506           WITH Y DO                                                     00050200           
507             BEGIN                                                       00050300           
508               SAVEYCUR := CURSOR;                                       00050400           
509               SAVEYLINE := CURSORLINENO;                                00050500           
510               SAVEYPREV := CURSORPREVIOUS                               00050600           
511             END;                                                        00050700           
512           COMPARELINES(MATCH);                                          00050800           
513           N := MINLINESFORMATCH - 1;                                    00050900           
514           WHILE MATCH AND (N <> 0) DO                                   00051000           
515             BEGIN                                                       00051100           
516               MOVECURSOR(X, FILEX);                                     00051200           
517               MOVECURSOR(Y, FILEY);                                     00051300           
518               COMPARELINES(MATCH);                                      00051400           
519               N := N - 1                                                00051500           
520             END;                                                        00051600           
521           WITH X DO                                                     00051700           
522             BEGIN                                                       00051800           
523               CURSOR := SAVEXCUR;                                       00051900           
524               CURSORLINENO := SAVEXLINE;                                00052000           
525               CURSORPREVIOUS := SAVEXPREV                               00052100           
526             END;                                                        00052200           
527           WITH Y DO                                                     00052300           
528             BEGIN                                                       00052400           
529               CURSOR := SAVEYCUR;                                       00052500           
530               CURSORLINENO := SAVEYLINE;                                00052600           
531               CURSORPREVIOUS := SAVEYPREV                               00052700           
532             END;                                                        00052800           
533         END (* CHECKFULLMATCH *);                                       00052900           
534                                                                         00053000           
535       BEGIN (* SEARCH *)                                                00053100           
536         MOVECURSOR(Y, FILEY);                                           00053200           
537         BACKTRACK(X, CURSORLIMIT);                                      00053300           
538         CHECKFULLMATCH;                                                 00053400           
539         WHILE (X.CURSOR <> CURSORLIMIT) AND NOT MATCH DO                00053500           
540           BEGIN                                                         00053600           
541             MOVECURSOR(X, FILEX);                                       00053700           
542             CHECKFULLMATCH                                              00053800           
543           END                                                           00053900           
544       END (* SEARCH *);                                                 00054000           
545                                                                         00054100           
546       PROCEDURE PRINTMISMATCH;                                          00054200           
547                                                                         00054300           
548         PROCEDURE PRINTDIFFERENCES;                                     00054400           
549                                                                         00054500           
550           VAR                                                           00054600           
551             EMPTYA, EMPTYB: BOOLEAN;                                    00054700           
552                                                                         00054800           
553           PROCEDURE WRITELINENO(VAR X: STREAM);                         00054900           
554                                                                         00055000           
555             VAR                                                         00055100           
556               F, L: INTEGER;                                            00055200           
557                                                                         00055300           
558           BEGIN (* WRITELINENO *)                                       00055400           
559             WITH X DO                                                   00055500           
560               BEGIN                                                     00055600           
561                 F := HEADLINENO;                                        00055700           
562                 L := CURSORLINENO - 1;                                  00055800           
563                 WRITE('LINE');                                          00055900           
564                 IF F = L                                                00056000           
565                 THEN                                                    00056100           
566                   WRITE(' ', F: 1)                                      00056200           
567                 ELSE                                                    00056300           
568                   WRITE('S ', F: 1, ' THRU ', L: 1);                    00056400           
569                 IF CURSOR = NIL THEN                                    00056500           
570                   WRITE(' (BEFORE END OF FILE)');                       00056600           
571               END                                                       00056700           
572           END (* WRITELINENO *);                                        00056800           
573                                                                         00056900           
574           PROCEDURE WRITEPAIRS(PA, PB: LINEPOINTER; LA, LB: INTEGER);   00057000           
575                                                                         00057100           
576            (* WRITES FROM THE HEAD TO THE CURSOR (LIKE WRITETEXT). *)   00057200           
577            (* UNLIKE WRITETEXT, WRITEPAIRS WRITES FROM BOTH FILES *)    00057300           
578            (* AT ONCE, COMPARES COLUMNS WITHIN LINES, AND MARKS *)      00057400           
579            (* UNEQUAL COLUMNS. *)                                       00057500           
580                                                                         00057600           
581             VAR                                                         00057700           
582               TEMPA, TEMPB: ARRAY[1..MAXLENGTH] OF CHAR;                00057800           
583               COL, MAXCOL: INTEGER;                                     00057900           
584                                                                         00058000           
585           BEGIN (* WRITEPAIRS *)                                        00058100           
586             REPEAT                                                      00058200           
587               WITH PA^ DO                                               00058300           
588                 BEGIN                                                   00058400           
589                   WRITE('A': 4, LA: 5, '. ');                           00058500           
590                   IF LENGTH = 0                                         00058600           
591                   THEN                                                  00058700           
592                     WRITELN                                             00058800           
593                   ELSE                                                  00058900           
594                     WRITELN(IMAGE: LENGTH);                             00059000           
595               END;                                                      00059100           
596               WITH PB^ DO                                               00059200           
597                 BEGIN                                                   00059300           
598                   WRITE('B': 4, LB: 5, '. ');                           00059400           
599                   IF LENGTH = 0                                         00059500           
600                   THEN                                                  00059600           
601                     WRITELN                                             00059700           
602                   ELSE                                                  00059800           
603                     WRITELN(IMAGE: LENGTH);                             00059900           
604               END;                                                      00060000           
605               UNPACK(PA^.IMAGE, TEMPA, 1);                              00060100           
606               UNPACK(PB^.IMAGE, TEMPB, 1);                              00060200           
607               IF PA^.LENGTH > PB^.LENGTH                                00060300           
608               THEN                                                      00060400           
609                 MAXCOL := PA^.LENGTH                                    00060500           
610               ELSE                                                      00060600           
611                 MAXCOL := PB^.LENGTH;                                   00060700           
612               WRITE(' ': 11)                                            00060800           
613                 (* 11 SPACES USED FOR FILE NAME AND LINE NUMBER *);     00060900           
614               FOR COL := 1 TO MAXCOL DO                                 00061000           
615                 IF TEMPA[COL] = TEMPB[COL]                              00061100           
616                 THEN                                                    00061200           
617                   WRITE(' ')                                            00061300           
618                 ELSE                                                    00061400           
619                   WRITE('^');                                           00061500           
620               WRITELN;                                                  00061600           
621               WRITELN;                                                  00061700           
622               PA := PA^.NEXTLINE;                                       00061800           
623               LA := LA + 1;                                             00061900           
624               PB := PB^.NEXTLINE;                                       00062000           
625               LB := LB + 1                                              00062100           
626             UNTIL (PA = A.CURSOR) OR (PA = NIL)                         00062200           
627           END (* WRITEPAIRS *);                                         00062300           
628                                                                         00062400           
629           PROCEDURE PRINTEXTRATEXT(VAR X, Y: STREAM);                   00062500           
630                                                                         00062600           
631           BEGIN (* PRINTEXTRATEXT *)                                    00062700           
632             WITH X, NAME DO                                             00062800           
633               WRITE('     EXTRA TEXT ON ', ACTUAL: LEN, ', ');          00062900           
634             WITH Y, NAME DO                                             00063000           
635               IF HEAD = NIL                                             00063100           
636               THEN                                                      00063200           
637                 WRITELN('BEFORE END OF FILE ON ', ACTUAL: LEN)          00063300           
638               ELSE                                                      00063400           
639                 WRITELN('BETWEEN LINES ', HEADLINENO - 1: 1,            00063500           
640                   ' AND ', HEADLINENO: 1, ' OF ', ACTUAL: LEN);         00063600           
641             WRITELN;                                                    00063700           
642             WRITETEXT(X, ' ')                                           00063800           
643           END (* PRINTEXTRATEXT *);                                     00063900           
644                                                                         00064000           
645         BEGIN (* PRINTDIFFERENCES *)                                    00064100           
646           WRITELN('***********************************': 46);           00064200           
647           WITH A DO                                                     00064300           
648             EMPTYA := (HEAD = CURSOR);                                  00064400           
649           WITH B DO                                                     00064500           
650             EMPTYB := (HEAD = CURSOR);                                  00064600           
651           IF EMPTYA OR EMPTYB                                           00064700           
652           THEN                                                          00064800           
653             IF EMPTYA                                                   00064900           
654             THEN                                                        00065000           
655               PRINTEXTRATEXT(B, A)                                      00065100           
656             ELSE                                                        00065200           
657               PRINTEXTRATEXT(A, B)                                      00065300           
658           ELSE                                                          00065400           
659             BEGIN                                                       00065500           
660               WRITE('     MISMATCH:');                                  00065600           
661               WRITE(' ', A.NAME.ACTUAL: A.NAME.LEN, ' ');               00065700           
662               WRITELINENO(A);                                           00065800           
663               WRITE(' <NOT EQUAL TO>');                                 00065900           
664               WRITE(' ', B.NAME.ACTUAL: B.NAME.LEN, ' ');               00066000           
665               WRITELINENO(B);                                           00066100           
666               WRITELN(':');                                             00066200           
667               WRITELN;                                                  00066300           
668               IF MARKUNEQUALCOLUMNS AND                                 00066400           
669                 ((A.CURSORLINENO - A.HEADLINENO) =                      00066500           
670                  (B.CURSORLINENO - B.HEADLINENO))                       00066600           
671               THEN                                                      00066700           
672                 WRITEPAIRS(A.HEAD, B.HEAD, A.HEADLINENO, B.HEADLINENO)  00066800           
673               ELSE                                                      00066900           
674                 BEGIN                                                   00067000           
675                   WRITETEXT(A, ' ');                                    00067100           
676                   WRITETEXT(B, ' ')                                     00067200           
677                 END;                                                    00067300           
678             END                                                         00067400           
679         END (*PRINTDIFFERENCES*);                                       00067500           
680                                                                         00067600           
681         PROCEDURE PRINTMODS;                                            00067700           
682                                                                         00067800           
683           PROCEDURE WRITELINEID(LINEID: LINEIDENTIFICATION);            00067900           
684                                                                         00068000           
685             VAR                                                         00068100           
686               C: 0..IDENTLENGTH;                                        00068200           
687                                                                         00068300           
688           BEGIN (* WRITELINEID *)                                       00068400           
689             WITH LINEID DO                                              00068500           
690               BEGIN                                                     00068600           
691                 IF IDENT[IDENTLENGTH] = ' '                             00068700           
692                 THEN                                                    00068800           
693                   BEGIN                                                 00068900           
694                     C := 1;                                             00069000           
695                     WHILE IDENT[C] <> ' ' DO                            00069100           
696                       BEGIN                                             00069200           
697                         WRITE(MODS, IDENT[C]);                          00069300           
698                         C := C + 1                                      00069400           
699                       END                                               00069500           
700                   END                                                   00069600           
701                 ELSE                                                    00069700           
702                   WRITE(MODS, IDENT);                                   00069800           
703                 WRITE(MODS, '.', NUMBER: 1)                             00069900           
704               END                                                       00070000           
705           END (* WRITELINEID *);                                        00070100           
706                                                                         00070200           
707         BEGIN (* PRINTMODS *)                                           00070300           
708           WITH A DO                                                     00070400           
709             IF HEAD = CURSOR                                            00070500           
710             THEN                                                        00070600           
711               BEGIN                                                     00070700           
712                 WRITE(MODS, '*INSERT,');                                00070800           
713                 WRITELINEID(LINEIDPREVIOUS);                            00070900           
714                 WRITELN(MODS)                                           00071000           
715               END                                                       00071100           
716             ELSE                                                        00071200           
717               BEGIN                                                     00071300           
718                 WRITE(MODS, '*DELETE,');                                00071400           
719                 WRITELINEID(HEAD^.LINEID);                              00071500           
720                 IF CURSORPREVIOUS <> NIL                                00071600           
721                 THEN                                                    00071700           
722                   IF (CURSORPREVIOUS^.LINEID.IDENT <>                   00071800           
723                       HEAD^.LINEID.IDENT) OR                            00071900           
724                      (CURSORPREVIOUS^.LINEID.NUMBER <>                  00072000           
725                       HEAD^.LINEID.NUMBER)                              00072100           
726                   THEN                                                  00072200           
727                     BEGIN                                               00072300           
728                       WRITE(MODS, ',');                                 00072400           
729                       WRITELINEID(CURSORPREVIOUS^.LINEID)               00072500           
730                     END;                                                00072600           
731                 WRITELN(MODS)                                           00072700           
732               END;                                                      00072800           
733           WITH B DO                                                     00072900           
734             IF HEAD <> CURSOR THEN                                      00073000           
735               WRITETEXT(B, ' ')                                         00073100           
736         END (* PRINTMODS *);                                            00073200           
737                                                                         00073300           
738         PROCEDURE PRINTFLAGS;                                           00073400           
739                                                                         00073500           
740         BEGIN (* PRINTFLBGS *)                                          00073600           
741           WITH A DO                                                     00073700           
742             IF HEAD <> CURSOR THEN                                      00073800           
743               WRITETEXT(A, 'D');                                        00073900           
744           WITH B DO                                                     00074000           
745             IF HEAD <> CURSOR THEN                                      00074100           
746               WRITETEXT(B, 'A')                                         00074200           
747         END (* PRINTFLAGS *);                                           00074300           
748                                                                         00074400           
749       BEGIN (* PRINTMISMATCH *)                                         00074500           
750         CASE OPTIONS OF                                                 00074600           
751           DIFFERENCES:                                                  00074700           
752             PRINTDIFFERENCES;                                           00074800           
753           FLAGS:                                                        00074900           
754             PRINTFLAGS;                                                 00075000           
755           MODIFICATIONS:                                                00075100           
756             PRINTMODS                                                   00075200           
757         END                                                             00075300           
758       END (* PRINTMISMATCH *);                                          00075400           
759                                                                         00075500           
760     BEGIN (* FINDMATCH *)                                               00075600           
761       (* NOT MATCH *)                                                   00075700           
762       ADVANCEB := TRUE;                                                 00075800           
763       REPEAT                                                            00075900           
764         IF NOT ENDOFFILE                                                00076000           
765         THEN                                                            00076100           
766           ADVANCEB := NOT ADVANCEB                                      00076200           
767         ELSE                                                            00076300           
768           ADVANCEB := ENDSTREAM(A);                                     00076400           
769         IF ADVANCEB                                                     00076500           
770         THEN                                                            00076600           
771           SEARCH(A, FILEA, B, FILEB)                                    00076700           
772         ELSE                                                            00076800           
773           SEARCH(B, FILEB, A, FILEA)                                    00076900           
774       UNTIL MATCH;                                                      00077000           
775       PRINTMISMATCH;                                                    00077100           
776     END (* FINDMATCH *);                                                00077200           
777                                                                         00077300           
778   BEGIN (* COMPAREFILES *)                                              00077400           
779     MATCH := TRUE (* I.E. BEGINNINGS OF FILES MATCH *);                 00077500           
780     REPEAT                                                              00077600           
781       IF MATCH                                                          00077700           
782       THEN                                                              00077800           
783         FINDMISMATCH                                                    00077900           
784       ELSE                                                              00078000           
785         BEGIN                                                           00078100           
786           SAME := FALSE;                                                00078200           
787           FINDMATCH                                                     00078300           
788         END                                                             00078400           
789     UNTIL ENDOFFILE AND MATCH;                                          00078500           
790     MARK(A);                                                            00078600           
791     MARK(B) (* MARK END OF FILES, THEREBY DISPOSING BUFFERS *);         00078700           
792   END (* COMPAREFILES *);                                               00078800           
793                                                                         00078900           
794     PROCEDURE FILENAME(VAR F: TEXT; VAR N: ALFA30);                     00078910           
795       EXTERNAL;                                                         00078920           
796                                                                         00078930           
797   PROCEDURE INITIALIZE;                                                 00079000           
798                                                                         00079100           
799     TYPE                                                                00079200           
800       CH80 = PACKED ARRAY [1..80] OF CHAR;                              00079300           
801       SETTING =                                                         00079400           
802         PACKED RECORD                                                   00079500           
803           CASE SWITCH: BOOLEAN OF                                       00079600           
804             TRUE: (ONOFF: CHAR);                                        00079700           
805             FALSE: (SIZE: 0..999999)                                    00079800           
806         END;                                                            00079900           
807                                                                         00080000           
808     VAR                                                                 00080100           
809     NOW : ARRAY[0..5] OF INTEGER;                                       00080200           
810       CS: CH80;                                                         00080300           
811       S: SETTING;                                                       00080400           
812       OPTS: BOOLEAN (* MUTUALLY EXCLUDE D, F, AND M OPTIONS *);         00080500           
813                                                                         00080600           
814                                                                         00080900           
815     FUNCTION OPTION(NAME: CHAR; VAR S: SETTING): BOOLEAN;               00081000           
816     VAR                                                                 00081010           
817       CSI : 1..81;                                                      00081012           
818       FOUND : BOOLEAN;                                                  00081014           
819     BEGIN                                                               00081016           
820       CSI := 1;                                                         00081018           
821       FOUND := FALSE;                                                   00081020           
822       OPTION := FALSE;                                                  00081022           
823       WHILE (CSI < 73) AND (NOT FOUND) DO BEGIN                         00081024           
824         WHILE ((CS[CSI] = ' ') OR (CS[CSI] = ',')) AND (CSI<73) DO BEGIN00081026           
825           CSI := CSI + 1;                                               00081028           
826         END;                                                            00081030           
827         IF (CS[CSI] = NAME) THEN BEGIN                                  00081032           
828           CASE CS[CSI] OF                                               00081034           
829           'D','F','P':                                                  00081036           
830             BEGIN                                                       00081037           
831               OPTION := TRUE;                                           00081038           
832               FOUND := TRUE;                                            00081040           
833             END;                                                        00081041           
834           'C','W':                                                      00081042           
835             BEGIN                                                       00081043           
836               OPTION := TRUE;                                           00081044           
837               FOUND := TRUE;                                            00081046           
838               S.SIZE := 0;                                              00081048           
839               CSI := CSI + 1;                                           00081049           
840               WHILE ((CS[CSI] = ' ') AND (CSI<73)) DO BEGIN             00081050           
841                 CSI := CSI+1;                                           00081052           
842               END;                                                      00081054           
843               IF (CSI>=73) THEN S.SWITCH := TRUE                        00081056           
844               ELSE                                                      00081058           
845                 WHILE (CS[CSI] IN ['0'..'9']) AND (CSI<73) DO BEGIN     00081060           
846                   S.SIZE := S.SIZE*10 + ORD(CS[CSI])-ORD('0');          00081062           
847                   CSI := CSI+1;                                         00081064           
848                 END;                                                    00081066           
849             END;                                                        00081067           
850           OTHERWISE                                                     00081068           
851           END;                                                          00081070           
852         END ELSE BEGIN                                                  00081072           
853           CSI := CSI+1;                                                 00081074           
854         END;                                                            00081076           
855       END;                                                              00081078           
856     END;   (* OPTION *)                                                 00081080           
857                                                                         00081200           
858     PROCEDURE ERROR;                                                    00081600           
859                                                                         00081700           
860     BEGIN (* ERROR *)                                                   00081800           
861       WRITELN(' COMPARE CONTROL STATEMENT ERROR.');                     00081900           
862       HALT;                                                             00081910           
863     END (* ERROR *);                                                    00082000           
864                                                                         00082100           
865     PROCEDURE INITSTREAM(VAR X: STREAM; VAR FILEX: TEXT; CH: CHAR);     00082200           
866                                                                         00082300           
867     BEGIN (* INITSTREAM *)                                              00082400           
868       WITH X, NAME DO                                                   00082500           
869         BEGIN                                                           00082600           
870           C := CH;                                                      00082700           
871           FILENAME(FILEX, ACTUAL);                                      00082800           
872           LEN := 30;                                                    00082900           
873           WHILE (ACTUAL[LEN] IN [' ',CHR(0)]) AND (LEN > 1) DO          00083000           
874             LEN := LEN - 1;                                             00083100           
875           CURSORLINENO := 0;                                            00083200           
876           HEADLINENO := 0;                                              00083300           
877           TAILLINENO := 0;                                              00083400           
878           CURSOR := NIL;                                                00083500           
879           HEAD := NIL;                                                  00083600           
880           TAIL := NIL;                                                  00083700           
881           RESET(FILEX);                                                 00083800           
882           ENDFILE := EOF(FILEX)                                         00083900           
883         END                                                             00084000           
884     END (* INITSTREAM *);                                               00084100           
885                                                                         00084200           
886   BEGIN (* INITIALIZE *)                                                00084300           
887     OPTIONS := DIFFERENCES;                                             00084400           
888     LINELENGTH := 72;                                                   00084500           
889     MINLINESFORMATCH := 6;                                              00084600           
890     MARKUNEQUALCOLUMNS := FALSE;                                        00084700           
891     RESET(INPUT);                                                       00084800           
892     CS := '  ';                                                         00084805           
893     READLN(INPUT,CS);                                                   00084810           
894     OPTS := FALSE;                                                      00084900           
895     IF OPTION('D', S) THEN                                              00085000           
896       BEGIN                                                             00085100           
897         OPTIONS := DIFFERENCES;                                         00085200           
898         OPTS := TRUE                                                    00085300           
899       END;                                                              00085400           
900     IF OPTION('F', S) THEN                                              00085500           
901       IF OPTS                                                           00085600           
902       THEN                                                              00085700           
903         ERROR                                                           00085800           
904       ELSE                                                              00085900           
905         BEGIN                                                           00086000           
906           OPTIONS := FLAGS;                                             00086100           
907           OPTS := TRUE                                                  00086200           
908         END;                                                            00086300           
909     IF OPTION('M', S) THEN                                              00086400           
910       IF OPTS                                                           00086500           
911       THEN                                                              00086600           
912         ERROR                                                           00086700           
913       ELSE                                                              00086800           
914         OPTIONS := MODIFICATIONS;                                       00086900           
915     IF OPTION('P', S) THEN                                              00087000           
916       MARKUNEQUALCOLUMNS := TRUE;                                       00087100           
917     IF OPTION('W', S) THEN                                              00087200           
918       IF NOT S.SWITCH                                                   00087300           
919       THEN                                                              00087400           
920         IF (S.SIZE < 10) OR (S.SIZE > MAXLENGTH)                        00087500           
921         THEN                                                            00087600           
922           ERROR                                                         00087700           
923         ELSE                                                            00087800           
924           LINELENGTH := S.SIZE                                          00087900           
925       ELSE                                                              00088000           
926         ERROR;                                                          00088100           
927     IF OPTION('C', S) THEN                                              00088200           
928       IF NOT S.SWITCH                                                   00088300           
929       THEN                                                              00088400           
930         IF (S.SIZE < 1) OR (S.SIZE > 100)                               00088500           
931         THEN                                                            00088600           
932           ERROR                                                         00088700           
933         ELSE                                                            00088800           
934           MINLINESFORMATCH := S.SIZE                                    00088900           
935       ELSE                                                              00089000           
936         ERROR;                                                          00089100           
937     INITSTREAM(A, FILEA, 'A');                                          00089400           
938     INITSTREAM(B, FILEB, 'B');                                          00089500           
939     ENDOFFILE := A.ENDFILE OR B.ENDFILE;                                00089600           
940     LINESTOOLONG := FALSE;                                              00089700           
941     FREELINES := NIL;                                                   00089800           
942     WITH TEMPLINE DO                                                    00089900           
943       BEGIN                                                             00090000           
944         LASTLINELENGTH := MAXLENGTH;                                    00090100           
945         IMAGE[0] := 'X' (* SENTINEL *);                                 00090200           
946       END;                                                              00090300           
947     TIMESTAMP(NOW);                                                     00090400           
948     WRITELN('    ', CS: 72, ' ', NOW[0]:2,'/',NOW[1]:2,'/',NOW[2]:2,'/',00090700           
949       '  ',NOW[3]:2,':',NOW[4]:2,':',NOW[5]:2);                         00090710           
950     WRITELN('     COMPARE VERSION ', VERSION,                           00090800           
951       '(': 26, COMPILEDATE, ')');                                       00090900           
952     WRITELN;                                                            00091000           
953     WRITE('     OUTPUT OPTION    = ');                                  00091100           
954     CASE OPTIONS OF                                                     00091200           
955       DIFFERENCES:                                                      00091300           
956         WRITE('DIFFERENCES.');                                          00091400           
957       FLAGS:                                                            00091500           
958         WRITE('FLAGS.');                                                00091600           
959       MODIFICATIONS:                                                    00091700           
960         WRITE('MODIFICATIONS.')                                         00091800           
961     END;                                                                00091900           
962     WRITELN;                                                            00092000           
963     WRITELN('     INPUT LINE WIDTH = ', LINELENGTH: 1, ' CHARACTERS.'); 00092100           
964     WRITELN('     MATCH CRITERION  = ', MINLINESFORMATCH: 1, ' LINES.');00092200           
965     WRITELN;                                                            00092300           
966     WRITELN('     FILEA: ', A.NAME.ACTUAL:A.NAME.LEN);                  00092400           
967     WRITELN('     FILEB: ', B.NAME.ACTUAL:B.NAME.LEN);                  00092500           
968     WRITELN;                                                            00092600           
969     WRITELN                                                             00092700           
970   END (* INITIALIZE *);                                                 00092800           
971                                                                         00092900           
972 BEGIN (* COMPARE *)                                                     00093000           
973   INITIALIZE;                                                           00093100           
974   IF A.ENDFILE THEN                                                     00093200           
975     WRITELN('     ', A.NAME.ACTUAL: A.NAME.LEN, ' IS EMPTY.');          00093300           
976   IF B.ENDFILE THEN                                                     00093400           
977     WRITELN('     ', B.NAME.ACTUAL: B.NAME.LEN, ' IS EMPTY.');          00093500           
978   IF NOT ENDOFFILE THEN                                                 00093600           
979     BEGIN                                                               00093700           
980       SAME := TRUE;                                                     00093800           
981       COMPAREFILES;                                                     00093900           
982       IF SAME THEN                                                      00094000           
983         WRITELN('     NO DIFFERENCES.');                                00094100           
984       IF LINESTOOLONG AND (OPTIONS = DIFFERENCES) THEN                  00094200           
985         BEGIN                                                           00094300           
986           WRITELN;                                                      00094400           
987           WRITELN(' WARNING:  SOME LINES WERE LONGER THAN ',            00094500           
988             LINELENGTH: 1, ' CHARACTERS.');                             00094600           
989           WRITELN('           THEY WERE NOT CHECKED PAST THAT POINT.'); 00094700           
990         END;                                                            00094800           
991     END                                                                 00094900           
992 END (* COMPARE *).                                                      00095000           