home *** CD-ROM | disk | FTP | other *** search
- *#######################################################################
- * PROGRAM COMP...File Compare Utility
- *
- * Dr. David C. Wilcox
- * DCW Industries, Inc.
- * 5354 Palm Dr., La Canada, CA 91011
- * 818/790-3844
- *
- * April 13, 1986
- *#####################################################################
- boot equ 00 *warm boot
- rchar equ 01 *console input
- wchar equ 02 *console output
- print equ 09 *print string
- constat equ 11 *console status
- openf equ 15 *open file
- readf equ 20 *sequential read
- setdma equ 26 *set dma address
- userf equ 32 *get/set user number
- break equ 03 *ascii etx (^C)
- lf equ 10 *line feed
- cr equ 13 *carriage return
- xoff equ 19 *ascii dc3 (^S)
- esc equ 27 *ascii escape
- space equ 32 *ascii space
- upmask equ $5f *upper case mask
- bdos equ $0002 *BDOS entry point
- *#####################################################################
- * Special registers:
- *
- * a4 = address of 2nd parsed fcb
- * a5 = address of dma buffer
- * a6 = address of 1st parsed fcb
- * d4 = number of records in file2
- * d5 = total number of records
- * d6 = number of records in file1
- * d7 = current user number
- *#####################################################################
- *
- * Locate fcb and dma (for portability)
- *
- link a6,#0 *mark stack frame
- move.l 8(a6),a0 *get base page address
- lea $80(a0),a5 *get address of dma buffer
- lea $5c(a0),a6 *get address of 1st parsed file name
- lea $38(a0),a4 *get address of 2nd parsed file name
- jsr clear *clear all data registers
- *
- * Check for no files specified
- *
- cmpi.b #space,$1(a6)
- bne start
- move.l #usage,d1 *if no parameters...
- jsr pstring *display instructions
- jsr quit *and exit to CP/M
- *
- start: movea.l a5,a1 *point to dma
- move.b (a1)+,d2 *put total characters in d2
- *
- move.l #0,d5 *get the name of file1
- movea.l #file1,a0
- sfile1: move.b (a1)+,(a0)+
- addq #1,d5
- subq #1,d2 *make sure we're not out of characters
- beq error *before we find a space
- cmpi.b #space,(a1)
- bne sfile1
- adda.l #1,a1 *skip over the space
- *
- move.l #0,d4 *now get the name of file2
- movea.l #file2,a0
- dfile1: move.b (a1)+,(a0)+
- addq #1,d4
- subq #1,d2 *make sure we're not out of characters
- blt error *before we find the null
- cmpi.b #0,(a1)
- bne dfile1
- *
- * Parse the filespecs and make valid fcb's if necessary
- *
- jsr chkwld *check for wildcards
- jsr usrset *set default user numbers
- jsr usrchk *check for compare across user areas
- *
- * Open the files
- *
- jsr open1 *open file1
- jsr open2 *open file2
- move.b #0,32(a6) *set current record to zero for
- move.b #0,32(a4) *both file1 and file2
- *
- * Fill the buffers and compare 16k at a time
- *
- move.l #0,d5 *initialize record count
- fillem: jsr chkcon *check console
- jsr filbuf2 *fill buffer2
- jsr chkcon *check console
- jsr filbuf1 *fill buffer1
- jsr compare *compare byte by byte
- cmpi.w #0,d5 *any more extents?
- beq quit *no....all done
- bra fillem *yes...go back for more
- *
- *#######################################################################
- * Subroutines
- *#######################################################################
- *
- * Change user number if different from current user
- *
- chgusr:
- cmp.b d7,d1
- beq donusr
- move.b d1,d7
- move.w #userf,d0
- trap #bdos
- donusr: rts
- *
- * Check for character entered at keyboard
- *
- chkcon:
- move.w #constat,d0 *check console status
- trap #bdos
- cmpi.b #0,d0 *anything there?
- beq chkdon *no....return
- getchr: move.w #rchar,d0 *yes...get the character
- trap #bdos
- cmpi.b #break,d0 *is it an abort (^C)?
- beq uabort *yes...say so and return to CP/M
- cmpi.b #xoff,d0 *is it a pause (^S)?
- bne chkdon *no....ignore it and return
- bra getchr *yes...hang until another char entered
- uabort: move.l #ustop,d1 *display user abort message
- jsr pstring
- bra quit *and return to CP/M
- chkdon: rts
- *
- * Check for wildcards in parsed fcb's
- *
- chkwld:
- move.l #11,d2
- movea.l a6,a2
- movea.l a4,a3
- adda #1,a2
- adda #1,a3
- cloop: cmpi.b #'?',(a2)+
- beq nowild
- cmpi.b #'?',(a3)+
- beq nowild
- subq.b #1,d2
- bne cloop
- rts
- *
- * Clear all data registers
- *
- clear:
- clr.l d0
- clr.l d1
- clr.l d2
- clr.l d3
- clr.l d4
- clr.l d5
- clr.l d6
- clr.l d7
- rts
- *
- * Clear fcb
- *
- clrfcb:
- movea.l a0,a2
- move.l #11,d3
- blank1: move.b #space,(a2)+
- subq #1,d3
- bne blank1
- move.l #20,d3
- blank2: move.b #0,(a2)+
- subq #1,d3
- bne blank2
- rts
- *
- * Compare the two files and report any differences found
- *
- compare:
- move.l d4,d3
- cmp.l d4,d6 *same number of sectors?
- beq samlen *yes...continue
- bgt eof2
- move.b #1,flag1 *mark file1 as shortest
- move.l d6,d3
- bra samlen
- eof2: move.b #1,flag2 *mark file2 as shortest
- samlen: add.l d3,d5 *update record count
- cmpi.b #128,d3 *is this the last extent?
- beq skip *no....continue
- move.b #1,lastex *yes...set flag
- skip: clr.l d2 *zero the byte count
- movea.l #buffer1,a1 *point to file1
- movea.l #buffer2,a2 *point to file2
- compr: cmpm.b (a1)+,(a2)+ *compare a byte
- beq same
- jsr shodif *show difference message
- addi.b #1,count *increment difference count
- movea.l #count,a0 *check for 10 differences
- cmpi.b #10,(a0)
- beq abort *give up if 10 differences
- same: addq.b #1,d2 *increment byte count
- cmpi.b #128,d2 *end of record?
- bne compr *no....go back for another character
- subq.b #1,d3 *decrement record count
- beq nomore *quit if all records compared
- jsr chkcon *check the console
- clr.l d2 *reset the byte counter
- bra compr *and go back for another record
- nomore: movea.l #lastex,a0 *is this the last extent?
- cmpi.b #1,(a0)
- beq finish *yes...print final message
- rts
- finish: movea.l #count,a0 *check difference count
- cmpi.b #0,(a0) *any found?
- bne unequal *yes...say so and quit
- move.l #crlf,d1
- jsr pstring *no....display identical message
- move.l #file1,d1
- jsr pstring
- move.l #eqmsg1,d1
- jsr pstring
- move.l #file2,d1
- jsr pstring
- move.l #eqmsg2,d1
- jsr pstring
- unequal:movea.l #flag1,a0 *check for early eof on file1
- cmpi.b #1,(a0) *flag set?
- bne check2 *no....check file2
- move.l #efmsg1,d1 *yes...say so and quit
- jsr pstring
- move.l #file1,d1
- jsr pstring
- move.l #efmsg2,d1
- jsr pstring
- move.l #file2,d1
- jsr pstring
- move.l #crlf,d1
- jsr pstring
- bra alldone
- check2: movea.l #flag2,a0 *check for early eof on file2
- cmpi.b #1,(a0) *flag set?
- bne alldone *no...exit
- move.l #efmsg1,d1 *yes...say so and quit
- jsr pstring
- move.l #file2,d1
- jsr pstring
- move.l #efmsg2,d1
- jsr pstring
- move.l #file1,d1
- jsr pstring
- move.l #crlf,d1
- jsr pstring
- bra alldone
- abort: move.l #abtmsg,d1
- jsr pstring
- alldone:move.l #0,d5 *d5 = 0 causes exit
- rts
- *
- * Show record and byte where difference exists
- *
- shodif:
- move.l #dfmsg1,d1 *print first part of message
- jsr pstring
- move.l d5,d1 *compute record number
- sub.l d3,d1
- jsr decprt *display it
- move.l #dfmsg2,d1 *print second part of message
- jsr pstring
- move.l d2,d1 *display byte number
- jsr decprt
- move.l #crlf,d1 *conclude with cr,lf
- jsr pstring
- rts
- *
- * Print d1 in decimal
- *
- decprt:
- move.l d3,d3save *save register d3
- move.l d4,d4save *save register d4
- move.l d1,d4
- clr.l d3 *print 1000's digit
- move.w d4,d3
- divu #1000,d3
- move.l d3,d4
- jsr digit
- swap d4
- clr.l d3 *print 100's digit
- move.w d4,d3
- divu #100,d3
- move.l d3,d4
- jsr digit
- swap d4
- clr.l d3 *print 10's digit
- move.w d4,d3
- divu #10,d3
- move.l d3,d4
- jsr digit
- swap d4
- move.w d4,d1 *print units digit
- addi.b #'0',d1
- jsr type
- movea.l #d3save,a0 *restore d3 and d4
- move.l (a0),d3
- movea.l #d4save,a0
- move.l (a0),d4
- rts
- digit: move.b d3,d1
- addi.b #'0',d1 *make it ascii
- type: move.w #wchar,d0 *and print it
- trap #bdos
- rts
- *
- * Fill buffer1
- *
- filbuf1:
- clr.l d1 *select appropriate user number
- movea.l #user1,a0
- move.b (a0),d1
- jsr chgusr
- move.l #0,d6 *initialize record count
- movea.l #buffer1,a3 *point to start of buffer
- loopf1: move.l a3,d1 *set dma to current location
- move.w #setdma,d0 *in buffer1
- trap #bdos
- move.l a6,d1 *point to fcb1
- move.w #readf,d0 *and read a record
- trap #bdos
- cmpi.b #1,d0 *end of file?
- beq donfl1 *yes...stop reading
- addq.b #1,d6 *no....increment record count
- cmpi.b #128,d6 *have we done a complete extent?
- beq donfl1 *yes...stop reading, buffer is full
- adda.l #128,a3 *no....add 128 to buffer address
- bra loopf1 *and go back for another record
- donfl1: rts
- *
- * Fill buffer2
- *
- filbuf2:
- clr.l d1 *select appropriate user number
- movea.l #user2,a0
- move.b (a0),d1
- jsr chgusr
- move.l #0,d4 *initialize record count
- movea.l #buffer2,a3 *point to start of buffer
- loopf2: move.l a3,d1 *set dma to current location
- move.w #setdma,d0 *in buffer2
- trap #bdos
- move.l a4,d1 *point to fcb1
- move.w #readf,d0 *and read a record
- trap #bdos
- cmpi.b #1,d0 *end of file?
- beq donfl2 *yes...stop reading
- addq.b #1,d4 *no....increment record count
- cmpi.b #128,d4 *have we done a complete extent?
- beq donfl2 *yes...stop reading, buffer is full
- adda.l #128,a3 *no....add 128 to buffer address
- bra loopf2 *and go back for another record
- donfl2: rts
- *
- * Open file1
- *
- open1:
- clr.l d1
- movea.l #user1,a0
- move.b (a0),d1
- jsr chgusr
- move.l a6,d1
- move.w #openf,d0
- trap #bdos
- cmpi.b #$ff,d0
- bne donop1
- move.l #nofile,d1
- jsr pstring
- move.l #file1,d1
- jsr pstring
- move.l #crlf,d1
- jsr pstring
- bra quit
- donop1: rts
- *
- * Open file2
- *
- open2:
- clr.l d1
- movea.l #user2,a0
- move.b (a0),d1
- jsr chgusr
- move.l a4,d1
- move.w #openf,d0
- trap #bdos
- cmpi.b #$ff,d0
- bne donop2
- move.l #nofile,d1
- jsr pstring
- move.l #file2,d1
- jsr pstring
- move.l #crlf,d1
- jsr pstring
- bra quit
- donop2: rts
- *
- * Display the string addressed by d1 on the console
- *
- pstring:
- move.w #print,d0
- trap #bdos
- rts
- *
- * Display error message and quit
- *
- error:
- move.l #errmsg,d1
- jsr pstring
- *
- * Quit to CP/M
- *
- quit:
- clr.l d1
- movea.l #user0,a0
- move.b (a0),d1
- jsr chgusr
- move.w #boot,d0
- trap #bdos
- *
- * Display no wildcard message
- *
- nowild:
- move.l #wldmsg,d1
- jsr pstring
- bra quit
- *
- * Fill the fcb's
- *
- filfcb:
- movea.l a3,a0
- adda #1,a0 *point to first char in file name
- jsr clrfcb *fill fcb with spaces
- move.l #8,d3 *d3 is the counter
- lname: move.b (a1)+,d0 *get character from dma string
- cmpi.b #'*',d0 *disallow wildcards
- beq nowild
- cmpi.b #'?',d0
- beq nowild
- cmpi.b #'.',d0 *filetype delimiter?
- beq lnamef
- cmpi.b #'a',d0 *lower case?
- blt nsave
- andi.b #upmask,d0 *make it upper case
- nsave: move.b d0,(a0)+ *store it in fcb
- subq #1,d3
- beq lnamef *all 8 chars processed
- subq #1,d2
- beq fildon *no more chars in dma string
- bra lname *go back for another character
- lnamef: subq #1,d2
- beq fildon *no more chars in dma string
- movea.l a3,a0 *make a0 point to first
- adda #9,a0 *char in type field
- cmpi.b #'.',(a1) *are we pointing to delimiter?
- bne fnext *no...carry on
- adda #1,a1 *yes...skip over it
- subq #1,d2
- beq fildon *no more chars in dma string
- fnext: move.l #3,d3 *d3 is the counter
- ltype: move.b (a1)+,d0 *get character from dma string
- cmpi.b #'*',d0 *disallow wildcards
- beq nowild
- cmpi.b #'?',d0
- beq nowild
- cmpi.b #'a',d0 *lower case?
- blt msave
- andi.b #upmask,d0 *make it upper case
- msave: move.b d0,(a0)+ *store it in fcb
- subq #1,d3
- beq fildon *all 3 chars processed
- subq #1,d2
- beq fildon *no more chars in dma string
- bra ltype *go back for another character
- fildon: rts
- *
- * Check for file1 user area
- *
- usrchk:
- movea.l #file1,a1
- move.b d5,d2
- move.w #1,d1
- schek: cmpi.b #':',(a1)
- beq sdrv
- adda #1,a1
- addq #1,d1
- subq #1,d2
- bne schek
- bra dchek0 *no user specified...check file2
- sdrv: cmpi.b #2,d1 *is it the logged user?
- bne sdig1 *no...check number of digits
- bra dchek0 *yes...further action not required
- sdig1: cmpi.b #3,d1 *is it a single digit user?
- bne sdig2 *no...check for two digit user
- movea.l #file1,a1 *get the drive number
- move.b (a1)+,d0
- andi.b #upmask,d0 *make it upper case
- subi.b #64,d0 *make it a number
- move.b d0,(a6) *save it in fcb1
- move.b (a1),d0 *get user number
- subi.b #'0',d0 *make it a number
- move.b d0,user1 *save user number in proper location
- move.b d5,d2
- subq #3,d2
- movea.l #file1+3,a1 *copy the rest to fcb1
- movea.l a6,a3
- jsr filfcb
- bra dchek0
- sdig2: cmpi.b #4,d1 *is it a two digit user?
- bne error *no...incorrect user number
- movea.l #file1,a1 *get the drive number
- move.b (a1)+,d0
- andi.b #upmask,d0 *make it upper case
- subi.b #64,d0 *make it a number
- move.b d0,(a6) *save it in fcb1
- movea.l #file1+2,a1 *get the second digit of user number
- move.b (a1),d0 *put it in d0
- subi.b #'0',d0 *make it a number
- addi.b #10,d0 *add 10 to it
- move.b d0,user1 *save user number in proper location
- move.b d5,d2
- subq #4,d2
- movea.l #file1+4,a1 *copy the rest to fcb1
- movea.l a6,a3
- jsr filfcb
- dchek0: movea.l #file2,a1 *check for file2 user area
- move.b d4,d2
- move.w #1,d1
- dchek: cmpi.b #':',(a1)
- beq ddrv
- adda #1,a1
- addq #1,d1
- subq #1,d2
- bne dchek
- move.b d4,d2 *no drive or user specified
- movea.l #file2,a1 *fill fcb2 in case a user was
- movea.l a4,a3 *given for file1 which sometimes
- jsr filfcb *zaps the second fcb
- rts
- ddrv: cmpi.b #2,d1 *is it the logged user?
- bne ddig1 *no...check number of digits
- movea.l #file2,a1 *get the drive number
- move.b (a1)+,d0
- andi.b #upmask,d0 *make it upper case
- subi.b #64,d0 *make it a number
- move.b d0,(a4) *save it in fcb2
- move.b d4,d2 *no user specified
- subq #2,d2
- movea.l #file2+2,a1 *fill fcb2 in case a user was
- movea.l a4,a3 *given for file1 which sometimes
- jsr filfcb *zaps the second fcb
- rts
- ddig1: cmpi.b #3,d1 *is it a single digit user?
- bne ddig2 *no...check for two digit user
- movea.l #file2,a1 *get the drive number
- move.b (a1)+,d0
- andi.b #upmask,d0 *make it upper case
- subi.b #64,d0 *make it a number
- move.b d0,(a4) *save it in fcb2
- move.b (a1),d0 *get user number
- subi.b #'0',d0 *make it a number
- move.b d0,user2 *save user number in proper location
- move.b d4,d2
- subq #3,d2
- movea.l #file2+3,a1 *copy the rest to fcb2
- movea.l a4,a3
- jsr filfcb
- rts
- ddig2: cmpi.b #4,d1 *is it a two digit user?
- bne error *no...incorrect user number
- movea.l #file2,a1 *get the drive number
- move.b (a1)+,d0
- andi.b #upmask,d0 *make it upper case
- subi.b #64,d0 *make it a number
- move.b d0,(a4) *save it in fcb2
- movea.l #file2+2,a1 *get the 2nd digit of user number
- move.b (a1),d0 *put it in d0
- subi.b #'0',d0 *make it a number
- addi.b #10,d0 *add 10 to it
- move.b d0,user2 *and store it in proper location
- move.b d4,d2
- subq #4,d2
- movea.l #file2+4,a1 *copy the rest to fcb2
- movea.l a4,a3
- jsr filfcb
- rts
- *
- * Set default user numbers
- *
- usrset:
- move.w #$ff,d1
- move.w #userf,d0
- trap #bdos
- move.b d0,d7
- move.b d0,user0
- move.b d0,user1
- move.b d0,user2
- rts
- *#####################################################################
- * Console Messages
- *#####################################################################
- even
- d3save: ds.l 1
- d4save: ds.l 1
- count: dc.b 0 *mismatch count
- flag1: dc.b 0 *file1 eof flag
- flag2: dc.b 0 *file2 eof flag
- lastex: dc.b 0 *last extent flag
- user0: ds.b 1 *user number at start of run
- user1: ds.b 1 *user number for file1
- file1: dc.b '$$$$$$$$$$$$$$$$'
- dc.b '$$$$$$$$$$$$$$$$' *name of file1
- user2: ds.b 1 *user number for file2
- file2: dc.b '$$$$$$$$$$$$$$$$'
- dc.b '$$$$$$$$$$$$$$$$' *name of file2
- even
- usage: dc.b lf,cr
- dc.b 'Correct usage:',cr,lf,lf
- dc.b ' COMP {d1<u1>:}file1 {d2<u2>:}file2'
- dc.b cr,lf,lf
- dc.b ' d1 = file1 drive',cr,lf
- dc.b ' u1 = file1 user number',cr,lf
- dc.b ' d2 = file2 drive',cr,lf
- dc.b ' u2 = file2 user number',cr,lf,lf
- dc.b 'COMPare terminates if 10 differences are found'
- dc.b cr,lf,lf,'$'
- even
- errmsg: dc.b 'File name error...COMP aborted',cr,lf,'$'
- wldmsg: dc.b 'Error...Wildcards NOT supported',cr,lf,'$'
- nofile: dc.b 'Error...Unable to open $'
- eqmsg1: dc.b ' and $'
- eqmsg2: dc.b ' are identical',cr,lf,'$'
- efmsg1: dc.b cr,lf,'End of file on $'
- efmsg2: dc.b ' before $'
- dfmsg1: dc.b 'Files differ in sector $'
- dfmsg2: dc.b ', byte $'
- crlf: dc.b cr,lf,'$'
- abtmsg: dc.b cr,lf
- dc.b ' 10 differences found..COMP aborted '
- dc.b cr,lf,'$'
- ustop: dc.b cr,lf
- dc.b ' COMP aborted by user '
- dc.b cr,lf,'$'
- even
- buffer1 equ *
- buffer2 equ *+16384
- *#####################################################################
- end