home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
DIFF.MQC
/
DIFF.MAC
Wrap
Text File
|
2000-06-30
|
15KB
|
725 lines
;
; PROGRAM: DIFF
; AUTHOR: Richard Conn
; VERSION: 2.0
; DATE: 18 MAY 84
; PREVIOUS VERSIONS: 1.6 (16 JAN 83)
; PREVIOUS VERSIONS: 1.5 (9 JAN 83), 1.4 (6 JAN 83), 1.3 (4 JAN 83)
; PREVIOUS VERSIONS: 1.2 (19 DEC 82), 1.1 (8 DEC 82), 1.0 (24 JULY 82)
; DERIVATION: COMPARE, VERSION 1.1
;
VERS EQU 20
z3env SET 0f400h
;
; DIFF is designed to provide the user with a convenient method
; to compare the contents of two files. It is invoked by one of two basic
; forms:
;
; DIFF filename.typ
; or
; DIFF file1.typ file2.typ
;
; The first form compares the file named "filename.typ" on drive A:
; to the file of the same name on drive B:; the second form compares the
; file named "file1.typ" on drive A: to the file named "file2.typ" on drive
; B:. Wild cards may NOT be used. The listing generated by the program gives
; relative offsets (in hex and decimal) as well as the different byte values
; in hex, decimal, and ASCII.
;
; SIZE OF BUFFER
BLIMIT EQU 32 ; NUMBER OF 128-BYTE BLOCKS
BSIZE EQU BLIMIT*128 ; 4K
; CP/M Constants
CPM equ 0 ; CP/M Warm Boot
BUFF equ CPM+80H ; Temporary Buffer
CR equ 0DH ; <CR>
LF equ 0AH ; <LF>
CTRLC EQU 'C'-'@'
CTRLX EQU 'X'-'@'
; SYSLIB and Z3LIB ROUTINES
EXT Z3INIT,ZFNAME,GETCRT
EXT PHL4HC,PHLDC,PA2HC,PADC
EXT BDOS,INITFCB
EXT LOGUD,RETUD
EXT F$OPEN,F$CLOSE,F$READ
EXT CAPS,CIN,COUT,CRLF,MOVEB,PRINT
EXT CODEND
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3init ;initialize the ZCPR3 Env and the VLIB Env
;
; SET BUFFER LOCATIONS
;
CALL CODEND ; ALLOCATE BUFFER SPACE
SHLD INLINE ; SET PTR TO INPUT LINE
LXI D,100H ; BUFFER SIZE
DAD D
SHLD BUFF1 ; SOURCE 1 BUFFER
LXI D,BSIZE ; SIZE OF BUFFER
INR D ; ADD 1
DAD D
SHLD BUFF2 ; SOURCE 2 BUFFER
;
; SET OPERATIONS FLAGS
;
XRA A ; A=0
STA MULT ; SET NO MULTIPLE RUN
STA COMP ; SET NO COMPARE ONLY
CALL GETCRT ; GET CRT CHARACTERISTICS
INX H ; PT TO TEXT LINE COUNT
INX H
MOV A,M ; GET COUNT
STA LSET ; SET COUNTER
;
; EXTRACT COMMAND LINE INFORMATION
;
LHLD INLINE ; PT TO INPUT LINE BUFFER
XCHG ; ... IN DE
LXI H,BUFF+1 ; PROCESS OPTIONS IN BUFFER
MVI B,80H ; ARBITRARY 80H BYTES
CALL MOVEB
XCHG ; PT TO FIRST CHAR WITH HL
CALL SBLANK ; SKIP SPACES
ORA A ; EOL?
JZ PRHELP ; PRINT HELP IF SO
CPI '/' ; ASKING FOR HELP?
JZ PRHELP
LXI D,FCBS ; PT TO SOURCE FCB
MVI A,0 ; DIR BEFORE DU
CALL ZFNAME ; EXTRACT NAME AND DIRECTORY DATA
MOV A,M ; GET NEXT CHAR
CPI ','
JZ START2
PUSH H ; SAVE PTR
LXI H,FCBS+1 ; NO 2ND NAME, SO SET IT TO SAME AS FIRST
LXI D,FCBD+1
MVI B,11 ; 11 BYTES
CALL MOVEB
CALL RETUD ; GET CURRENT USER/DISK
MOV A,B ; GET DISK
INR A ; A=1
STA FCBD ; SET DISK
MOV A,C ; GET USER
STA FCBD+13 ; PT TO S1 FOR USER
POP H ; GET PTR
JMP START3
START2:
INX H ; PT TO NEXT CHAR AFTER COMMA
LXI D,FCBD ; SET DEST FCB
MVI A,0 ; DIR BEFORE DU
CALL ZFNAME ; PROCESS NAME
LDA FCBD+1 ; CHECK FOR NO NAME
CPI ' ' ; SPACE MEANS NO NAME
JNZ START3
PUSH H ; SAVE PTR
PUSH B ; SAVE USER/DISK
LXI H,FCBS+1 ; SET NAMES THE SAME
LXI D,FCBD+1 ; COPY SOURCE TO DEST
MVI B,11 ; 11 BYTES
CALL MOVEB
POP B ; RESTORE BC
POP H ; RESTORE PTR
START3:
CALL SBLANK ; SKIP SPACES
CALL OPTS ; PROCESS OPTIONS
START4:
LXI H,FCBS ; SET UP SOURCE FCB
CALL QCHECK ; NO AMBIGUOUS ENTRIES PERMITTED
LXI H,FCBD ; SET UP DESTINATION FCB
CALL QCHECK ; NO AMBIGUOUS ENTRIES PERMITTED
CALL RETUD ; GET CURRENT DU IN BC
LXI H,FCBS ; PT TO SOURCE DISK
MOV A,M ; GET SOURCE DISK
ORA A ; CURRENT?
JNZ START5
MOV A,B ; SET CURRENT DISK
INR A ; ADJUST FOR A=1
START5:
STA SDISK
MVI M,0 ; CLEAR SOURCE DISK
LDA FCBS+13 ; GET USER
STA SUSER
LXI H,FCBD ; GET DESTINATION DISK
MOV A,M ; GET DEST DISK
ORA A ; CURRENT?
JNZ START6
MOV A,B ; SET CURRENT DISK
INR A ; ADJUST FOR A=1
START6:
STA DDISK
MVI M,0 ; CLEAR DEST DISK
LDA FCBD+13 ; GET USER
STA DUSER
MLOOP:
CALL BANNER ; PRINT BANNER
CALL PRS1 ; PRINT SOURCE FILE NAMES
CALL PRS2
LDA MULT ; MULTIPLE RUNS
ORA A
JZ MLOOP1
CALL PRINT
DB CR,LF,' Type ^C to Abort or RETURN to Proceed - ',0
CALL CIN ; GET RESPONSE
CALL CAPS ; CAPITALIZE
CPI CTRLC ; ABORT?
RZ
MVI C,13 ; RESET DISKS
CALL BDOS
MLOOP1:
CALL LOGS ; LOG IN SOURCE
LXI D,FCBS ; TRY TO OPEN SOURCE 1
CALL INITFCB ; INIT FCB
CALL F$OPEN ; Z IF NO ERROR
JNZ FERR
CALL LOGD ; LOG IN DEST DISK/USER
LXI D,FCBD ; TRY TO OPEN SOURCE 2
CALL INITFCB ; INIT FCB
CALL F$OPEN
JNZ FERR
XRA A ; A=0
STA FIRST ; SET FLAG FOR FIRST ERROR
LXI H,0 ; INIT OFFSET
SHLD OFFSET
CALL VERIFY ; PERFORM VERIFICATION
LDA FIRST ; ANY ERRORS?
ORA A ; 0=NO ERRORS
JNZ MLOOP2
CALL PRINT
DB CR,LF,' Files are Identical',0
MLOOP2:
LDA MULT ; CHECK FOR MULTIPLE RUNS
ORA A ; 0=NO
RZ
CALL CRLF ; NEW LINES
CALL CRLF
JMP MLOOP
FERR:
CALL PRINT
DB CR,LF,' File Not Found -- ',0
CALL PRFN
JMP MLOOP2
;
; PROCESS OPTIONS
;
OPTS:
MOV A,M ; GET NEXT OPTION CHAR
INX H ; PT TO NEXT
ORA A ; END OF LINE?
RZ
CPI ' ' ; SKIP SPACES
JZ OPTS
LXI D,OTAB ; PT TO OPTION TABLE
MOV B,A ; OPTION CHAR IN B
OPTS1:
LDAX D ; GET TABLE CHAR
ORA A ; OPTION NOT FOUND?
JZ OPTSE ; PROCESS ERROR
CMP B ; MATCH?
JZ OPTS2
INX D ; SKIP TO NEXT
INX D
INX D
JMP OPTS1
OPTS2:
XCHG ; USE HL
INX H ; GET ADDRESS
MOV A,M ; GET LOW
INX H
MOV H,M ; GET HIGH
MOV L,A ; PUT LOW
XCHG ; DE PTS TO OPTION ADDRESS, HL TO NEXT BYTE
LXI B,OPTS ; SET UP RETURN ADDRESS
PUSH B
PUSH D ; SET UP OPTION ADDRESS
RET ; "RUN" OPTION
OPTSE:
CALL PRHELP ; PRINT HELP MESSAGE
POP PSW ; CLEAR RETURN ADDRESS
RET ; RETURN TO OPSYS
;
; OPTION TABLE
;
OTAB:
DB 'C' ; COMPARE ONLY
DW SCOMPF
DB 'M' ; MULTIPLE RUN
DW SMULTF
DB 0 ; END OF TABLE
;
; SET COMPARE FLAG
;
SCOMPF:
MVI A,0FFH ; SET FLAG
STA COMP
RET
;
; SET MULTIPLE RUN FLAG
;
SMULTF:
MVI A,0FFH ; SET FLAG
STA MULT
RET
;
; SKIP TO NON-BLANK CHAR
;
SBLANK:
MOV A,M ; GET CHAR
INX H ; PT TO NEXT
CPI ' ' ; BLANK?
JZ SBLANK
DCX H ; PT TO NON-BLANK
RET
;
; PRINT HELP MESSAGE
;
PRHELP:
CALL BANNER ; PRINT BANNER
CALL PRINT
DB CR,LF,'Syntax:'
DB CR,LF,' DIFF ufn1,ufn2 o... -or- DIFF ufn o...'
db cr,lf,'Options:'
db cr,lf,' C Compare Files Only (Stop at First Difference)'
db cr,lf,' M Multiple Runs (Keep on prompting for disks)'
DB CR,LF,'Examples:'
DB CR,LF,' Command Files Compared'
DB CR,LF,' DIFF T.COM,A1: $$:T.COM, A1:T.COM'
DB CR,LF,' DIFF A:T.COM A$:T.COM, $$:T.COM'
DB CR,LF,' DIFF A:T.COM,ROOT: A$:T.COM, ROOT:T.COM'
DB CR,LF,' DIFF A:T.COM,B:S.COM A$:T.COM, B$:S.COM'
DB 0
RET
;
; CHECK FOR ANY QUESTION MARKS FROM HL+1 TO HL+11
; AFFECT ONLY AF REGISTERS IF OK
;
QCHECK:
PUSH H ; SAVE HL
PUSH B ; SAVE BC
INX H ; PT TO FIRST CHAR
MVI B,11 ; 11 BYTES
MVI C,'?' ; SCAN FOR '?'
QC:
MOV A,M ; GET BYTE
CMP C ; '?'?
JZ QC1
INX H ; PT TO NEXT
DCR B ; COUNT DOWN
JNZ QC
POP B ; RESTORE
POP H
RET
QC1:
POP B ; RESTORE AND ABORT
POP H
POP D ; CLEAR RETURN ADDRESS
XCHG ; FCB PTR IN DE
CALL CRLF
CALL PRFN ; PRINT FILE NAME
CALL PRINT
DB ' AFN not Allowed',CR,LF,0
RET
;
; PRINT BANNER
;
BANNER:
CALL PRINT
DB 'DIFF Version '
DB VERS/10+'0','.',(VERS MOD 10)+'0'
DB 0
RET
;
; PRINT NAMES OF SOURCE FILES
; PRS1 -- SOURCE FILE 1
; PRS2 -- SOURCE FILE 2
;
PRS1:
CALL PRINT
DB CR,LF,'Source 1 -- ',0
LXI H,SDISK ; PT TO FIRST BYTE
CALL PRUD
LXI D,FCBS ; SOURCE FCB
JMP PRFN ; PRINT FILE NAME
PRS2:
CALL PRINT
DB CR,LF,'Source 2 -- ',0
LXI H,DDISK ; PT TO FIRST BYTE
CALL PRUD
LXI D,FCBD ; DESTINATION FCB
JMP PRFN ; PRINT FILE NAME
;
; MAIN VERIFY ROUTINE
;
VERIFY:
LHLD BUFF1 ; PT TO BUFFER 1
PUSH H ; SAVE PTR
CALL LOGS ; LOG IN SOURCE 1
LXI D,FCBS ; SOURCE 1 FCB
CALL LOAD ; READ IN BLOCK
LDA BCNT ; GET OLD BLOCK COUNT
STA BCNT1 ; SAVE IT
LHLD BUFF2 ; PT TO BUFFER 2
PUSH H ; SAVE PTR
CALL LOGD ; LOG IN SOURCE 2
LXI D,FCBD ; SOURCE 2 FCB
CALL LOAD ; READ IN BLOCK
POP D ; DE PTS TO BUFF 2
POP H ; HL PTS TO BUFF 1
LDA BCNT ; CHECK FOR NO BLOCK READ
MOV B,A
LDA BCNT1
ORA B
RZ ; DONE IF NONE READ
;
; VERIFY LOADED BUFFERS BY COMPARING THEM AND PRINTING DIFFERENCES
;
VERBLOCK:
MVI B,128 ; SCAN ONE BLOCK
VERBL:
LDAX D ; GET BYTE
CMP M ; COMPARE
CNZ NOMATCH ; PRINT DIFFERENCE
PUSH H ; INC OFFSET
LHLD OFFSET
INX H
SHLD OFFSET
POP H
INX H ; PT TO NEXT
INX D
DCR B ; COUNT DOWN
JNZ VERBL
LDA BCNT ; COUNT DOWN
DCR A
STA BCNT
LDA BCNT1
DCR A
STA BCNT1
JZ VEREQ
LDA BCNT ; CHECK FIRST BUFFER COUNT
ORA A
JNZ VERBLOCK ; CONTINUE COMPARE IF NOT EMPTY
VEREQ:
LDA BCNT ; CHECK FOR BOTH DONE
MOV B,A
LDA BCNT1
ORA B ; IF ZERO, BOTH DONE AT SAME TIME AND CONTINUE
JZ VERIFY
LDA BCNT1 ; CHECK FOR ONE DONE BEFORE THE OTHER
ORA A ; 2ND DONE?
MVI C,'2' ; GET LETTER
JZ DONE1
MVI C,'1' ; GET LETTER
; ONE FILE IS SHORTER THAN THE OTHER -- SAY SO
DONE1:
CALL PRINT
DB CR,LF,' Source ',0
MOV A,C
CALL COUT ; PRINT LETTER
CALL PRINT
DB ' has terminated prematurely',0
JMP DABORT
; MATCH ERROR
NOMATCH:
LDA COMP ; GET COMPARE FLAG
ORA A ; NZ=SIMPLE COMPARE
JNZ CABORT
PUSH H ; SAVE REGS
PUSH D
PUSH B
LDA FIRST ; FIRST TIME THRU?
ORA A ; 0=YES
JZ NMAT0
LDA LCNT ; CHECK FOR NEW SCREEN
ORA A ; ZERO IF DONE
JNZ NMAT1
CALL PRINT
DB CR,LF,' DIFF Pause -- Strike RETURN to Continue, '
DB '^C to Abort, or ^X to Advance - ',0
CALL CIN ; GET RESPONSE
CALL CAPS
CPI CTRLC ; ABORT?
JZ NMAT00
CPI CTRLX ; ADVANCE?
JNZ NMAT0
POP B ; CLEAR REGS
POP D
POP H
POP D ; CLEAR STACK
CALL PRINT
DB CR,LF,' DIFF Advancing',0
RET ; RETURN TO VERIFY CALLER
NMAT00:
POP B ; CLEAR REGS
POP D
POP H
POP D ; CLEAR STACK
POP D
DABORT:
CALL PRINT
DB CR,LF,' DIFF Aborting',0
RET ; RETURN TO OPSYS
CABORT:
POP D ; CLEAR STACK
MVI A,1 ; SET ERROR FLAG
STA FIRST
CALL PRINT
DB CR,LF,' Files are Different',0
RET ; RETURN TO VERIFY CALLER
NMAT0:
MVI A,0FFH ; CLEAR FIRST TIME FLAG
STA FIRST
CALL HEADER ; PRINT HEADING AND RETURN NEW LINE COUNT
NMAT1:
DCR A ; COUNT DOWN 1 LINE
STA LCNT ; NEW LINE COUNT
CALL CRLF
PUSH H ; SAVE HL
LHLD OFFSET ; PRINT OFFSET VALUE
CALL PHL4HC ; PRINT AS HEX
CALL SPACER ; PRINT SPACES
CALL PHLDC ; PRINT AS DEC
POP H ; RESTORE HL
CALL SPACER
CALL SPACER
MVI A,' '
CALL COUT
MOV A,M ; GET SOURCE 1 VALUE
CALL PRVAL ; PRINT AS HEX, DEC, ASCII
CALL SPACER ; 10 SPACES
CALL SPACER
CALL SPACER
CALL SPACER
CALL SPACER
LDAX D ; GET SOURCE 2 VALUE
CALL PRVAL ; PRINT AS HEX, DEC, ASCII
POP B ; RESTORE REGS
POP D
POP H
RET
; PRINT HEADER AND RETURN NEW LINE COUNT IN A
HEADER:
PUSH D ; SAVE REGS
PUSH H
CALL PRINT
DB CR,LF,' Rel Offset ',0
LXI H,SDISK ; PRINT DISK/USER
CALL PRUD
LXI D,FCBS
CALL PRFN ; PRINT FILE NAME
CALL SPACER ; 5 SPACES
CALL SPACER
CALL SPACE1
LXI H,DDISK ; PRINT DISK/USER
CALL PRUD
LXI D,FCBD
CALL PRFN ; PRINT FILE NAME
CALL PRINT
DB CR,LF,' Hex Dec Hex Dec Asc Hex Dec Asc',0
LDA LSET ; SET LINE COUNT
SUI 1 ; ADJUST FOR HEADING AND FOOTER
STA LCNT
POP H
POP D ; RESTORE REGS
RET
; PRINT A AS HEX, DEC, AND ASCII
PRVAL:
CALL SPACER ; 3 SPACES
CALL SPACE1
CALL PA2HC ; PRINT AS HEX
CALL SPACER
CALL PADC ; PRINT AS DEC
CALL SPACER
ANI 7FH ; MASK OUT MSB
CPI 7FH ; DOT FOR <DEL>
JZ PRDOT
CPI ' ' ; PRINT DOT IF LESS THAN <SP>
JNC COUT
PRDOT:
MVI A,'.' ; PRINT DOT
JMP COUT
; PRINT 2 SPACES
SPACER:
PUSH PSW ; SAVE A
MVI A,' ' ; <SP>
CALL COUT
POP PSW
SPACE1:
PUSH PSW
MVI A,' '
CALL COUT
POP PSW
RET
;
; LOAD BUFFER FROM FILE WHOSE FCB IS PTED TO BY DE
; ON OUTPUT, BCNT=NUMBER OF BLOCKS LOADED (UP TO BLIMIT)
;
LOAD:
XRA A ; A=0
STA BCNT ; SET BLOCK COUNT
; MAIN LOAD LOOP
LOAD1:
CALL F$READ ; READ A BLOCK
ORA A ; END OF FILE?
RNZ ; RETURN IF DONE
PUSH D ; SAVE FCB PTR
LXI D,BUFF ; PT TO BUFFER
MVI B,128 ; COPY 128 BYTES
LOAD2:
LDAX D ; GET BYTE READ
MOV M,A ; PUT BYTE
INX H ; PT TO NEXT
INX D
DCR B ; COUNT DOWN
JNZ LOAD2
POP D ; GET FCB PTR
LDA BCNT ; GET BLOCK COUNT
INR A ; INCREMENT IT
STA BCNT ; SET IT
CPI BLIMIT ; LAST BLOCK READ?
JNZ LOAD1
RET
;
; LOG IN SOURCE (LOGS) AND DESTINATION (LOGD) DRIVES/USERS
;
LOGS:
LDA SDISK ; GET DISK
DCR A ; A=0
MOV B,A
LDA SUSER ; GET USER
MOV C,A
CALL LOGUD ; LOG IN
RET
LOGD:
LDA DDISK ; GET DISK
DCR A ; A=0
MOV B,A
LDA DUSER ; GET USER
MOV C,A
CALL LOGUD ; LOG IN
RET
;
; PRINT DISK/USER PTED TO BY HL (2 BYTES)
;
PRUD:
MOV A,M ; GET DISK
ADI 'A'-1 ; CONVERT TO LETTER
CALL COUT
INX H ; PT TO USER
MOV A,M ; GET USER
CALL PADC ; PRINT AS DEC
CALL PRINT
DB ': ',0
RET
;
; PRINT FILE NAME WHOSE FCB IS PTED TO BY DE
;
PRFN:
PUSH H ; SAVE REGS
PUSH D
PUSH B
XCHG ; FN PTED TO BY HL
INX H ; PT TO FIRST CHAR
MVI B,8 ; 8 CHARS
CALL PRFN1
MVI A,'.'
CALL COUT
MVI B,3 ; 3 CHARS FOR FILE TYPE
CALL PRFN1
POP B ; RESTORE REGS
POP D
POP H
RET
PRFN1:
MOV A,M ; GET CHAR
INX H ; PT TO NEXT
CALL COUT ; PRINT
DCR B ; COUNT DOWN
JNZ PRFN1
RET
;
; BUFFERS
;
BUFF1:
DS 2 ; PTR TO BUFFER 1
BUFF2:
DS 2 ; PTR TO BUFFER 2
OFFSET:
DS 2 ; RELATIVE OFFSET
FIRST:
DS 1 ; ERROR INDIC
LSET:
DS 1 ; NUMBER OF TEXT LINES ON SCREEN
LCNT:
DS 1 ; LINE COUNT
COMP:
DS 1 ; COMPARE FLAG (0=NO SIMPLE COMPARE)
MULT:
DS 1 ; MULTIPLE RUN FLAG (0=NO MULT RUNS)
SDISK:
DS 1 ; SOURCE DISK (MUST BE FOLLOWED BY SUSER)
SUSER:
DS 1 ; SOURCE USER
FCBS:
DS 36 ; SOURCE FCB
DDISK:
DS 1 ; DEST DISK (MUST BE FOLLOWED BY DUSER)
DUSER:
DS 1 ; DEST USER
FCBD:
DS 36 ; DESTINATION FCB
BCNT:
DS 1 ; BUFFER COUNT
BCNT1:
DS 1 ; SECOND BUFFER COUNT
INLINE:
DS 2 ; PTR TO INPUT LINE BUFFER
END