Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - utilities/redit.mac
There are 8 other files named redit.mac in the archive. Click here to see a list.
;<UTILITIES>REDIT.MAC.33,  4-Feb-81 02:45:35, Edit by ADMIN.MRC
; More "?Failed to find..." stuff
;<UTILITIES>REDIT.MAC.32,  4-Feb-81 02:38:39, Edit by ADMIN.MRC
; Fixed "?Failed to find..." message to not output a line feed at the end
;<MURPHY>REDIT.MAC.31,  6-Jun-77 22:58:49, EDIT BY MURPHY
;<MURPHY>REDIT.MAC.28,  1-APR-76 17:56:40, EDIT BY MURPHY

	TITLE REDIT
	SALL
	.DIRECT FLBLST
	SEARCH MONSYM,MACSYM
	.REQUIRE SYS:MACREL
	SUBTTL DEFINITIONS

DEFINE SCALL (NAM,ARGS)<
	..AC==T1
	IRP ARGS,<
	  MOVE ..AC,ARGS
	  ..AC=..AC+1>
	CALL NAM>

DEFINE MV (FRM,TO)<
	MOVE T1,FRM
	MOVEM T1,TO>

;GENERAL ERROR

DEFINE ERROR (TAG,MSG)<
	JRST [	TMSG <
MSG
>
		JRST TAG]>

;ERROR WITH JSYS MESSAGE

DEFINE ERRORJ (TAG,MSG)<
	JRST [	TMSG <
MSG, >
		CALL JSERRM
		JRST TAG]>

DEFINE TXTPTR (MSG)<POINT 7,[ASCIZ \MSG\]>
;INITIAL PARAMETERS

IMINDI==^D5			;MINIMUM DIFFERENCE
INMAT==^D5			;NUMBER LINES FOR MATCH
MAXCHL==^D120			;MAX CHARS/LINE

;ACS

T1=1
T2=2
T3=3
T4=4

P=17
;16,15 USED BY MACSYM
BP1=14				;BLOCK POINTER 1
BP2=13				;BLOCK POINTER 2
F=0				;FLAGS

;FLAGS

TOPF==1B0			;TOP OF FILE

;STRUCTURE OF POINTER BLOCK

BFA==0				;LINE POINTER TABLE ORIGIN
BFA2==1				;MID-POINT OF LINE POINTER TABLE
NL==2				;NEXT LINE IN LINE POINTER TABLE
FRE==3				;FREE WORD IN LINE POINTER TABLE
INJFN==4			;INPUT JFN
SFRE==5				;STRING FREE ORIGIN
SBFR==6				;STRING BUFFER ORIGIN
ESBFR==7			;END OF STRING BUFFER
INCNT==10			;INPUT BUFFER COUNT
IPTR==11			;INPUT BYTE POINTER
BFADR==12			;ADDRESS OF FILE BUFFER
paglin==13			;page number,,line number
ipagln==14			;paglin at start of difference
 NBPW==15			;NUMBER WORDS IN POINTER BLOCK
;STORAGE

PGSIZ==1000

	LOC 20000

MINDIF:	BLOCK 1			;MINIMUM NUMBER LINES DIFFERENCES OUTPUT
NMATCH:	BLOCK 1			;NUMBER LINES FOR MATCH AFTER DIFFERENCE
MAXDIF:	BLOCK 1			;MAXIMUM NUMBER LINES DIFFERENT
CNGNO:	BLOCK 1			;CHANGE NUMBER

;COMND STORAGE

CBFSIZ==^D200/5
CBFR:	BLOCK CBFSIZ		;COMMAND LINE BUFFER
ACBSIZ==^D200/5
ACBFR:	BLOCK ACBSIZ		;ATOM BUFFER
CBLK:	BLOCK .CMGJB+1		;COMMAND STATE BLOCK
GJBLK:	BLOCK .GJBFP+1

DEFDIR:	BLOCK 10
DEFNAM:	BLOCK 10
DEFEXT:	BLOCK 10
DEFVER:	BLOCK 10

INL1:	BLOCK 1			;FIRST LINE OF DIFFERENCE
INL2:	BLOCK 1			; "

BBP1:	BLOCK NBPW		;POINTER BLOCK
BBP2:	BLOCK NBPW

NLMAX==^D1000			;MAX NUMBER LINES BUFFERED
LPTR1:	BLOCK NLMAX*^D20		;LINE POINTER TABLES
LPTR2:	BLOCK NLMAX

NBUF==NLMAX*^D10		;SIZE OF STRING BUFFERS
BUF1:	BLOCK NBUF*^D10		;STRING BUFFERS
EBUF1:	BLOCK 0
BUF2:	BLOCK NBUF
EBUF2:	BLOCK 0

FBUF1:	BLOCK PGSIZ		;FILE BUFFERS
FBUF2:	BLOCK PGSIZ
FBUFO:	BLOCK PGSIZ
NCHBF==PGSIZ*5

OUTCNT:	BLOCK 1			;OUTPUT FILE BUFFER COUNT
OPTR:	BLOCK 1			;OUTPUT BYTE PTR
OUTJFN:	BLOCK 1			;OUTPUT JFN

NPDL==100			;SIZE OF PDL
PDL:	BLOCK NPDL		;PDL

	RELOC 0
	SUBTTL START AND INITIALIZE

START:
REINIT:	MOVE P,[IOWD NPDL,PDL]
	RESET
	MOVX T1,.FHSLF
	MOVEI T2,[JRST START
		JRST REINIT]	;ESTABLISH ENTRY VECTOR
	HRLI T2,2
	SEVEC
	MOVEI BP1,BBP1		;SETUP BLOCK ADDRESSES
	MOVEI BP2,BBP2
	MOVEI T1,LPTR1		;INIT BLOCKS
	MOVEM T1,BFA(BP1)
	MOVEM T1,NL(BP1)
	MOVEM T1,FRE(BP1)
	MOVEI T1,LPTR2
	MOVEM T1,BFA(BP2)
	MOVEM T1,NL(BP2)
	MOVEM T1,FRE(BP2)
	MOVEI T1,LPTR1+NLMAX/2
	MOVEM T1,BFA2(BP1)
	MOVEI T1,LPTR2+NLMAX/2
	MOVEM T1,BFA2(BP2)
	MOVEI T1,BUF1
	MOVEM T1,SFRE(BP1)
	MOVEM T1,SBFR(BP1)
	MOVEI T1,EBUF1
	MOVEM T1,ESBFR(BP1)
	MOVEI T1,BUF2
	MOVEM T1,SFRE(BP2)
	MOVEM T1,SBFR(BP2)
	MOVEI T1,EBUF2
	MOVEM T1,ESBFR(BP2)
	MOVEI T1,FBUF1
	MOVEM T1,BFADR(BP1)
	MOVEI T1,FBUF2
	MOVEM T1,BFADR(BP2)
	MOVEI T1,IMINDI
	MOVEM T1,MINDIF
	MOVEI T1,INMAT
	MOVEM T1,NMATCH
	MOVEI T1,NLMAX-^D100
	MOVEM T1,MAXDIF
	SETZM CNGNO
	MOVE T1,[ICBLK,,CBLK]	;INIT COMMAND STATE BLOCK
	BLT T1,CBLK+.CMGJB
CLRST:	SETO T1,
	CLOSF
	 JFCL
	RLJFN
	 JFCL
	; ..
;TOP OF COMMAND LOOP

RESTRT:	MOVE P,[IOWD NPDL,PDL]	;RESET STACK
	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMINI]
	COMND
REPAR1:	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMKEY,,CTBL,<COMMAND NAME>]
	COMND			;GET KEYWORD
	TXNE T1,CM%NOP
	ERROR RESTRT,<?Not a defined command>
	HRRZ T2,0(T2)		;GET DISPATCH
	JRST 0(T2)		;DO IT

;REPARSE DISPATCH

REPAR0:	JRST REPAR1		;RETRY

;COMMAND COMPLETED

CDONE:	JRST REINIT

;CONFRM - PRESERVES ALL ACS

CONFRM:	PUSH P,T1
	PUSH P,T2
	PUSH P,T3
	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMCFM]
	COMND
	TXNE T1,CM%NOP
	ERROR RESTRT,<?Not confirmed>
	POP P,T3
	POP P,T2
	POP P,T1
	RET

;INITIAL COMND STATE BLOCK

ICBLK:	REPAR0
	.PRIIN,,.PRIOU
	POINT 7,[ASCIZ /REDIT>/]
	POINT 7,CBFR
	POINT 7,CBFR
	CBFSIZ*5
	0
	POINT 7,ACBFR
	ACBSIZ*5
	GJBLK
;COMMAND DISPATCH TABLE

DEFINE TB (DAT,TXT)<
	XWD [ASCIZ \TXT\],DAT>

CTBL:	NCTBL,,NCTBL
	TB $CMP,<COMPARE>
	TB $EXIT,<EXIT>
	TB $HELP,<HELP>
	TB $MERGE,<MERGE>
	TB $MINM,<MINIMUM>
NCTBL==.-CTBL-1

;COMMANDS...

;EXIT

$EXIT:	CALL CONFRM
	HALTF
	JRST CDONE

;HELP

$HELP:	CALL CONFRM
	HRROI T1,HLPMSG
	PSOUT
	JRST CDONE

HLPMSG:	ASCIZ /

COMPARE	compares a "new source" with a previous version to produce a
	"differences file" which can be given to a subsequent MERGE.

MERGE	merges a "differences file" with a related source to produce
	a new version of the source.

/

;MINIMUM LINES FOR MATCH

$MINM:	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <LINES TO MATCH>>]
	COMND
	MOVEI T2,[FLDDB. .CMNUM,,^D10]
	COMND
	TXNE T1,CM%NOP
	ERROR RESTRT,<?Not a decimal number>
	CALL CONFRM
	MOVEM T2,MINDIF
	JRST CDONE
;COMPARE NEW-SOURCE OLD-SOURCE DIFFERENCES

$CMP:	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <NEW SOURCE FILE>>]
	COMND
	SETZM GJBLK+.GJDIR	;FLUSH DEFAULTS
	SETZM GJBLK+.GJNAM
	SETZM GJBLK+.GJEXT
	MOVX T2,GJ%OLD
	MOVEM T2,GJBLK+.GJGEN	;SET TO GET EXISTING FILE
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T1,CM%NOP
	ERRORJ RESTRT,<?Invalid source file>
	MOVEM T2,INJFN(BP2)
	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <WITH FILE>>]
	COMND
	SCALL SETFDF,<INJFN(BP2)> ;SET DEFAULTS FROM FIRST FILE
   repeat 0,<			;default to previous generation - not used
	HRROI T1,DEFVER		;GET GENERATION NUMBER FROM FIRST FILE
	MOVE T2,INJFN(BP2)
	MOVX T3,1B14
	JFNS
	HRROI T1,DEFVER
	MOVEI T3,^D10
	NIN
	 JSERR
	SOS T2			;DEFAULT TO ONE BEFORE THAT
	MOVEM T2,GJBLK+.GJGEN
   >				;end repeat 0
	MOVX T2,GJ%OLD
	moveM T2,GJBLK+.GJGEN
	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T1,CM%NOP
	ERRORJ RESTRT,<?Invalid source file>
	MOVEM T2,INJFN(BP1)
	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <DIFFERENCES TO>>]
	COMND
	HRROI T2,[ASCIZ /DIF/]
	MOVEM T2,GJBLK+.GJEXT	;SET SPECIFIC DEFAULT EXT
	MOVX T2,GJ%FOU+GJ%MSG
	MOVEM T2,GJBLK+.GJGEN
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T1,CM%NOP
	ERRORJ RESTRT,<?Invalid destination file>
	MOVEM T2,OUTJFN
	CALL CONFRM
	CALL FILSET		;OPEN FILES
	CALL CMP		;DO THE WORK
	CALL FILFIN		;CLOSE FILES
	JRST CDONE
;UPDATE DIFFERENCES SOURCE NEW-SOURCE

$MERGE:	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <DIFFERENCES FROM>>]
	COMND
	SETZM GJBLK+.GJDIR	;FLUSH DEFAULTS
	SETZM GJBLK+.GJNAM
	HRROI T2,[ASCIZ /DIF/]
	MOVEM T2,GJBLK+.GJEXT	;STANDARD DEFAULT EXT
	MOVX T2,GJ%OLD
	MOVEM T2,GJBLK+.GJGEN
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T1,CM%NOP
	ERRORJ RESTRT,<?Invalid source file>
	MOVEM T2,INJFN(BP2)
	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <WITH SOURCE>>]
	COMND
	SCALL SETFDF,<INJFN(BP2)> ;SET DEFAULTS FROM FIRST FILE
	SETZM GJBLK+.GJEXT	;BUT NOT EXTENSION
	MOVX T2,GJ%OLD
	MOVEM T2,GJBLK+.GJGEN
	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T2,CM%NOP
	ERRORJ RESTRT,<?Invalid source file>
	MOVEM T2,INJFN(BP1)
	MOVEI T2,[FLDDB. .CMNOI,,<TXTPTR <TO>>]
	COMND
	SCALL SETFDF,<INJFN(BP1)> ;SET DEFAULTS FROM SECOND FILE
	MOVX T2,GJ%FOU+GJ%MSG
	MOVEM T2,GJBLK+.GJGEN
	MOVEI T1,CBLK
	MOVEI T2,[FLDDB. .CMFIL]
	COMND
	TXNE T1,CM%NOP
	ERRORJ RESTRT,<?Invalid destination file>
	MOVEM T2,OUTJFN
	CALL CONFRM
	CALL FILSET		;OPEN FILES
	CALL SCH		;DO THE WORK
	CALL FILFIN		;CLOSE FILES
	JRST CDONE
;SETUP FILES

FILSET:	MOVE T1,INJFN(BP1)
	MOVX T2,<FLD(7,OF%BSZ)+OF%RD>
	OPENF
	 JSHLT
	MOVE T1,INJFN(BP2)
	MOVX T2,<FLD(7,OF%BSZ)+OF%RD>
	OPENF
	 JSHLT
	MOVE T1,OUTJFN
	MOVX T2,<FLD(7,OF%BSZ)+OF%WR>
	OPENF
	 JSHLT
	SETZM INCNT(BP1)	;INIT BUFFERS
	SETZM INCNT(BP2)
	CALLRET FBFINI

;FINISH FILES

FILFIN:	CALL FBFOUT		;DUMP LAST BUFFER
	MOVE T1,OUTJFN
	CLOSF
	 JFCL
	SKIPL T1,INJFN(BP1)
	CLOSF
	 JFCL
	SKIPL T1,INJFN(BP2)
	CLOSF
	 JFCL
	RET

;SET FILE DEFAULTS
; T1/ JFN

SETFDF:	ACVAR <JFN,P1>
	MOVEM T1,JFN		;SAVE SOURCE JFN
	MOVSI P1,-NJFLD		;NUMBER OF FIELDS TO DO
SETFD1:	HRRO T1,JFLD1(P1)	;DEFAULT STRING BUFFER
	MOVEM T1,GJBLK+.GJNAM(P1)
	MOVE T2,JFN
	MOVE T3,JFLD2(P1)	;BIT FOR JFNS
	JFNS
	AOBJN P1,SETFD1
	RET

JFLD1:	GJ%NAM+DEFNAM
	GJ%EXT+DEFEXT
NJFLD==.-JFLD1

JFLD2:	1B8
	1B11
	SUBTTL MAIN COMPARE LOOP

CMP:	ACVAR <P1>
	TXO F,TOPF		;NOTE NOW AT TOP
	move t1,[1,,1]		;init page and line numbers
	movem t1,paglin(bp1)
	movem t1,paglin(bp2)
	JRST DIF1		;FIND FIRST SYNCH POINT

CMPLP:	SCALL FILL,<BP1>	;FILL BOTH BUFFERS IF NECESSARY
	SCALL FILL,<BP2>
	SCALL LCOMP,<NL(BP1),NL(BP2)> ;COMPARE ONE LINE
	JUMPN T1,DIF1		;JUMP IF DIFFERENT
	SCALL BUMPL,<BP1>	;INCREMENT LINE
	MOVE T1,NL(BP1)
	CAML T1,BFA2(BP1)	;LINE BUFFER HALF FULL?
	JRST [	SCALL SHIFT,<BP1> ;YES, SHIFT IT DOWN
		JRST .+1]
	SCALL BUMPL,<BP2>	;INCREMENT LINE
	MOVE T1,NL(BP2)
	CAML T1,BFA2(BP2)	;DITTO
	JRST [	SCALL SHIFT,<BP2>
		JRST .+1]
	MOVE T1,NL(BP1)
	MOVE T2,NL(BP2)
	CAML T1,FRE(BP1)	;BOTH AT EOF?
	CAMGE T2,FRE(BP2)
	JRST CMPLP		;NO, CONTINUE SCAN
	RET			;YES, DONE
;FOUND ONE LINE DIFFERENT, BEGIN SCAN TO LOOK FOR MATCH

DIF1:	SCALL SHIFT,<BP1>	;SHIFT OUT ALL GOOD STUFF
	SCALL SHIFT,<BP2>
	mv paglin(bp1),ipagln(bp1) ;and line numbers
	mv paglin(bp2),ipagln(bp2)
	MV NL(BP1),INL1		;SAVE START OF DIFFERENCE AREA
	MV NL(BP2),INL2
	MOVE P2,MAXDIF		;INIT COUNT
DIF4:	SCALL BUMpx,<BP1>	;MOVE TO NEXT LINE IN EACH FILE
	SCALL BUMpx,<BP2>
	SCALL FILL,<BP1>	;ADD TEXT TO BUFFERS
	SCALL FILL,<BP2>
	SCALL LCOMPN,<NL(BP1),NL(BP2)> ;COMPARE LAST GROUP IN EACH FILE
	JUMPE T1,MCH
	MOVE P1,NL(BP2)		;COMPARE FILE 1 WITH ALL GROUPS IN FILE 2
DIF2:	SOS P1			;BACKUP ONE LINE IN FILE 2
	SCALL LCOMPN,<NL(BP1),P1> ;COMPARE GROUP OF LINES
	JUMPE T1,[MOVEM P1,NL(BP2) ;MATCH, UPDATE CURRENT LINE
		JRST MCH]
	CAMLE P1,INL2		;DONE ALL GROUPS IN FILE 2?
	JRST DIF2		;NO
	MOVE P1,NL(BP1)		;COMPARE FILE 2 WITH ALL GROUPS IN FILE 1
DIF3:	SOS P1			;BACKUP ONE LINE IN FILE 1
	SCALL LCOMPN,<P1,NL(BP2)> ;COMPARE GROUP OF LINES
	JUMPE T1,[MOVEM P1,NL(BP1) ;MATCH, UPDATE CURRENT LINE
		JRST MCH]
	CAMLE P1,INL1		;DONE ALL GROUPS IN FILE 1?
	JRST DIF3		;NO
	SOJG P2,DIF4		;YES, STILL NO MATCH
	TMSG <
?Apparent change of at least >
	MOVEI T1,.PRIOU
	MOVE T2,MAXDIF
	MOVX T3,^D10
	NOUT
	 JSERR
	TMSG < lines, files cannot be compared.
>
	HALTF
;HAVE FOUND MATCH, OUTPUT DIFFERENCES TO FILE

MCH:	HRROI T1,[ASCIZ /***** Change #/]
	CALL STOUT
	AOS T1,CNGNO
	CALL NOUT10
	hrroi t1,[asciz /; Page /]
	call stout
	hlrz t1,ipagln(bp2)
	call nout10
	hrroi t1,[asciz /, line /]
	call stout
	hrrz t1,ipagln(bp2)
	call nout10
	hrroi t1,[asciz /; Page /]
	call stout
	hlrz t1,ipagln(bp1)
	call nout10
	hrroi t1,[asciz /, line /]
	call stout
	hrrz t1,ipagln(bp1)
	call nout10
	MOVEI T1,.CHLFD
	CALL COUT
	TXZE F,TOPF		;WERE AT TOP?
	JRST MCH1		;YES, NO OUTPUT
	SCALL BFOUT,<BP1>	;OUTPUT BUFFER 1
MCH1:	MOVEI T1,.CHESC
	CALL COUT
	hrroi t1,[asciz / ---------------------------------
/]
	call stout
	SCALL BFOUT,<BP2>
	MOVEI T1,.CHESC
	CALL COUT
	MOVEI T1,.CHLFD
	CALL COUT
	move p1,inl1		;reset to initial line
	exch p1,nl(bp1)
	camle p1,nl(bp1)	;have moved past change?
	jrst [	scall bumpl,<bp1> ;no, step line and account position
		jrst .-1]
	move p1,inl2		;ditto
	exch p1,nl(bp2)
	camle p1,nl(bp2)
	jrst [	scall bumpl,<bp2>
		jrst .-1]
	SCALL SHIFTA,<BP1>	;SHIFT OUT COMPLETED STUFF
	SCALL SHIFTA,<BP2>
	JRST CMPLP
;UPDATE SECTION, SEARCH AND REPLACE

SCH:
SCH0:	SCALL FILL,<BP2>	;GET MORE DIFFERENCES
	MOVE T1,@NL(BP2)	;FIND BEGINNING OF NEXT REPLACE
	MOVE T2,0(T1)
	CAME T2,[ASCII /*****/]
	JRST [	SCALL BUMPL,<BP2>
		MOVE T1,NL(BP2)
		CAML T1,FRE(BP2) ;AT EOF?
		JRST SCH8	;YES
		JRST SCH0]
	SCALL BUMPL,<BP2>

;FIND FIRST MATCHING LINE

SCHLP:	MOVE T1,@NL(BP2)	;CHECK FOR NULL SEARCH
	MOVE T2,0(T1)
	CAMN T2,[<.CHESC>B6]	;END OF STRING?
	JRST SCH9		;YES
	SCALL FILL,<BP1>	;GET MORE INPUT IF NECESSARY
	SCALL LCOMP,<NL(BP1),NL(BP2)>
	JUMPE T1,SCH1		;JUMP IF LINES MATCH
SCH3:	SCALL BUMPL,<BP1>	;NO MATCH, BUMP INPUT
	MOVE T1,NL(BP1)
	CAMGE T1,FRE(BP1)	;EOF?
	JRST SCHLP		;NO, KEEP SEARCHING
	TMSG <
?Failed to find >
	MOVE T1,NL(BP2)		;GET CURRENT LINE
	HRRZ T2,-1(T1)		;CHANGE BANNER IS ONE BEFORE IT
	TLOA T2,(<POINT 7,>)	;OUTPUT THE TEXT SANS TERMINATING LINE FEED
SCH3A:	 PBOUT
	ILDB T1,T2
	CAIE T1,.CHLFD
	 JRST SCH3A
	MV BFA(BP1),NL(BP1)	;RESET INPUT POINTER
	JRST SCH0		;GO ON TO NEXT CHANGE
;FOUND FIRST MATCHING LINE, CHECK REMAINDER

SCH1:	MV NL(BP1),INL1		;SAVE CURRENT POINTERS
	MV NL(BP2),INL2
SCH2:	SCALL BUMPL,<BP1>	;STEP TO NEXT LINE
	SCALL BUMPL,<BP2>
	MOVE T1,@NL(BP2)
	MOVE T2,0(T1)
	CAMN T2,[<.CHESC>B6]	;END OF SEARCH?
	JRST SCH4		;YES, COMPLETE MATCH
	SCALL FILL,<BP1>	;NO, GET MORE INPUT
	SCALL FILL,<BP2>
	SCALL LCOMP,<NL(BP1),NL(BP2)> ;CHECK NEXT LINE
	JUMPE T1,SCH2		;JUMP IF MATCH
	MV INL1,NL(BP1)		;NO MATCH, RESET POINTERS
	MV INL2,NL(BP2)
	JRST SCH3
;COMPLETE MATCH, EFFECT REPLACEMENT

SCH9:	MV NL(BP1),INL1		;SET BEG OF CHANGE POINTS
	MV NL(BP2),INL2
SCH4:	scall bumpl,<bp2>	;bypass junk
	MOVE T1,NL(BP1)		;SET POINTER TO BEG OF DELETION
	EXCH T1,INL1		;AND SAVE END OF DELETION
	CAMG T1,BFA(BP1)	;ANYTHING BEFORE DELETION?
	JRST SCH5		;NO
	MOVEM T1,NL(BP1)
	SCALL BFOUT,<BP1>
SCH5:	MV INL1,NL(BP1)		;STEP POINTER BEYOND DELETION
	SCALL SHIFTA,<BP1>	;FLUSH EVERYTHING ALREADY PROCESSED
	SCALL BUMPL,<BP2>	;STEP TO FIRST LINE TO INSERT
	SCALL SHIFTA,<BP2>	;FLUSH EVERYTHING BEFORE THAT
	MV NL(BP2),INL2		;SAVE TOP OF INSERT
SCH6:	SCALL FILL,<BP2>	;GET MORE INSERT TEXT
	MOVE T1,@NL(BP2)
	MOVE T2,0(T1)		;CHECK FOR END OF INSERT
	CAME T2,[<.CHESC>B6]
	JRST [	SCALL BUMPL,<BP2> ;NOT END, STEP LINE
		JRST SCH6]
	SCALL BFOUT,<BP2>	;OUTPUT INSERTION
	AOS NL(BP2)
	SCALL SHIFTA,<BP2>	;FLUSH EVERYTHING PROCESSED
	JRST SCH0		;DO NEXT CHANGE

;EOF IN DIFFERENCE FILE

SCH8:	MV FRE(BP1),NL(BP1)	;SET CURRENT LINE TO END
	SCALL BFOUT,<BP1>	;DUMP ALL CURRENT BUFFER
SCH7:	SCALL CIN,<BP1>		;COPY REST OF FILE
	 RET			;DONE
	CALL COUT
	JRST SCH7
	SUBTTL SUBROUTINES

;COMPARE ROUTINES

;COMPARE ONE LINE
; T1/ LINE INDEX
; T2/ LINE INDEX
; RETURNS +1,
;  T1/ 0 IF LINES IDENTICAL, NON-0 IF LINES DIFFERENT

LCOMP:	ACVAR <P1,P2>
	CAML T1,FRE(BP1)	;AT EOF?
	JRST [	CAML T2,FRE(BP2) ;YES, BOTH FILES?
		TDZA T1,T1	;YES, EQUAL
		SETO T1,	;NO, DIFFERENT
		RET]
	CAML T2,FRE(BP2)	;AT EOF?
	JRST [	SETO T1,	;YES, DIFFERENT
		RET]
	MOVE P1,0(T1)		;GET STRING ADDRESSES
	MOVE P2,0(T2)
LCOM1:	MOVE T1,0(P1)
	CAME T1,0(P2)		;SAME?
	JRST [	SETO T1,	;NO
		RET]
	AOS P1			;BUMP WORDS
	AOS P2
	TRNE T1,177B34		;LAST WORD?
	JRST LCOM1		;NO
	SETZ T1,		;YES, LINES IDENTICAL
	RET

;COMPARE 'NMATCH' LINES, SAME ARGS AS LCOMP

LCOMPN:	ACVAR <P1,P2,P3>
	MOVEM T1,P1
	MOVEM T2,P2
	MOVE P3,NMATCH
LCOMN1:	SCALL LCOMP,<P1,P2>
	JUMPN T1,R		;STOP NOW IF DIFFERENT
	AOS P1			;BUMP LINE INDEXES
	AOS P2
	SOJG P3,LCOMN1		;DO NEXT LINE
	RET			;ALL COMPARE OK
;SHIFT OUT LINES ALREADY PROCESSED
; T1/ BLOCK ADDRESS

SHIFTA:	TDZA T2,T2		;SHIFT OUT EVERYTHING BEFORE CURRENT LINE
SHIFT:	MOVE T2,MINDIF		;SHIFT OUT UP TO MINDIF BEFORE CURRENT LINE
	ACVAR <BP>
	MOVEM T1,BP		;SAVE BLOCK ADDRESS
	MOVE T1,NL(BP)
	SUB T1,T2		;FIND FIRST LINE TO KIIP
	MOVN T3,T1
	ADD T3,BFA(BP)		;COMPUTE (NEG) NUMBER LINES TO DELETE
	JUMPGE T3,R		;QUIT IF NONE
	HRLZ T1,T1		;SETUP BLT FROM
	HRR T1,BFA(BP)		; .. TO
	ADDM T3,NL(BP)		;UPDATE POINTERS
	ADDM T3,FRE(BP)
	MOVE T2,FRE(BP)		;SETUP BLT FINAL ADR
	BLT T1,-1(T2)
	RET

;BUMP CURRENT LINE
; T1/ BLOCK ADDRESS
; RETURN +1, CHECKS FOR END OF BUFFER

BUMPL:	AOS T2,NL(T1)		;BUMP LINE POINTER
	CAMLE T2,FRE(T1)	;PAST END?
	jrst [	SOS T2,NL(T1)	;YES, UNDO IT
		ret]
	move t3,-1(t2)		;check previous line for ffd
	move t3,0(t3)
	came t3,[<.chffd>b6]
	jrst bumpl1
	movsi t3,1		;increment page number
	add t3,paglin(t1)
	hllzm t3,paglin(t1)
bumpl1:	aos paglin(t1)		;increment line number
	RET

;same as above but no position accounting - used during
;difference scan

bumpx:	aos t2,nl(t1)
	camle t2,fre(t1)
	sos t2,nl(t1)
	ret
;FILL BUFFER SO THAT AT LEAST MINDIF LINES PRESENT FOLLOWING NL
; T1/ BLOCK ADDRESS

FILL:	ACVAR <BP,P1>
	MOVEM T1,BP		;SAVE BLOCK ADDRESS
FILL3:	MOVE T1,NL(BP)
	ADD T1,MINDIF
	CAMGE T1,FRE(BP)	;ENOUGH LINES PRESENT?
	RET			;YES, DONE
	SKIPGE INJFN(BP)	;HAVE A JFN?
	RET			;NO, ALREADY AT EOF
	MOVE P1,SFRE(BP)	;ASSIGN STRING STORAGE
	ADDI P1,MAXCHL/5	;SEE IF ENOUGH LEFT
	CAML P1,ESBFR(BP)
	JRST [	MOVE P1,SBFR(BP) ;NO, WRAPAROUND
		MOVEM P1,SFRE(BP)
		JRST .+1]
	MOVE P1,SFRE(BP)
	MOVEM P1,@FRE(BP)	;PUT ADDRESS IN LINE PTR TABLE
	HRLI P1,(POINT 7,0)
FILL1:	SCALL CIN,<BP>		;GET A CHAR
	 JRST [	MOVE T1,INJFN(BP) ;EOF
		CLOSF
		 JSERR
		SETOM INJFN(BP)	;NOTE NO JFN
		RET]
	IDPB T1,P1		;STORE CHAR
	CAIE T1,.CHLFD		;END OF LINE?
	CAIN T1,.CHFFD
	JRST FILL2		;YES
	CAIN T1,.CHESC		;ESC TREATED AS EOL
	JRST FILL2
	JRST FILL1		;NO

FILL2:	SETZ T1,		;TIE OFF LINE
	IDPB T1,P1
	TXNE P1,76B5		;FILLED WORD?
	JRST FILL2		;NO, KEEP APPENDING NULLS
	AOS P1			;UPDATE STRING FREE
	HRRM P1,SFRE(BP)
	AOS FRE(BP)
	JRST FILL3
;OUTPUT CONTENTS OF BUFFER FROM TOP TO CURRENT LINE
; T1/ BLOCK PTR
; RETURNS +1

BFOUT:	ACVAR <BP,P1,P2>
	MOVEM T1,BP
	MOVE P1,BFA(BP)		;GET FIRST LINE 
BFOU2:	CAML P1,NL(BP)		;BUFFER EMPTY?
	RET			;YES
	MOVE P2,0(P1)		;GET STRING ADDRESS
	HRLI P2,(POINT 7,0)
BFOU1:	ILDB T1,P2
	JUMPN T1,[CALL COUT	;OUTPUT CHAR
		JRST BFOU1]
	AOJA P1,BFOU2		;DO ALL LINES

;STRING OUT TO FILE
; T1/ POINTER

STOUT:	ACVAR <P1>
	HLRZ T2,T1
	CAIN T2,-1		;DEFAULT?
	HRLI T1,(POINT 7,0)	;YES
	MOVEM T1,P1
STOUT1:	ILDB T1,P1
	JUMPN T1,[CALL COUT	;OUTPUT A CHAR
		JRST STOUT1]
	RET

;NUMBER OUTPUT, DECIMAL
; T1/ NUMBER

NOUT10:	STKVAR <<NBF,3>>
	MOVE T2,T1		;SETUP NUMBER
	HRROI T1,NBF
	MOVEI T3,^D10
	NOUT			;WRITE TO TEMP STACK BUFFER
	 JSERR
	HRROI T1,NBF		;COPY BUFFER TO FILE
	CALLRET STOUT
;FILE IO
;CHARACTER IN
; T1/ BLOCK PTR
; RETURNS +1, END OF FILE
;	+2, SUCCESS, T1/ CHARACTER

CIN:	MOVEM T1,T4		;SAVE BLOCK PTR
CIN1:	SOSGE INCNT(T4)		;CHAR IN BUFFER?
	JRST GBF1		;NO
	ILDB T1,IPTR(T4)	;GET IT
	RETSKP

GBF1:	SKIPGE T1,INJFN(T4)
	RET			;FILE ALREADY CLOSED
	GTSTS			;GET FILE STATUS
	TXNE T2,GS%EOF		;AT EOF?
	RET			;YES
	MOVE T2,BFADR(T4)
	HRLI T2,(POINT 7,0)
	MOVEM T2,IPTR(T4)	;INIT PTR
	MOVNI T3,NCHBF
	SIN
	ADDI T3,NCHBF		;COMPUTE NUMBER BYTES STORED
	MOVEM T3,INCNT(T4)
	JRST CIN1

;CHARACTER OUT
; T1/ CHARACTER
; RETURNS +1

COUT:	SOSGE OUTCNT
	JRST [	SETZM OUTCNT
		CALL FBFOUT
		JRST COUT]
	IDPB T1,OPTR
	RET

FBFOUT:	STKVAR <CH>
	MOVEM T1,CH
	MOVE T1,OUTJFN
	HRROI T2,FBUFO
	MOVNI T3,NCHBF
	ADD T3,OUTCNT
	SOUT
	CALL FBFINI
	MOVE T1,CH
	RET

FBFINI:	MOVEI T1,NCHBF
	MOVEM T1,OUTCNT
	MOVE T1,[POINT 7,FBUFO]
	MOVEM T1,OPTR
	RET
JSERRM:	MOVEI T1,.PRIOU
	HRLOI T2,.FHSLF		;THIS FORK, LAST ERROR
	SETZ T3,
	ERSTR
	 JFCL
	 JFCL
	TMSG <
>
	RET

	END START