CDECK DECLS

C	FILCOM
C
C	THIS PROGRAM WILL COMPARE TWO FILES LINE BY LINE AND WILL PRINT
C	LINES THAT DIFFER.
C
C	LOGICAL VARIABLES BLK, CLN, SPC, AND COM ARE SET INTERACTIVELY TO
C	IGNORE BLANK LINES, LINES THAT BEGIN WITH A DESIGNATED COMMENT
C	CHARACTER, SPACES, AND ALL CHARACTERS FOLLOWING A DESIGNATED
C	BEGIN-COMMENT CHARACTER.
C
C	RECORDS FROM THE TWO INPUT FILES THAT DO NOT MATCH ARE STORED
C	IN BLOCKS IN THE ARRAY HEAP WHICH GROWS AS NECESSARY TO HOLD
C	MORE UNMATCHING LINES.  HEAP BLOCKS ARE OF SIZE &BLKSIZ+1,
C	AND EACH BLOCK IS LINKED TO THE NEXT BLOCK FOR THAT FILE
C	USING THE FINAL WORD IN THE BLOCK TO HOLD THE HEAP
C	INDEX OF THE FIRST WORD OF THE NEXT BLOCK.
C
C	ONE RECORD FROM ONE FILE IS THOUGHT
C	OF AS A VECTOR, AND IS COMPARED TO ALL PREVIOUS UNMATCHED
C	LINES FROM THE OTHER FILE, THESE LINES BEING THOUGHT OF AS
C	AN ARRAY.  IF NO MATCH IS FOUND THE VECTOR LINE IS STORED
C	IN THE CURRENT HEAP BLOCK FOR THAT FILE, THE FILE WITH THE
C	FEWEST STORED UNMATCHED LINES IS THOUGHT OF AS THE VECTOR,
C	AND THE PROCESS IS REPEATED.

$ EOLCHAR '[';

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C				C
C	SWITCHES		C
C				C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

$ SWITCH CDC6600, VAX;
$ SWITCH DEBUG;
$ SWITCH TRACE;

$ SET VAX;
$ RESET CDC6600;

$ RESET DEBUG;
$ RESET TRACE;


CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C					C
C	MACHINE DEPENDENT VARIABLES	C
C					C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

$ IF CDC6600 THEN
$ QUOTEX;
$ CNTR WDSPL: 10;		[MACHINE WORDS PER LINE IN THE INPUT FILE]
$ CNTR CHPWD: 10;		[CHARACTERS PER MACHINE WORD]
$ END; [IF CDC6600]

$ IF VAX THEN
$ NOQUOTEX;
$ CNTR WDSPL: 33;
$ CNTR CHPWD: 4;
$ END; [IF VAX]

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C				C
C	I/O UNITS		C
C				C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

C INPUT FILES MUST BE ON UNITS ONE AND TWO !!

$ STRING	LUOUT: 3,		[DIFFERENCES FILE]
$		LUIN:4,			[OPTIONS INPUT]
$		LUPROMPT:5,		[PROMPTS FOR OPTIONS]
$		LUDEBUG:6;		[DEBUG OUTPUT]
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C				C
C	MACROS			C
C				C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

$ MACRO HEAP <
$	INTEGER HEAP(&HEAPSZ)
$	COMMON HEAP
$ >;

$ MACRO HEAPVARS <
$	INTEGER	HEAPPT,		[PTR TO NEXT FREE WORD IN HEAP]
$     1		HEAPTP,		[PTR TO LAST FREE WORD IN HEAP]
$     2		OLDLEN,		[ORIGINAL FIELD LENGTH (SET BY ALLOC)]
$     3		NFL		[NEW FIELD LENGTH (SET BY ALLOC IF EXPANSION NECESSARY)]
$	COMMON /HEAPV/HEAPPT,HEAPTP,OLDLEN,NFL
$ >;

$ MACRO NOALLOC <
$	INTEGER NOALLOC		[TRUE IF NO CORE ALLOCATION DONE YET]
$	COMMON /NOALLOC/ NOALLOC
$ >;

$ MACRO FLAGS <
$	INTEGER DIFF		[TRUE IF DIFFERENCES FOUND BETWEEN FILES]
$	COMMON /FLAGS/DIFF
$ >;

$ MACRO SPACES <
$	INTEGER SPACES
$$ IF CDC6600 THEN
$	DATA SPACES /10H          /
$$ END; [IF CDC6600]
$$ IF VAX THEN
$	DATA SPACES /4H    /
$$ END; [IF VAX]
$ >;

$ MACRO SPACE <
$	INTEGER SPACE
$	DATA SPACE /1H /
$ >;

$ MACRO TAB <
$$ IF CDC6600 THEN
$$ ELSE
$	INTEGER TAB
$	DATA TAB /1H	/
$$ END; [IF CDC6600 THEN ELSE]
$ >;

$ MACRO SWITCHES <
$	LOGICAL BLK,		[TRUE IF BLANK LINES ARE TO BE IGNORED]
$     1		CLN,		[TRUE IF LINES BEGINNING WITH A DESIGNATED COMMENT CHAR ARE TO BE IGNORED]
$     2		SPC,		[TRUE IF SPACES (AND TABS) ARE TO BE IGNORED]
$     3		COM		[TRUE IF ALL TEXT FOLLOWING A DESIGNATED COMMENT CHAR IS TO BE IGNORED]
$	COMMON /SWITCH/ BLK,CLN,SPC,COM
$ >;

$ MACRO PARAMS <
$	INTEGER	CLCHAR,	[CHAR FOR CLN SWITCH]
$     1		EOLCHR	[CHAR FOR COM SWITCH]
$	COMMON /PARAMS/ CLCHAR,EOLCHR
$ >;


$ CNTR LINLEN: 1;		[NUMBER OF CHARACTERS PER LINE]
$ CNTRMUL LINLEN, &WDSPL, &CHPWD;

$ CNTR LSPBLK: 100;		[LINES PER BLOCK OF HEAP STORAGE]
$ CNTR BLKSIZ: 1;
$ CNTRMUL BLKSIZ, &WDSPL, &LSPBLK;	[WORDS PER BLOCK OF HEAP STORAGE]
$ CNTRADD BLKSIZ, 1;			[PLUS ONE FOR LINK WORD]
$ CNTR BLK2SIZ: 1;
$ CNTRMUL BLK2SIZ, &BLKSIZ, 2;		[NUMBER OF WORDS IN TWO HEAP BLOCKS]

$ IF CDC6600 THEN
$ CNTR HEAPSZ: &BLK2SIZ;		[ORIGINAL SIZE OF HEAP]
$ END; [IF CDC6600]

$ IF VAX THEN
$ CNTR HEAPSZ: 100000;
$ END; [IF VAX]


CDECK MAIN

$ IF CDC6600 THEN
	PROGRAM FILCOM(IN1,IN2,OUT1,
     *			INPUT,OUTPUT,
     *			DEBUG,
     1			TAPE1=IN1,TAPE2=IN2,
     2			TAPE&LUOUT=OUT1,
     *			TAPE&LUIN=INPUT,TAPE&LUPROMPT=OUTPUT,
     *			TAPE&LUDEBUG=DEBUG)
$ END; [IF CDC6600]

$ IF VAX THEN
	PROGRAM FILCOM
$ END; [IF VAX]

	LOGICAL FREEZE,		[TRUE IF A FILE IS AT EOF]
     2		ENDFIL		[ARG TO SUBROUTINE READ - TRUE IF READ CAUSED EOF]

	INTEGER POINTER(2),	[HEAP INDEX OF CURRENT LINE]
     1		COUNTER(2),	[NUMBER OF UNMATCHED LINES]
     2		FIRST(2),	[HEAP INDEX OF FIRST LINE OF FIRST BLOCK]
     3		FIRDIF(2),	[HEAP INDEX OF FIRST UNMATCHED LINE]
     5		TEMP,
     6		MATCH,
     7		ENDM,
     C		ARRAY,		[WHICH FILE IS GOING INTO THE ARRAY]
     D		VECTOR,		[WHICH FILE IS GOING INTO THE VECTOR]
     E		ALLOC,		[FUNCTION - ALLOCATES MORE CORE]
     F		COMPARE		[FUNCTION - RETURNS HEAP INDEX OF MATCHING LINE]

	INTEGER SAVPNT		[SAVES POINTER(VECTOR) FOR RESETTING IF EOF FROM READ]

$ HEAP;
$ HEAPVARS;
$ NOALLOC;
$ FLAGS;
$ PARAMS;
$ SWITCHES;

	DATA NOALLOC /.TRUE./

$ IF VAX THEN
	CALL OPENF					[GO OPEN FILES]
$ END; [IF VAX]

	CALL GETOPT					[GET SWITCH VALUES AND PARAMETERS]

C INITIALIZE

	HEAPTP = &BLK2SIZ
	HEAPPT = HEAPTP + 1
	DIFF = .FALSE.
	FIRST(1) = 1
	FIRST(2) = &BLKSIZ + 1
	ARRAY = 1
	VECTOR = 2

10	CALL DEALLOC					[RETURN EXTRA CORE IF ANY]
$ IF DEBUG THEN
	WRITE(&LUDEBUG,11)
11	FORMAT(' AT LINE 10')
$ END; [IF DEBUG]
	POINTER(ARRAY) = FIRST(ARRAY)
	POINTER(VECTOR) = FIRST(VECTOR) - &WDSPL	[POINTER(VECTOR) IS INCREMENTED BEFORE READING]
	FIRDIF(ARRAY) = FIRST(ARRAY)
	FIRDIF(VECTOR) = FIRST(VECTOR)
	COUNTER(ARRAY) = 0
	COUNTER(VECTOR) = 0

C READ A LINE INTO THE ARRAY

	CALL READ(ARRAY,POINTER(ARRAY),ENDFIL)
	IF(ENDFIL)GOTO 1000
	COUNTER(ARRAY) = COUNTER(ARRAY) + 1
	GOTO 60

C HERE SWAP FILES IF THERE ARE MORE LINES IN THE VECTOR,
C AND NEITHER FILE IS AT EOF

50	IF(COUNTER(ARRAY) .GE. COUNTER(VECTOR))GOTO 60
	IF(FREEZE)GOTO 60
55	TEMP = ARRAY
	ARRAY = VECTOR
	VECTOR = TEMP

C HERE READ A LINE INTO THE VECTOR
60	SAVPNT = POINTER(VECTOR)
	POINTER(VECTOR) = POINTER(VECTOR) + &WDSPL
	IF(MOD(POINTER(VECTOR),&BLKSIZ) .EQ. 0)			[IF CURRENT HEAP BLOCK IS FULL ...
     1		POINTER(VECTOR) = ALLOC(POINTER(VECTOR),&BLKSIZ) [ALLOCATE ANOTHER]
	CALL READ(VECTOR,POINTER(VECTOR),ENDFIL)
	IF(ENDFIL)GOTO 2000
	COUNTER(VECTOR) = COUNTER(VECTOR) + 1

C CALL COMPARE TO SEE IF THE NEW VECTOR LINE MATCHES ANY ARRAY LINES

	MATCH = COMPARE(FIRDIF(ARRAY),HEAP(POINTER(VECTOR)),COUNTER(ARRAY))
	IF(MATCH .EQ. 0)GOTO 50

C HERE IF MATCH WAS FOUND

	IF(COUNTER(ARRAY) .EQ. 1 .AND. COUNTER(VECTOR) .EQ. 1)GOTO 10	[IF NO PREVIOUS UNMATCHED LINES DONT OUTPUT ANYTHING]
	ENDM = POINTER(ARRAY)
	POINTER(ARRAY) = MATCH
	IF(COUNTER(VECTOR) .EQ. 1 .AND. MATCH .EQ.
     1		FIRDIF(ARRAY))GOTO 90				[DONT WRITE IF VECTOR LINE FIRST FOR THAT FILE
								[AND MATCHED LINE IS FIRST LINE FOR ARRAY FILE]
	CALL WRITE(1,FIRDIF(1),POINTER(1))
	CALL WRITE(2,FIRDIF(2),POINTER(2))
90	IF(MATCH .EQ. ENDM)GOTO 10
	FIRDIF(ARRAY) = MATCH + &WDSPL				[FIRST UNMATCHED LINE IS FIRST LINE AFTER MATCH]
	IF(MOD(FIRDIF(ARRAY),&BLKSIZ) .EQ. 0)
     1		FIRDIF(ARRAY) = HEAP(FIRDIF(ARRAY))		[CORRECT FOR HEAP BLOCK BOUNDARY IF NECESSARY]
	POINTER(ARRAY) = ENDM					[POINT TO LAST UNMATCHED LINE]
	CALL RESET(COUNTER(ARRAY),FIRDIF(ARRAY),POINTER(ARRAY))	[RESET COUNTER]
	POINTER(VECTOR) = FIRST(VECTOR) - &WDSPL
	FIRDIF(VECTOR) = FIRST(VECTOR)
	COUNTER(VECTOR) = 0
	GOTO 50

C HERE IF ARRAY FILE AT EOF
C
C ARRAY IS READ ONLY AFTER RESETTING BOTH ARRAY AND VECTOR.
C THUS THERE CAN BE NO PREVIOUS UNMATCHED LINES IN ARRAY,
C AND ALL LINES REMAINING IN THE VECTOR FILE ARE EXTRAS.

1000	FREEZE = .TRUE.
1010	SAVPNT = POINTER(VECTOR)
	POINTER(VECTOR) = POINTER(VECTOR) + &WDSPL
	IF(MOD(POINTER(VECTOR),&BLKSIZ) .EQ. 0)
     1		POINTER(VECTOR) = ALLOC(POINTER(VECTOR),&BLKSIZ)
	CALL READ(VECTOR,POINTER(VECTOR),ENDFIL)
	IF(ENDFIL)GOTO 2000
	COUNTER(VECTOR) = COUNTER(VECTOR) + 1
	DIFF = .TRUE.						[EXTRA LINES COUNT AS DIFFERENCES]
	GOTO 1010

C HERE IF THE VECTOR FILE IS AT EOF

2000	POINTER(VECTOR) = SAVPNT				[RESET POINTER]
	IF(FREEZE)GOTO 2010
	FREEZE = .TRUE.
	GOTO 55

2010	IF(COUNTER(1) .EQ. 0)GOTO 2020
	CALL WRITE(1,FIRDIF(1),POINTER(1))
2020	IF(COUNTER(2) .EQ. 0)GOTO 2030
	CALL WRITE(2,FIRDIF(2),POINTER(2))
2030	IF(DIFF)WRITE(&LUOUT,2035)
2035	FORMAT(//,1X,'%FILES ARE DIFFERENT')
	IF(.NOT. DIFF)WRITE(&LUOUT,2045)
2045	FORMAT(1X,'NO DIFFERENCES ENCOUNTERED')
	STOP
	END



CDECK READ

	SUBROUTINE READ(UNIT,TO,ENDFIL)

C READ ONE RECORD FROM THE INPUT FILE ON LOGICAL UNIT UNIT
C
C	COMMON AREAS ACCESSED
C
C		HEAP		[HEAP STORAGE]

$ HEAP;

	INTEGER UNIT,		[LOGICAL UNIT ON WHICH TO READ]
     1		TO		[HEAP INDEX INTO WHICH TO READ]

	LOGICAL ENDFIL		[TO BE SET IF THIS READ CAUSES EOF]

	LOGICAL CLINE,		[FUNCTION, RETURNS TRUE IF LINE BEGINS WITH
     *				[&CLINECHAR, OR FIRST NON-BLANK CHAR IS &COMNTCHAR]
     1		BLANK		[FUNCTION, RETURNS TRUE IF LINE IS BLANK]

	INTEGER I,J

$ IF TRACE THEN
	WRITE(&LUDEBUG,987)
987	FORMAT(' ENTER READ')
$ END; [IF TRACE]

	J = TO + &WDSPL - 1

$ IF CDC6600 THEN
10	READ(UNIT,20)(HEAP(I),I=TO,J)
	IF(EOF(UNIT) .NE. 0.0)GOTO 100
$ END; [IF CDC6600]

$ IF VAX THEN
10	READ(UNIT,20,END=100)(HEAP(I),I=TO,J)
$ END; [IF VAX]

20	FORMAT(&WDSPL.A&CHPWD)
	ENDFIL = .FALSE.
	IF(CLINE(HEAP(TO)))GOTO 10
	IF(BLANK(HEAP(TO)))GOTO 10
	RETURN
100	ENDFIL = .TRUE.
	RETURN
	END



CDECK COMPARE

	INTEGER FUNCTION COMPARE(START,VECTOR,N)

C COMPARE AN ARRAY OF LINES TO A SINGLE LINE
C RETURN 0 IF NO MATCH FOUND
C ELSE RETURN HEAP INDEX OF MATCHING LINE
C
C	COMMON AREAS ACCESSED
C
C		/FLAGS/DIFF		[TRUE IF DIFFERENCES FOUND]
C		/SWITCH/...		[SWITCHES FOR WHAT TO IGNORE]
C		/PARAMS/...		[VALUES FOR CLINECHAR AND CMNTCHAR]
C		HEAP			[HEAP STORAGE]

$ HEAP;
$ FLAGS;
$ SPACE;
$ TAB;
$ SWITCHES;
$ PARAMS;

	INTEGER START,		[HEAP INDEX OF FIRST LINE IN ARRAY]
     1		VECTOR(&WDSPL),	[SINGLE LINE]
     2		N,		[NUMBER OF UNMATCHED LINES IN ARRAY]
     3		I,J,K,L,M	[ASSORTED INDICES]


C NEED ARRAYS INTO WHICH TO DECODE A SINGLE ARRAY LINE AND THE
C SINGLE VECTOR LINE IF IGNORING SPACES AND/OR COMMENTS

	INTEGER A(&LINLEN),V(&LINLEN)




$ IF TRACE THEN
	WRITE(&LUDEBUG,9876)
9876	FORMAT(' ENTER COMPARE')
$ END; [IF TRACE]
$ IF DEBUG THEN
	WRITE(&LUDEBUG,987)VECTOR
987	FORMAT(' COMPARE: VECTOR=',&WDSPL.A&CHPWD)
$ END; [IF DEBUG]

	IF(COM .OR. SPC)GOTO 99
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C							C
C HERE IF NEITHER COMMENTS NOR SPACES ARE TO BE IGNORED C
C							C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

	K = START		[K POINTS TO CURRENT LINE OF ARRAY IN HEAP]
	DO 20 I=1,N
		DO 10 J= 1,&WDSPL
			IF(HEAP(K+J-1) .NE. VECTOR(J))GOTO 15
10		CONTINUE
		COMPARE = K
$ IF DEBUG THEN
		WRITE(&LUDEBUG,876)K
876		FORMAT(' COMPARE RETURNS ',1I5)
$ END; [IF DEBUG]
		RETURN
15		K = K + &WDSPL
		IF(MOD(K,&BLKSIZ) .EQ. 0)K=HEAP(K)
20	CONTINUE
	COMPARE = 0
	DIFF = .TRUE.
$ IF DEBUG THEN
	WRITE(&LUDEBUG,765)
765	FORMAT(' COMPARE RETURNS 0')
$ END; [IF DEBUG]
	RETURN
99	IF(SPC)GOTO 199

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C							C
C HERE IF COMMENTS ONLY ARE TO BE IGNORED		C
C							C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

100	DECODE(&LINLEN,110,VECTOR(1))V			[GET THE VECTOR IN A1 FORMAT]
110	FORMAT(&LINLEN.A1)
	K = START
	DO 190 I=1,N
		DECODE(&LINLEN,110,HEAP(K))A		[GET THE CURRENT ARRAY LINE IN A1 FORMAT]
		DO 150 J=1,&LINLEN
			IF(A(J) .EQ. EOLCHR .AND. V(J) .EQ. EOLCHR)
     1				GOTO 160
			IF(A(J) .NE. V(J))GOTO 180
150		CONTINUE
160		COMPARE = K
		RETURN
180		IF(A(J) .NE. EOLCHR .AND. V(J) .NE. EOLCHR)GOTO 185

C HERE IF THE REMAINDER OF ONE OF THE LINES IS A COMMENT
C IF THE OTHER LINE CONTAINS ONLY SPACES FROM HERE ON, CALL IT A MATCH

		IF(V(J) .EQ. EOLCHR)GOTO 182
		DO 181 L=J,&LINLEN
			IF(V(L) .NE. SPACE)GOTO 185
181		CONTINUE
		GOTO 160
182		DO 183 L=J,&LINLEN
			IF(A(L) .NE. SPACE)GOTO 185
183		CONTINUE
		GOTO 160
185		CONTINUE
		K = K + &WDSPL
		IF(MOD(K,&BLKSIZ) .EQ. 0)K = HEAP(K)
190	CONTINUE
	DIFF = .TRUE.
	COMPARE = 0
	RETURN
199	CONTINUE

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C							C
C HERE TO IGNORE SPACES AND MAYBE COMMENTS		C
C							C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

200	DECODE(&LINLEN,205,VECTOR(1))V
205	FORMAT(&LINLEN.A1)
	K = START
	DO 290 I=1,N
		L = 1
		DECODE(&LINLEN,205,HEAP(K))A
$ IF DEBUG THEN
		WRITE(&LUDEBUG,1234)A
1234		FORMAT(' ARRAY LINE:',&LINLEN.A1)
$ END; [IF DEBUG]
		DO 250 J=1,&LINLEN
			IF(A(J) .EQ. SPACE
$ IF VAX THEN
     1			.OR. A(J) .EQ. TAB
$ END; [IF VAX]
     X			)GOTO 250
210			IF(V(L) .EQ. SPACE
$ IF VAX THEN
     1			.OR. V(L) .EQ. TAB
$ END; [IF VAX]
     X			)GOTO 220
			IF(COM .AND. A(J) .EQ. EOLCHR)GOTO 260
			IF(COM .AND. V(L) .EQ. EOLCHR)GOTO 225
			IF(A(J) .NE. V(L))GOTO 280
C HERE IF A(J) = V(L)
			L = L + 1
			IF(L .LE. &LINLEN)GOTO 250
			IF(J .EQ. &LINLEN)GOTO 260
			GOTO 225
C HERE IF V(L) IS A SPACE
220			L = L + 1
			IF(L .LE. &LINLEN)GOTO 210
C HERE IF THROUGH WITH V - LOOK AT REMAINING A
225			DO 230 M = J,&LINLEN
				IF(COM .AND. A(M) .EQ. EOLCHR)GOTO 235
				IF(A(M) .NE. SPACE
$ IF VAX THEN
     1				.AND. A(M) .NE. TAB
$ END; [IF VAX]
     X				)GOTO 280
230			CONTINUE

C HERE IF MATCH

235			COMPARE = K
$ IF DEBUG THEN
			WRITE(&LUDEBUG,876)K
876			FORMAT(' COMPARE RETURNS ',1I5)
$ END; [IF DEBUG]
			RETURN
250		CONTINUE
C HERE IF DONE WITH A - LOOK AT REMAINING V
260		COMPARE = K
$ IF DEBUG THEN
		IF(L .GE. &LINLEN)WRITE(&LUDEBUG,876)K
$ END;
			IF(L .GE. &LINLEN)RETURN
			DO 270 M = L,&LINLEN
				IF(COM .AND. V(M) .EQ. EOLCHR)RETURN
				IF(V(M) .NE. SPACE
$ IF VAX THEN
     1				.AND. V(M) .NE. TAB
$ END; [IF VAX]
     X				)GOTO 280
270			CONTINUE
$ IF DEBUG THEN
			WRITE(&LUDEBUG,876)K
$ END; [IF DEBUG]
			RETURN
C HERE TO SET K TO POINT TO NEXT LINE IN HEAP
280		K = K + &WDSPL
		IF(MOD(K,&BLKSIZ) .EQ. 0)K = HEAP(K)
290	CONTINUE

	COMPARE = 0
$ IF DEBUG THEN
	WRITE(&LUDEBUG,765)
765	FORMAT(' COMPARE RETURNS 0')
$ END;
	DIFF = .TRUE.
	RETURN

	END


CDECK ALLOC

	INTEGER FUNCTION ALLOC(PTR,LENGTH)

C ALLOCATE MORE CORE IF NEEDED
C
C	COMMON AREAS ACCESSED
C
C	/HEAPV/	HEAPPT,		[PTR TO NEXT FREE WORD IN HEAP]
C		HEAPTP,		[PTR TO LAST FREE WORD IN HEAP
C		OLDLEN,		[ORIGINAL FIELD LENGTH]
C		NFL		[NEW FIELD LENGTH (SET HERE IF CORE EXPANDED)]
C	/NOALLOC/ NOALLOC	[TRUE IF FIRST TIME HERE]
C	HEAP		[HEAP STORAGE

$ HEAPVARS;
$ NOALLOC;
$ HEAP;

	INTEGER	PTR,		[HEAP INDEX OF LINK WORD TO BE SET TO START OF ALLOCATED BLOCK]
     1		LENGTH		[NUMBER OF WORDS TO ALLOCATE]

	INTEGER FL

$ IF TRACE THEN
	WRITE(&LUDEBUG,876)
876	FORMAT(' ENTER ALLOC')
$ END; [IF TRACE]

$ IF CDC6600 THEN
	IF(.NOT. NOALLOC)GOTO 100
	NOALLOC = .FALSE.
	OLDLEN = 0
	CALL XRFL(OLDLEN,0)
	HEAPTP = OLDLEN - LOCF(HEAP(1))
100	IF(HEAPPT + LENGTH .LE. HEAPTP)GOTO 1000

C HERE IF NECESSARY TO EXTEND FIELD LENGTH

	FL = 0
	CALL XRFL(FL,0)				[GET CURRENT FIELD LENGTH]
	NFL = ((FL + LENGTH + 511)/512)*512
	HEAPTP = HEAPTP + NFL - FL
	CALL XRFL(NFL,0)
	WRITE(&LUOUT,987)FL,NFL
987	FORMAT(' ALLOC: OLDFIELD LENGTH=',1I9,
     1		/,'        NEW FIELD LENGTH=',1I9)
$ END; [IF CDC6600]

1000	HEAP(PTR) = HEAPPT
	ALLOC = HEAPPT
	HEAPPT = HEAPPT + LENGTH

$ IF VAX THEN
	IF(HEAPPT .LE. &HEAPSZ)RETURN
	WRITE(&LUOUT,1010)
1010	FORMAT(' ?HEAP STORAGE EXHAUSTED')
	STOP
$ END; [IF VAX]

$ IF CDC6600 THEN
	RETURN
$ END; [IF CDC6600]
	END



CDECK DEALLOC

	SUBROUTINE DEALLOC

C RETURN FIELD TO ORIGINAL LENGTH
C
C	COMMON AREAS ACCESSED
C
C	/HEAPV/HEAPPT		[PTR TO NEXT FREE WORD IN HEAP]
C		HEAPTP		[PTR TO LAST FREE WORD IN HEAP
C		OLDLEN		[ORIGINAL FIELD LENGTH]
C		NFL		[NEW FIELD LENGTH (SET HERE IF CORE EXPANDED)]
C	/NOALLOC/ NOALLOC	[TRUE IF NO CORE ALLOCATION HAS BEEN DONE]

$ HEAPVARS;
$ NOALLOC;

$ IF TRACE THEN
	WRITE(&LUDEBUG,987)
987	FORMAT(' ENTER DEALLOC')
$ END; [IF TRACE]

$ IF CDC6600 THEN
	IF(NOALLOC)RETURN		[NO CORE ALLOCATION HAS BEEN DONE]
	IF(OLDLEN .EQ. NFL)RETURN	[DEALLOCATION HAS ALREADY BEEN DONE]
	WRITE(&LUOUT,10)OLDLEN
10	FORMAT(' DEALLOC: RESETTING FIELD LENGTH TO ',1I9)
	CALL XRFL(OLDLEN,0)
	NFL = OLDLEN
	HEAPTP = &BLK2SIZ
	HEAPPT = HEAPTP + 1
$ END; [IF CDC6600]

	RETURN
	END



CDECK WRITE

	SUBROUTINE WRITE(FILE,FROM,TO)

C WRITE OUT DIFFERING LINES
C
C	COMMON AREAS ACCESSED
C
C	HEAP			[HEAP STORAGE]

$ HEAP;
$ SPACES;

	INTEGER FILE,		[WHICH FILE'S LINES WE ARE WRITING]
     1		FROM,		[HEAP INDEX OF FIRST LINE]
     2		TO		[HEAP INDEX OF LAST LINE]

	INTEGER I,J,K,L,M	[INDICES]
	INTEGER DOTO		[DO LOOP INDEX (FOR THE STUPID CDC6600)]

$ IF DEBUG THEN
	WRITE(&LUDEBUG,987)FROM,TO
987	FORMAT(' FROM=',1I5,/,' TO=',1I5)
$ END; [IF DEBUG]
	IF(FILE .EQ. 1)WRITE(&LUOUT,10)
	IF(FILE .EQ. 2)WRITE(&LUOUT,20)
10	FORMAT(1X,14(1H*))
20	FORMAT(1X,3H***)
	J = FROM
25	CONTINUE				[START OF LOOP TO WRITE DIFFERING LINES]
		DOTO = &WDSPL
		DO 27 L = 1,DOTO			[LOOP TO TRUNCATE TRAILING SPACES]
			M = DOTO - L + 1		[LOOK AT WORDS IN REVERSE ORDER]
			IF(HEAP(J+M-1) .NE. SPACES)GOTO 28
27		CONTINUE
28		CONTINUE
		WRITE(&LUOUT,30)FILE,(HEAP(J+K-1),K=1,M)
30		FORMAT(1X,1I1,1H),5X,&WDSPL.A&CHPWD)
		IF(J .EQ. TO)RETURN
		J = J + &WDSPL
		IF(MOD(J,&BLKSIZ) .EQ. 0)J = HEAP(J)
	GOTO 25
	END



CDECK CLINE

	LOGICAL FUNCTION CLINE(LINE)

C SEE IF A LINE CONTAINS ONLY A COMMENT

$ SPACE;
$ SWITCHES;
$ PARAMS;
$ TAB;

	INTEGER LINE(&LINLEN)		[LINE TO SCAN]
	INTEGER CHAR(&CHPWD)		[VAR INTO WHICH TO DECODE EACH WORD OF LINE]
	INTEGER I,J			[INDICES]

$ IF TRACE THEN
	WRITE(&LUDEBUG,987)
987	FORMAT(' ENTER CLINE')
$ END; [IF TRACE]

	CLINE = .FALSE.
	IF(.NOT. CLN)RETURN
	CLINE = .TRUE.
	DECODE(&CHPWD,10,LINE(1))CHAR
10	FORMAT(&CHPWD.A1)
	IF(CHAR(1) .EQ. CLCHAR)RETURN		[LINE BEGINS WITH A LINE COMMENT CHAR]
	DO 50 I=1,&WDSPL
		DECODE(&CHPWD,10,LINE(I))CHAR
		DO 40 J=1,&CHPWD

			IF(CHAR(J) .EQ. SPACE
$ IF VAX THEN
     1			.OR. CHAR(J) .EQ. TAB
$ END; [IF VAX]
     X			)GOTO 40
			IF(CHAR(J) .EQ. EOLCHR)RETURN	[FIRST NON-BLANK CHAR IS A BEGIN COMMENT CHAR]
			CLINE = .FALSE.
			RETURN
40		CONTINUE
50	CONTINUE

C HERE IF LINE IS TOTALLY BLANK

	CLINE = .FALSE.
	RETURN
	END




CDECK BLANK


	LOGICAL FUNCTION BLANK(LINE)

C SEE IF A LINE CONTAINS ONLY SPACES AND/OR TABS

$ IF CDC6600 THEN		[NO TABS ON THIS MACHINE - BE FAST]
$ SPACES;
$ SWITCHES;

	INTEGER LINE(&WDSPL)				[LINE TO BE SCANNED]
	INTEGER I					[INDEX]

	BLANK = .FALSE.
	IF(.NOT. BLK)RETURN
	DO 10 I=1,&WDSPL
		IF(LINE(I) .NE. SPACES)RETURN
10	CONTINUE
	BLANK = .TRUE.
	RETURN
	END
$ END; [IF CDC6600]

$ IF VAX THEN

$ SPACE;
$ TAB;
$ SWITCHES;

	INTEGER LINE(&WDSPL)			[LINE TO BE SCANNED]
	INTEGER CHAR(&CHPWD)			[ARRAY INTO WHICH TO DECODE LINE]
	INTEGER I,J				[INDICES]

	BLANK = .FALSE.
	IF(.NOT. BLK)RETURN
	DO 50 I=1,&WDSPL
		DECODE(&CHPWD,10,LINE(I))CHAR
10		FORMAT(&CHPWD.A1)
		DO 40 J=1,&CHPWD
			IF(CHAR(J) .NE. SPACE
     1				.AND.
     2			   CHAR(J) .NE. TAB)RETURN
40		CONTINUE
50	CONTINUE
	BLANK = .TRUE.
	RETURN
	END
$ END; [IF VAX]




CDECK RESET

	SUBROUTINE RESET(COUNTER,BEGIN,END)

C COUNT NUMBER OF LINES IN HEAP BETWEEN BEGIN AND END INCLUSIVE
C
C	COMMON AREAS ACCESSED
C
C		HEAP			[HEAP STORAGE]

$ HEAP;

	INTEGER	COUNTER,	[VARIABLE TO BE RESET]
     1		BEGIN,		[HEAP INDEX OF FIRST LINE]
     2		END		[HEAP INDEX OF LAST LINE]

	INTEGER START		[USED TO AVOID CHANGING BEGIN]


	START = BEGIN
	COUNTER = 0

10	COUNTER = COUNTER + 1
	IF(START .EQ. END)RETURN
	START = START + &WDSPL
	IF(MOD(START,&BLKSIZ) .EQ. 0)START = HEAP(START)
	GOTO 10

	END

CDECK OPENF
$ IF VAX THEN
	SUBROUTINE OPENF

C OPEN FILES FOR THE VAX

	CHARACTER*36 FILNAM			[NAME OF FILE TO OPEN]
	INTEGER I				[INDEX]

	DO 50 I=1,2
		TYPE 10,I
10		FORMAT(' FILE',1I2,': ',$)
		ACCEPT 20,FILNAM
20		FORMAT(A)
		OPEN(UNIT=I,NAME=FILNAM,TYPE='OLD')
50	CONTINUE

	TYPE 60
60	FORMAT(' DIF FILE (<CR> MEANS TT:): ',$)
	ACCEPT 70,NAMLEN,FILNAM
70	FORMAT(Q,1A13)
	IF(NAMLEN .EQ. 0)OPEN(UNIT=&LUOUT,NAME='TT:',RECORDSIZE=200)
	IF(NAMLEN .NE. 0)OPEN(UNIT=&LUOUT,NAME=FILNAM,TYPE='NEW')

	OPEN(UNIT=&LUPROMPT,NAME='TT:')
	OPEN(UNIT=&LUIN,NAME='TT:')
$ IF DEBUG THEN
	OPEN(UNIT=&LUDEBUG,NAME='TT:',RECORDSIZE=200)
$ END; [IF DEBUG]

	RETURN
	END

$ END; [IF VAX]

CDECK GETOPT
	SUBROUTINE GETOPT

C GET SWITCH AND PARAMETER VALUES
C
C	COMMON AREAS ACCESSED
C
C	/SWITCH/BLK		[LOGICAL VARS FOR IGNORING BLANK LINES,
C		CLN		[COMMENT LINES,
C		SPC		[SPACES (AND TABS),
C		COM		[AND COMMENTS]
C
C	/PARAMS/CLCHAR		[CHARACTER WHICH IN COLUMN 1 MEANS A COMMENT LINE]
C		EOLCHAR		[CHARACTER WHICH MEANS TEXT TO END OF LINE IS A COMMENT]
$ SWITCHES;
$ PARAMS;

	WRITE(&LUPROMPT,101)
101	FORMAT(' IGNORE BLANK LINES? (T/F):',$)
	READ(&LUIN,100)BLK
	WRITE(&LUPROMPT,102)
102	FORMAT(' IGNORE COMMENT LINES? (T/F):',$)
	READ(&LUIN,100)CLN
	IF(CLN)WRITE(&LUPROMPT,103)
103	FORMAT(' COMMENT LINE CHAR:',$)
	IF(CLN)READ(&LUIN,200)CLCHAR
	WRITE(&LUPROMPT,104)
104	FORMAT(' IGNORE SPACES? (T/F):',$)
	READ(&LUIN,100)SPC
	WRITE(&LUPROMPT,105)
105	FORMAT(' IGNORE COMMENTS? (T/F):',$)
	READ(&LUIN,100)COM
	IF(COM)WRITE(&LUPROMPT,106)
106	FORMAT(' COMMENT CHARACTER:',$)
	IF(COM)READ(&LUIN,200)EOLCHR
100	FORMAT(1L)
200	FORMAT(1A1)

	RETURN
	END
