home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
zcpr2
/
compare.mqc
/
COMPARE.MAC
Wrap
Text File
|
1985-02-09
|
13KB
|
592 lines
; PROGRAM: COMPARE
; AUTHOR: Richard Conn
; VERSION: 1.4
; DATE: 6 JAN 83
; PREVIOUS VERSIONS: 1.3 (19 DEC 82)
; PREVIOUS VERSIONS: 1.2 (8 DEC 82), 1.1 (21 JULY 82), 1.0 (11 JULY 82)
VERS EQU 14
;
; This program is Copyright (c) 1982, 1983 by Richard Conn
; All Rights Reserved
;
; ZCPR2 and its utilities, including this one, are released
; to the public domain. Anyone who wishes to USE them may do so with
; no strings attached. The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
; The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;
;
; COMPARE 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:
;
; COMPARE filename.typ
; or
; COMPARE 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:.
;
; CP/M Constants
CPM equ 0 ; CP/M Warm Boot
BUFF equ CPM+80H ; Temporary Buffer
CR equ 0DH
LF equ 0AH
; CRC ROUTINES
EXT CRCCLR,CRCUPD,CRCDONE
; SYSLIB ROUTINES
EXT COMPHD,BDOS,INITFCB,LOGUD,RETUD
EXT F$OPEN,F$CLOSE,F$READ
EXT CAPS,CIN,COUT,CRLF
EXT PADC,MOVEB,PRINT
EXT ZGPINS,ZFNAME
;
; Branch to Start of Program
;
JMP START
;
;******************************************************************
;
; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
; This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;
;
; EXTERNAL PATH DATA
;
EPAVAIL:
DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
;
; INTERNAL PATH DATA
;
INTPATH:
DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT
; DISK = 1 FOR A, '$' FOR CURRENT
; USER = NUMBER, '$' FOR CURRENT
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT
DB 0 ; END OF PATH
;
; MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
;
; DISK/USER LIMITS
;
MDISK:
DB 4 ; MAXIMUM NUMBER OF DISKS
MUSER:
DB 31 ; MAXIMUM USER NUMBER
;
; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
;
; PRIVILEGED USER DATA
;
PUSER:
DB 10 ; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS
DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
;
; CURRENT USER/DISK INDICATOR
;
CINDIC:
DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS)
;
; DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
DW 80H ; TBUFF AREA
;
; NAMED DIRECTORY INFORMATION
;
NDRADR:
DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
DB 64 ; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
DB 'NAMES ' ; NAME OF DISK NAME FILE
DB 'DIR' ; TYPE OF DISK NAME FILE
;
; REQUIREMENTS FLAGS
;
EPREQD:
DB 0FFH ; EXTERNAL PATH?
MCREQD:
DB 0FFH ; MULTIPLE COMMAND LINE?
MXREQD:
DB 0FFH ; MAX USER/DISK?
UDREQD:
DB 0FFH ; ALLOW USER/DISK CHANGE?
PUREQD:
DB 000H ; PRIVILEGED USER?
CDREQD:
DB 0FFH ; CURRENT INDIC AND DMA?
NDREQD:
DB 0FFH ; NAMED DIRECTORIES?
Z2CLASS:
DB 0 ; CLASS 0
DB 'ZCPR2'
DS 10 ; RESERVED
;
; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;
;
; Start of Program
;
START:
CALL ZGPINS ; INIT ZCPR2 BUFFERS
XRA A ; SET NO MULTIPLE RUN
STA MULT
CALL RETUD ; GET CURRENT USER/DISK
MOV A,B ; SAVE DISK
STA CDISK
MOV A,C ; SAVE USER
STA CUSER
LXI H,BUFF ; PROCESS OPTIONS IN BUFFER
MOV A,M ; GET CHAR COUNT
INX H ; PT TO FIRST CHAR
PUSH H ; SAVE PTR TO FIRST CHAR
ADD L ; HL=HL+A
MOV L,A
MOV A,H
ACI 0
MOV H,A
MVI M,0 ; STORE ENDING ZERO
POP H ; GET PTR TO FIRST CHAR
LXI D,INLINE ; PT TO INPUT LINE BUFFER
PUSH D ; SAVE PTR
START0:
MOV A,M ; COPY INPUT LINE SO BUFF MAY BE USED
STAX D ; PUT BYTE
INX H ; PT TO NEXT
INX D
ORA A ; EOL?
JNZ START0
POP H ; PT TO FIRST CHAR
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
CALL ZFNAME ; EXTRACT NAME AND DIRECTORY DATA
JNZ START1
UDERR:
CALL PRINT
DB CR,LF,'Invalid Disk or User -- Aborting',0
RET
START1:
MOV A,B ; SAVE SOURCE DISK
CPI 0FFH ; CHECK FOR CURRENT
JNZ SDISK1
LDA CDISK ; SPECIFY CURRENT DISK INSTEAD
INR A ; ADD 1 FOR FOLLOWING DECREMENT
SDISK1:
DCR A ; DOWN 1 SO RANGE IS 0-F
STA SDISK
MOV A,C ; SAVE SOURCE USER
CPI 0FFH ; CHECK FOR CURRENT
JZ SUSER0
CPI '?' ; WILD IS CURRENT
JNZ SUSER1
SUSER0:
LDA CUSER ; GET CURRENT USER
SUSER1:
STA SUSER
MOV A,M ; GET SEPARATION CHAR
CPI ',' ; COMMA IF SECOND NAME SPECIFIED
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
LDA CDISK ; SET DISK AND USER TO CURRENT
STA DDISK
LDA CUSER
STA DUSER
POP H ; GET PTR
JMP START3
START2:
INX H ; PT TO NEXT CHAR AFTER COMMA
LXI D,FCBD ; SET DEST FCB
CALL ZFNAME ; PROCESS NAME
JZ UDERR
LDA FCBD+1 ; CHECK FOR AMBIGUOUS NAME
CPI '?' ; ASSUME ALL IS AMBIGUOUS IF FIRST CHAR IS
JNZ NOSET
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
NOSET:
MOV A,B ; GET DISK
CPI 0FFH
JNZ DDISK1
LDA CDISK ; SELECT CURRENT DISK IF DEFAULT
INR A ; ADD 1 FOR FOLLOWING DECREMENT
DDISK1:
DCR A
STA DDISK
MOV A,C ; GET USER
CPI 0FFH ; CURRENT?
JZ DUSER0
CPI '?' ; WILD IS CURRENT
JNZ DUSER1
DUSER0:
LDA CUSER
DUSER1:
STA DUSER ; SET DEST USER
START3:
CALL SBLANK ; SKIP SPACES
CPI 'M' ; MULTIPLE OPTION?
JNZ START4
MVI A,0FFH ; SET FLAG
STA MULT
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
MLOOP:
CALL BANNER ; PRINT BANNER
LDA MULT ; MULTIPLE RUNS?
ORA A ; 0=NO
JZ MLOOP1
CALL PRS1 ; PRINT SOURCE FILE 1
CALL PRS2 ; PRINT SOURCE FILE 2
CALL PRINT
DB CR,LF,' Change Disks if Desired and Type ^C or A to Abort or '
DB '<RETURN> to Continue - ',0
CALL CIN ; GET RESPONSE
CALL CAPS ; CAPITALIZE
CPI 3 ; ABORT?
RZ
CPI 'A' ; ABORT?
RZ
MVI C,13 ; RESET DISKS
CALL BDOS
MLOOP1:
CALL VERIFY ; PERFORM VERIFICATION
CALL CRLF ; NEW LINE
LDA MULT ; MULTIPLE RUNS?
ORA A ; 0=NO
JNZ MLOOP ; CONTINUE IF SO
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
DB CR,LF,'COMPARE is used to quickly compare two files for '
DB 'equality'
DB CR,LF
DB CR,LF,'COMPARE is invoked by a command like:'
DB CR,LF,' COMPARE dir:file1.typ,dir:file2.typ M'
DB CR,LF,'where:'
DB CR,LF,' "file1.typ" must be specified and is unambiguous'
DB CR,LF,' "dir:" is an optional named directory (or DU:)'
DB CR,LF,' "file2.typ" is optional and set equal to '
DB '"file1.typ" if omitted'
DB CR,LF,' "M" is optional and allows Multiple Runs if given'
DB CR,LF
DB CR,LF,'Examples:'
DB CR,LF,'Command Files Compared'
DB CR,LF,'COMPARE T.COM,A1: $$:T.COM, A1:T.COM'
DB CR,LF,'COMPARE A:T.COM A$:T.COM, $$:T.COM'
DB CR,LF,'COMPARE A:T.COM,ROOT: A$:T.COM, ROOT:T.COM'
DB CR,LF,'COMPARE 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 BANNER ; PRINT BANNER
CALL CRLF
CALL PRFN ; PRINT FILE NAME
CALL PRINT
DB ' Ambiguous File Name not Allowed',CR,LF,0
RET
;
; PRINT BANNER
;
BANNER:
CALL PRINT
DB 'COMPARE 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 File 1 -- ',0
LXI H,SDISK ; PT TO FIRST BYTE
CALL PRUD
LXI D,FCBS ; COMPUTE CRC FOR SOURCE FCB
JMP PRFN ; PRINT FILE NAME
PRS2:
CALL PRINT
DB CR,LF,'Source File 2 -- ',0
LXI H,DDISK ; PT TO FIRST BYTE
CALL PRUD
LXI D,FCBD ; COMPUTE CRC FOR DESTINATION FCB
JMP PRFN ; PRINT FILE NAME
;
; MAIN VERIFY ROUTINE
;
VERIFY:
CALL PRS1 ; PRINT SOURCE 1
LDA SDISK ; SELECT DISK AND USER
MOV B,A
LDA SUSER
MOV C,A
CALL LOGUD ; LOG IN DISK AND USER IN B,C
CALL CRCCLR ; CLEAR CRC
CALL COMPCRC ; READ IN FILE
CALL CRCDONE ; GET CRCK VALUE
SHLD CRCVAL ; SAVE IT
LDA BCNT ; GET OLD BLOCK COUNT
STA BCNT1 ; SAVE IT
CALL PRS2 ; PRINT NAME OF SOURCE 2
LDA DDISK ; SELECT DISK AND USER
MOV B,A
LDA DUSER
MOV C,A
CALL LOGUD ; LOG IN DISK AND USER IN B,C
CALL CRCCLR ; CLEAR CRC
CALL COMPCRC ; READ IN FILE
LDA BCNT ; GET BLOCK COUNT
MOV B,A ; RESULT IN B
LDA BCNT1 ; CHECK FOR SAME SIZE
CMP B ; COMPARE BLOCK SIZES
JNZ NOMATCH ; NO MATCH IF NOT SAME
LHLD CRCVAL ; GET OLD CRC VALUE
XCHG ; VALUE IN DE
CALL CRCDONE ; UPDATE COMPLETE
CALL COMPHD ; COMPARE HL TO DE
JNZ NOMATCH
CALL PRINT
DB CR,LF,'** Files are Identical **',0
RET
; VERIFY ERROR
NOMATCH:
CALL PRINT
DB CR,LF,'** Files are Different **',0
RET
;
; READ IN FILE AND COMPUTE ITS CRC; DE PTS TO FILE'S FCB
;
COMPCRC:
CALL CRCCLR ; CLEAR CRCK VALUE
CALL INITFCB ; INIT FCB FIELDS
CALL F$OPEN ; OPEN FILE
CPI 0FFH ; FILE NOT FOUND?
JNZ LOAD ; LOAD DATA AND COMPUTE CRCVAL AND BCNT
POP H ; CLEAR 2 LEVELS OF RETURN ADDRESS
POP H
CALL CRLF
CALL PRFN ; PRINT FILE NAME
CALL PRINT
DB ' File Not Found',CR,LF,0
RET
;
; LOAD BUFFER FROM FILE WHOSE FCB IS PTED TO BY DE
; ON OUTPUT, BCNT=NUMBER OF BLOCKS LOADED (UP TO 128) AND
; CONT=0 IF DONE OR 128 IF NOT DONE
;
LOAD:
XRA A ; A=0
STA BCNT ; SET BLOCK COUNT
; MAIN CRC EVALUATION LOOP
LOAD1:
CALL F$READ ; READ IN BLOCK
ORA A ; END OF FILE?
JNZ LOAD3 ; RETURN
LXI H,BUFF ; PT TO BUFFER TO COMPUTE CRC FROM
MVI B,128 ; COPY 128 BYTES
LOAD2:
MOV A,M ; GET BYTE
CALL CRCUPD ; UPDATE CRC
INX H ; PT TO NEXT
DCR B ; COUNT DOWN
JNZ LOAD2
LDA BCNT ; GET BLOCK COUNT
INR A ; INCREMENT IT
STA BCNT ; SET IT
JMP LOAD1 ; CONTINUE
LOAD3:
CALL F$CLOSE ; CLOSE FILE
RET
;
; PRINT DISK/USER PTED TO BY HL (2 BYTES)
;
PRUD:
MOV A,M ; GET DISK
ADI 'A' ; 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
;
MULT:
DS 1 ; MULTIPLE RUN FLAG (0=NO MULT RUNS)
CDISK:
DS 1 ; CURRENT DISK
CUSER:
DS 1 ; CURRENT USER
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
CRCVAL:
DS 2 ; CRC VALUE
CURDISK:
DS 1 ; CURRENT DISK NUMBER
BCNT:
DS 1 ; BUFFER COUNT
BCNT1:
DS 1 ; SECOND BUFFER COUNT
INLINE:
DS 200 ; INPUT LINE BUFFER
END