Files
RomWBW/Source/Images/hd0/s0/u15/DIFF.MAC
2016-09-30 18:07:16 -07:00

725 lines
14 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;
; 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