;COMPASC.ASM ;MOD OF COMPARE.ASM FOR ASCII FILES ;INCLUDES REPORTING AND ACCEPTANCE OF INSERTIONS, ;DELETIONS, ETC. ; ;COMPARE.ASM ;11/??/77 ORIGINALLY WRITTEN BY WARD CHRISTENSEN ;12/31/77 ADD PICKUP OF SECOND FILENAME IF BLANK ;01/08/77 ADD SEQIO MACLIB TO READ BIG BLOCKS ;02/11/82 MOD TO COMPASC BY RUSS BAKKE ; MACLIB SEQIO BSIZE EQU 1024 ;DISK BUFFER SIZE (TIMES 2) ORG 100H ; ;MACRO DEFS ;TYPE SINGLE CHAR OR CHAR IN A TYPE MACRO ?C IF NOT NUL ?C MVI A,?C ENDIF PUSH B PUSH D PUSH H PUT CON POP H POP D POP B ENDM ; PRINT MACRO ?L LOCAL Z CALL Z IRP ?M, DB ?M ENDM DB '$' Z POP D MVI C,@MSG CALL @BDOS ENDM ; GETF MACRO ?B,?P,?F,?E,?L LOCAL Q,R,S IF NOT NUL ?B LXI H,?B ENDIF IF NOT NUL ?P SHLD ?P ENDIF IF NOT NUL ?L LXI B,?L ENDIF Q PUSH B PUSH H CALL ?F POP H POP B MOV M,A JZ R ;EOF INX H DCX B MOV A,B ;DONE? ORA C JNZ Q ;NO JMP S ; R MVI A,1 ;SET EOF FLAG STA ?E ; S ENDM ; REFILL MACRO ?B,?P,?E,?C LOCAL P PUSH D SHLD ?C XCHG LXI B,8192 ;BUFFER SIZE LHLD ?P PUSH H MOV A,H ;NEGATE HL CMA MOV H,A MOV A,L CMA MOV L,A INX H DAD D ;ADD DE LXI D,?B DAD D ;ADD BUFST SHLD ?C POP H P MOV A,M ;MOVE CHAR STAX D DCX B ;COUNT IT INX D ;MOVE POINTERS INX H CALL ?E JNZ P ENDM ; CKEOB MACRO ?E PUSH D LXI D,?E CALL CMPHD POP D ENDM ; ;COMPASC.ASM - COMPARES 2 ASCII FILES ; ;COMMAND FORMAT: COMPASC NAME1 NAME2 ; IF NAME2 = NAME1 BUT IS ON B DISK, ; JUST TYPE: COMPASC NAME1 B: ; LXI SP,STACK ;INIT STACK ; PRINT <'COMPASC.COM 02/11/82',0DH,0AH> ; ;IF THE SECOND FCB IS BLANK, ;MOVE IN THE NAME FROM THE FIRST ; LDA @TFCB+17 CPI ' ' JNZ MOVE2 ;NOT BLANK MVI B,11 LXI D,@TFCB+1 LXI H,@TFCB+17 CALL MOVER ; ;'DECLARE' BOTH FCB'S ; MOVE2 FILE INFILE,FILE1,,1,,BSIZE FILE INFILE,FILE2,,2,,BSIZE ; ;COMPARE THE 2 FILES ; ;FIRST, READ 8K INTO FIRST BUFFER GETF BUF1ST,OK1,GETFILE1,EOF1FG,8192 ;READ 8K INTO SECOND BUFFER GETF BUF2ST,OK2,GETFILE2,EOF2FG,8192 ; ;NOW START COMPARE LXI H,BUF1ST LXI D,BUF2ST COMP LDAX D CMP M JNZ DIFFER CPI CR CZ EOL CPI EOF JZ EOFFND INX H INX D CALL CKEOB1 CZ EOBUF1 CALL CKEOB2 CZ EOBUF2 JMP COMP ; ;FOUND A DIFFERENCE; ;IF EOF IS NOT IN BUFFER, FIRST FORCE ;BUFFER FILL IN ORDER TO AVOID HITTING ;EOBUF IN DIFFERENCE PROCESSING DIFFER LDA EOF1FG ORA A ;TEST 0 JNZ DIFF1 ;NOW SEE IF AT START OF BUFFER PUSH H LHLD OK1 CKEOB BUF1ST POP H CNZ EOBUF1 DIFF1 LDA EOF2FG ORA A JNZ DIFF2 XCHG PUSH H LHLD OK2 CKEOB BUF2ST POP H XCHG CNZ EOBUF2 ; ;IF WE ARE NOT AT EOL+1, STEP (STOP AT EOF) DIFF2 MVI B,CR MVI C,EOF ;ARE WE AT START OF LINE? DCX H MOV A,M INX H CMP B JZ DIFF3 ;YES, FORGET IT ;MOVE TO START OF NEXT LINE (EOL+1) CALL GOSOL XCHG CALL GOSOL XCHG ; ;NOW SEE IF WE ARE AT EOF IN EITHER FILE DIFF3 MOV A,M CMP C JZ DIFEOF LDAX D CMP C JZ DIFEOF ; ;NOW FIND EXTEND OF DIFFERENCE. ;COMPARE CURRENT LINE IN FILE 1 TO ;NEXT 8 IN FILE 2. ;HL POINTS TO CURRENT LINE IN FILE 1, ;DE IN FILE 2 MVI C,EOF SHLD CURR1 ;SAVE CURRENT LINE XCHG SHLD CURR2 XCHG MVI B,8 ;8 LINES DIFF4 LHLD CURR1 CALL CKLINE PUSH PSW CMP C ;EOF? JZ DIFEOF POP PSW JZ MATCH ;MATCH FOUND DCR B JNZ DIFF4 ; ;NOW COMPARE CURRENT LINE IN FILE 2 TO ;NEXT 8 IN FILE 1 MVI B,8 LHLD CURR1 DIFF5 XCHG LHLD CURR2 XCHG CALL CKLINE PUSH PSW CMP C ;EOF? JZ DIFEOF POP PSW JZ MATCH DCR B JNZ DIFF5 ; ;STILL NO MATCH FOUND. PRINT 8 LINES ;FROM EACH BUFFER & EXIT. ; ;WE HAVE A DIFFERENCE AND ARE AT EOF IN A FILE ;PRINT FROM "LAST" POINTER TO EOF IN BOTH BUFFERS ;(STOP AFTER 8 LINES) DIFEOF LDA ERFLG ORA A ;TEST ERROR FLAG JNZ DIFE1 INR A ;SET IT STA ERFLG PRINT <'FILES UNEQUAL',0DH,0AH> DIFE1 PRINT <'****** FILE 1:',0DH,0AH> ;PRINT FILE 1 FROM "LAST OK" LHLD OK1 CALL PRBUF PRINT <'*** FILE 2:',0DH,0AH> LHLD OK2 CALL PRBUF JMP EXIT ; ;PRBUF--PRINT BUFFER (AT HL) FOR 9 LINES OR EOF PRBUF MVI B,9 PRBUF1 CALL PRLINE ;PRINT LINE CPI EOF ;AT EOF? JZ PREOF DCR B ;COUNT LINE JNZ PRBUF1 RET ; ;PREOF--AT EOF IN PRINT PREOF PRINT <'*EOF',0DH,0AH> RET ; ;PRLINE--PRINT LINE (RET EOF IN A IF EOF) PRLINE MOV A,M ;GET CHAR CPI EOF RZ TYPE INX H CPI CR JNZ PRLINE RET ; ;MATCH: HAVE A MATCHED LINE. HL & DE POINT ;TO START OF FOLLOWING LINE. ;PRINT FROM OK1 & OK2 TO END OF DIFF. ;UPDATE OK1 & OK2 & RETURN TO COMPARE. MATCH PUSH H PUSH D ;FIRST, MOVE HL & DE BACK TO START OF PREV. LINE DCX H ;MOVE OFF THE C/R DCX H DCX D DCX D CALL RETSOL XCHG CALL RETSOL SHLD CURR2 ;TEMP STORAGE XCHG SHLD CURR1 ; ;PRINT THE BUFFERS PUSH H LDA ERFLG ORA A ;TEST ERROR FLAG JNZ MAT1A INR A ;SET IT STA ERFLG PRINT <'FILES UNEQUAL',0DH,0AH> MAT1A PRINT <'****** FILE 1:',0DH,0AH> POP D ;DE POINTS TO END OF BUFF1 TO BE PRINTED LHLD OK1 MAT2 CALL PRTOLM MAT3 PRINT <'*** FILE 2:',0DH,0AH> LHLD CURR2 ;NOW BUFF 2 XCHG LHLD OK2 MAT4 CALL PRTOLM ; ;NOW UPDATE OK1, OK2, POINTERS MAT5 LHLD CURR1 INX H ;INC TO EOL+1 SHLD OK1 LHLD CURR2 INX H SHLD OK2 POP D POP H JMP COMP ;RETURN TO COMPARE LOOP ; ;PRTOLM--PRINT FROM HL TO LIMIT IN DE PRTOLM CALL PRLINE CALL CMPHD ;COMPARE HL TO DE RZ ;DONE JNC PRTOLM ;NOT DONE RET ; ;EOL--MOVE POINTERS TO "LAST OK LINES" EOL PUSH H PUSH D MVI B,CR CALL RETSOL ;BACK UP TO PREVIOUS LINE INX H ;STEP TO EOL+1 SHLD OK1 ;SAVE IT XCHG CALL RETSOL INX H SHLD OK2 POP D POP H RET ; ;EOBUF1-END OF BUFFER 1 ;COPY FROM "LAST OK LINE" POINTER THRU END ;OF BUFFER, TO START OF BUFFER; ;REFILL REST OF BUFFER ;KEEP POINTER TO CURRENT CHAR (NOW AT EOBUF) EOBUF1 REFILL BUF1ST,OK1,CKEOB1,CURR1 ; ;NOW FILL BUFFER XCHG GETF ,,GETFILE1,EOF1FG, ; ;SET UP POINTER OK1 LXI H,BUF1ST SHLD OK1 LHLD CURR1 ;NEW BUFFER PTR POP D ;RECOVER RET ; ;EOBUF2--END OF BUFFER2 EOBUF2 XCHG REFILL BUF2ST,OK2,CKEOB2H,CURR2 XCHG GETF ,,GETFILE2,EOF2FG, LXI H,BUF2ST SHLD OK2 LHLD CURR2 XCHG POP H RET ; ;CKEOB1--SEE IF HL IS AT END OF BUFF1 ;(RET Z IF SO) CKEOB1 CKEOB BUF1EN RET ; ;CKEOB2--SEE IF DE IS AT END OF BUFF2 CKEOB2 XCHG CKEOB BUF2EN XCHG RET ; ;CKEOB2H--SEE IF HL IS AT END OF BUFF2 CKEOB2H CKEOB BUF2EN RET ; ;CKLINE--COMPARE LINE AT HL (BUFF1) ;TO LINE AT DE (BUFF2). C=EOF ;IF EOF, RET EOF IN A; ELSE RET Z IF IDENTICAL, ;ELSE NZ ;STOPS AT EOL (& LEAVES DE, HL POINTING TO EOL+1) CKLINE LDAX D CMP M JNZ LINDIF CPI CR JZ LINDON CMP C ;EOF? RZ ;RET WITH EOF IN A MOV A,M CMP C RZ ;RET WITH EOF IN A INX H INX D JMP CKLINE ; ;LINDON--INC POINTERS & EXIT LINDON INX H INX D RET ;NOTE THAT Z FLAG IS SET ; ;LINDIF--DIFFERENCE IN LINES. ;STEP HL & DE TO NEXT LINES; RET NZ. ;IF EOF, RET EOF IN A LINDIF INX H MOV A,M CMP C ;EOF? RZ CPI CR JNZ LINDIF LIND1 INX D LDAX D CMP C ;EOF? RZ CPI CR JNZ LIND1 ;STEP TO EOL+1 BEFORE RET INX D INX H ORI 1 ;CLEAR Z FLAG RET ; ;EOFFND--AT EOF IN VALID COMPARE ;IF NO ERROR FLAG, PRINT OK & EXIT ;ELSE JUST EXIT EOFFND LDA ERFLG ORA A ;SET FLAGS JZ AOK JMP EXIT ; ;A-OK - FILES MATCH ; AOK PRINT 'FILES MATCH' EXIT RST 0 ;RET TO CP/M ; ERXIT POP D ;GET MESSAGE MVI C,@MSG CALL @BDOS JMP EXIT ; ;RETSOL--RET HL TO START OF LINE RETSOL MVI A,CR RETS1 DCX H CMP M JNZ RETS1 RET ; ;GOSOL--INC HL TO START OF NEXT LINE ;B=CR, C=EOF GOSOL MOV A,M CMP C RZ CMP B INX H JNZ GOSOL RET ; ;CMPHD--COMPARE HL TO DE ;RETS Z IF EQ, C IF HL>DE CMPHD MOV A,D SUB H RNZ MOV A,E SUB L RET ; ;MOVE FROM (DE) TO (HL) LENGTH IN B MOVER LDAX D MOV M,A INX D INX H DCR B JNZ MOVER RET ; ;DATA STORAGE DS 80 ;STACK STACK EQU $ OK1 DS 2 ;LAST VALID LINE, FILE1 OK2 DS 2 CURR1 DS 2 ;CURRENT LINE IN SEARCH CURR2 DS 2 ERFLG DB 0 ;ERROR FLAG EOF1FG DB 0 ;EOF FLAGS EOF2FG DB 0 BUF1ST DS 8192 BUF1EN BUF2ST DS 8192 BUF2EN BUFFERS EQU $ MEMSIZE EQU BUFFERS+@NXTB END