home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE CFcomp - CHKfile file compare utility
- ; SUBTTL General program description and use of common storage
- ;-----------------------------------------------------------------------------;
- ; CFCOMP - Compare output files created by CHKfile ;
- ;-----------------------------------------------------------------------------;
- ; CFCOMP 1.0 ■ PCDATA TOOLKIT Copyright (c) 1990 Ziff Communications Co. ;
- ; PC Magazine ■ Wolfgang Stiller ;
- ; ;
- ;-----------------------------------------------------------------------------;
- ;
- ; Purpose: ;
- ; CFCOMP does a high speed compare of redirected output (report) files ;
- ; captured from CHKfile. CFCOMP then displays which files have been ;
- ; changed, deleted or added between the creation of the OLD and NEW ;
- ; report files. ;
- ; ----------------------------------------------------------------------------;
- ;Format: ;
- ; ;
- ;CFCOMP OLDfile NEWfile [/C] [/O] [/P] ;
- ; ;
- ; OLDfile and NEWfile are CHKFILE.COM created report files. ;
- ; "/C" Changes only - reports and checks only for changed files ;
- ; and ignores additions or deletions from file list. ;
- ; "/O" Only use check fields and file size for comparison. DOS time ;
- ; and date stamps are not used in comparing. ;
- ; "/P" Pauses after each page of output if non-matches are detected.;
- ; ----------------------------------------------------------------------------;
- ;Remarks: ;
- ; CFCOMP utilizes a high speed compare algorithm tailored specifically ;
- ; to comparing data produced by CHKfile. It will work even if the ;
- ; directories have been sorted in a different order. The order of the ;
- ; files in the NEW and OLD files is completely independent. If the order ;
- ; is the same, (which is usually the case) CFCOMP runs the fastest. If ;
- ; both files were created using the /T option on CHKfile, then CFCOMP ;
- ; will report whether the totals match. If the totals match, yet CFCOMP ;
- ; reports additions and deletions, this usually indicates that files ;
- ; were effectively renamed. CFCOMP writes to DOS standard output, so ;
- ; that its output may be redirected to a file. "CFCOMP A B >OUT" will ;
- ; compare old file A and new file B with any differences reported on ;
- ; file OUT. ;
- ; ;
- ; If the OLDfile is not found, CFCOMP will report this fact and then ;
- ; continue executing, treating OLDfile as if it were an empty file. ;
- ; ;
- ; The individual report (input) files may not be larger than 65,536 ;
- ; bytes. This size allows up to 1260 file entries in each report file. ;
- ; To compare this many entries in each file, CFCOMP requires that at ;
- ; least 133,000 bytes of memory are free. CFCOMP will automatically ;
- ; adjust its memory allocation to use whatever memory is available. For ;
- ; each 1000 less bytes of free memory, 10 fewer file entries can be ;
- ; supported. ;
- ; ;
- ; All serious error conditions (such as a corrupted or invalid report ;
- ; file) will result in an error message accompanied by a beep, a prompt ;
- ; and a wait for a key press. ;
- ; ;
- ; CFCOMP will return the following DOS ERRORLEVELs (decimal): ;
- ; 128 - indicates control card syntax error ;
- ; 20 - indicates file open or other I/O error on one of the files ;
- ; 16 - indicates file(s) of invalid type for CFCOMP or file too large ;
- ; (64K or larger is too large - this is more than 1260 lines) ;
- ; 12 - indicates file(s) have been changed ;
- ; 8 - indicates file(s) added and/or deleted but no files changed ;
- ; 4 - indicates file(s) have probably been renamed rather than actually ;
- ; changed or deleted, since the "TOTAL==>" lines match but the files ;
- ; themselves did not. ;
- ; 0 - files match exactly ;
- ; -------------------------------------------------------------------------- ;
- ;Sample output: ;
- ; ;
- ;CFCOMP 1.0 [(c) 1989 W. Stiller] comparing in directory: \ASM\EXAMPLES ;
- ; File Name + Check Check File Update Update ;
- ; Extension: Val1: Val2: Size: Date: Time: ;
- ; ---------- ---- ---- ----- ------ ------ ;
- ;Chgd: OLD:SDOC.BAK BC37 2709 61A6 02/09/89 00:07:54 ;
- ; NEW:SDOC.BAK A6B4 A64F 6769 02/11/89 23:55:02 ;
- ;Chgd: OLD:SDOC BC37 2709 61A6 02/09/89 00:13:48 ;
- ; NEW:SDOC BC37 2709 61A6 02/12/89 00:07:54 ;
- ;Deleted-->OUT 1E4A 4FD5 65 02/12/89 00:10:30 ;
- ;NEW Fil-->NEWOUT.TXT 1E4A 4FD5 65 02/12/89 00:10:30 ;
- ;NEW Fil-->TESTDIR Dir. 02/11/89 00:07:48 ;
- ;File totals unequal ;
- ; ;
- ;Notes: CFCOMP displays which directory it is in, when doing the compare. ;
- ; In this case, it is in directory \ASM\EXAMPLES. Files SDOC and ;
- ; SDOC.BAK have both changed. Even though file OUT has apparently ;
- ; been deleted and file NEWOUT.TXT has been added, it is obvious ;
- ; that file OUT has merely been renamed since the check values and ;
- ; file sizes match. TESTDIR is the name of a directory which has ;
- ; been added. ;
- ; ----------------------------------------------------------------------------;
-
- ;---------------------------------------------------------------;
- ; Constants: ;
- ;---------------------------------------------------------------;
- BOX EQU 254 ;Small box character code
- CR EQU 0Dh
- LF EQU 0Ah
- CRLF EQU 0A0Dh ;Carriage return line feed.
- DSP_Key_len EQU 12 ;Length of the key part of DSP record
- DSP_Rec_len EQU 51 ;Length of the DSP (Display) record
-
-
- CSEG SEGMENT
- ASSUME CS:CSEG, DS:CSEG, ES:Nothing, SS:CSEG
- SUBTTL Main program
- ;******************************************************************************;
- ;** Main program begins here -CFCOMP- **;
- ;******************************************************************************;
- ORG 100H ; THIS IS A COM TYPE PROGRAM
- CFCOMP:
- CALL Parse_parms_Open_Files ;Parse cmdline paramters + open files
-
- MOV BX,offset Buffer_Area+200 ;locate stack down in prog storage
- MOV SP,BX ;Stack of 200 bytes
-
- CALL Allocate_Memory ;Allocate memory for file buffers
- ;and release other unused memory.
- ;ES will point to start of alloc mem
-
- CALL Read_and_Validate_Files ;Validate that both files are
- ;readable and of right type to read
- ;DS is now addressing DATA SEG (DS=CS)
- XOR BX,BX ;Zero highest error level variable(BL)
- MOV BH,Page_mode ;Load line counter + pagemode flag
- ; =FFh for no paging
- CALL Compare_Files ;Compare OLD file with NEW file and
- ; determine changed or deleted recs
- CALL Scan_for_Additions ;Look for records left on NEW file
- CALL Compare_totals ;Check if total===> lines match
- CMP BH,0FFh ;See if page mode is off (= FFh)
- JE Normal_termination ; IF turned off, skip page control
- OR BL,BL ;See if changes detected (BL not = 0)
- JE Normal_termination ; If no changes, then terminate
- CALL Page_Wait ; otherwise pause for user to read
- ; the display.
- Normal_termination:
- MOV AL,BL ;Load error level for termination
- MOV AH,4Ch ; terminate
- INT 21h
-
- ;---------------------------------------------------------------------------;
- ; Compare files - will compare OLD and NEW file (51 char DISPLAY records) ;
- ;---------------------------------------------------------------------------;
- ; Register conventions: ;
- ; DS=Segment register for OLD SEG ES=NEW report file segment ;
- ; SI=offset of current OLD rec DI=offset of current NEW rec ;
- ; CX=number of OLD recs left to proc. BP=offset of last NEW rec ;
- ; BL=highest code for DOS errorlevel BH=line counter (for /P option) ;
- ;---------------------------------------------------------------------------;
- ; Entry: ;
- ; Both files have been read into buffers and validated ;
- ; DS is segment register for DATA(=CS); ES is segment regst for NEW file. ;
- ; BP is offset 1st rec on NEW file ;
- ; Exit: ;
- ; All matched NEW file entries have 1st byte of filename zeroed. ;
- ; Reports have been written to Std output, on discrepancies so far. ;
- ; BL = 12 if changes, =8 if added/deleted files, and =0 for no changes ;
- ;---------------------------------------------------------------------------;
- Compare_early_exit:
- RET
- Compare_Files: ;<==== Enter here
- MOV DI,BP ;1st record address of NEW file
- MOV SI,OLD_File_Start ;1st record address of OLD file
- MOV CX,OLD_Rec_count ;number of records on OLD file
- JCXZ Compare_early_exit ;If no files in OLD directory: EXIT
- MOV BP,NEW_End_Of_File ;Offset after last rec on NEW file
- MOV AX,ES ;NEW file SEGment
- SUB AX,File_Size_PARAs ;Back down from NEW file to OLD file
- MOV DS,AX ;DS = SEG reg for OLD file
- SUB DI,DSP_Rec_Len ;Point to -1 record on NEW file
- SUB SI,DSP_Rec_Len ;Point to record -1 on OLD file
-
- Compare_Next: ;Main compare loop - Get next NEW+OLD
- ADD DI,DSP_Rec_Len ;Advance to next NEW record
- Check_Next_OLD_REC: ;Secondary compare loop: next OLD rec
- ADD SI,DSP_rec_len ;Advance to next OLD rec
- CMP DI,BP ;Compare offset of this NEW rec + EOF
- JB Compare_Keys ; If we are not past EOF on this rec
- CALL Display_Deleted_MSG ; Else remaining old recs are deletd
- LOOP Check_Next_OLD_REC ;Continue reporting deleted old recs
- RET ;All done with main file compare
-
- Compare_Keys:
- ; Compare File keys (1st 12 characters of each record)
- MOV DX,CX ;Save a copy of CX (# of old recs)
- MOV CX,DSP_Key_Len/2 ;Compare 12 character key (6 words)
- PUSH DI ;Save current NEW rec loc
- PUSH SI ;Save current OLD rec loc
- REPE CMPSW ;Do compare
- JNE Find_Matching_NEW_Rec ;if not =, Scan NEW file for a match
-
- ; Now compare the actual records (keys already match):
- ; ***Warning*** the length field of following instr may be patched by /O
- PATCH1: MOV CX,18 ;Check remainder of record (18 words)
- INC DI ;Skip checking next blank separator
- INC SI ;Skip checking next blank separator
- REPE CMPSW ;Do compare
- POP SI ;Point back to start of this OLD rec
- POP DI ;Point back to start of this NEW rec
- JE Good_compare ;If the records match
- CALL Display_changed_MSG ;Report detection of changed record
- Good_compare:
- ; Now zero out the 1st byte of the matched NEW file record:
- XOR AX,AX ;Zeros to store on key of record
- STOSB ;Zero 1st byte
- DEC DI ;Point back to beginning of NEW rec
- MOV CX,DX ;Restore OLD file recs remaining count
- LOOP Compare_Next ;Go check next record on OLD file
- RET ;All done with COMPARE_FILE
-
- ;-------------------------------------------;
- ;Search NEW file records for a matching key ;
- ;-------------------------------------------;
- Find_Matching_NEW_Rec: ;Search NEW file to match OLD file rec
- POP SI ;Restore pointer to current record
- POP DI ;Restore pointer to current record
- SUB SP,2 ;Leave current NEW rec pointer on stak
-
- Continue_NEW_file_Search:
- ADD DI,DSP_Rec_Len ;Next record on NEW file
- ; Are we at end of file on NEW file ?
- CMP DI,BP ;Compare current NEW rec with EOF
- JB Compare_Keys_NEW_Rec ;IF not EOF, go compare this key
- ; We are at END Of File (EOF) on NEW file on this search, so report deleted rec
- CALL Display_Deleted_MSG ;Report that rec from OLD file deleted
- POP DI ;Point to last CURRENT rec on NEW file
- MOV CX,DX ;Restore OLD file recs remaining count
- LOOP Check_Next_OLD_rec ;Go check next record on OLD file
- RET ;All done with COMPARE_FILE
- Compare_Keys_NEW_Rec: ; (1st 12 characters of each record)
- MOV CX,DSP_Key_Len/2 ;Compare 12 character key (6 words)
- PUSH DI ;Save current NEW rec loc
- PUSH SI ;Save current OLD rec loc
- REPE CMPSW ;Do compare
- JE Match_rest_of_NEW_Rec ;If keys =, check the records
- POP SI ;Point back to start of this OLD rec
- POP DI ;Point back to start of this NEW rec
- JMP SHORT Continue_NEW_File_Search ;Keek searching through NEW rec
-
- Match_rest_of_NEW_Rec: ;NEW file scan has found matching keys
- ; Now compare the actual records (keys already match):
- ; ***Warning*** the length field of following instr may be patched by /O
- PATCH2: MOV CX,18 ;Check remainder of record (18 words)
- INC DI ;Skip checking next blank separator
- INC SI ;Skip checking next blank separator
- REPE CMPSW ;Do compare
- POP SI ;Point back to start of this OLD rec
- POP DI ;Point back to start of this NEW rec
- JE Found_matching_NEW_rec ;If the records match
- CALL Display_changed_MSG ;Report detection of changed record
- Found_matching_NEW_rec:
- ; Now zero out 1st byte of the matched NEW file record:
- XOR AX,AX ;Zeros to store on key of record
- STOSB ;Store zero byte at start of record
- POP DI ;point to last current rec on NEW file
- MOV CX,DX ;Restore OLD file recs remaining count
- LOOP Check_Next_OLD_rec ;Go check next record on OLD file
- RET ;All done with COMPARE_FILE
-
-
-
- ;---------------------------------------------------------------------------;
- ; Scan for Additions: ;
- ; Scan through the NEW file and look for records which have not had the ;
- ; 1st byte zeroed. These recs represent added files. We will put out a ;
- ; message recording this fact. ;
- ; ENTRY: ES is segment register for NEW file ;
- ;---------------------------------------------------------------------------;
- Scan_for_Additions:
- MOV AX,CS ;Used to access normal DATA segment
- MOV DS,AX ;DS=CS (normal DATA segment)
- CMP Changes_only,'Y' ;Does user want only changes?
- JNE Scan_continue ; If not execute rest of procedure
- Scan_early_Exit:
- RET ; Otherwise, pack up and go home
- Scan_continue:
- MOV CX,NEW_Rec_Count ;Get # of 51 char recs on NEW file
- JCXZ Scan_Early_Exit ;If no NEW records to scan
- MOV DI,NEW_File_Start ;1st record on NEW file
- SUB DI,DSP_Rec_Len ;Point to record # -1
- MOV AX,ES ;Use both segment regs for NEW file
- MOV DS,AX
- Check_for_Next_Addition:
- ADD DI,DSP_Rec_Len ;Look at next NEW file record
- CMP BYTE PTR [DI],0 ;Is this a zeroed record?
- JE Continue_Zero_Check ; If zeroed, keep checking
- CALL Display_Added_MSG ; Else record file addition
- Continue_Zero_Check:
- LOOP Check_For_Next_Addition
- RET
-
- ;---------------------------------------------------------------------------;
- ; COMPARE TOTALS - If both OLD and NEW files have total lines check that ;
- ; they match. If they match, yet files were changed then put out a message;
- ; to that effect and return ERRORLEVEL 4 at termination (BL reg). ;
- ; ENTRY: ES is segment register for NEW file ;
- ; EXIT: DS is back to original Data Segment (=CS) ;
- ; BL = 4 if records have changed but both totals match. ;
- ;---------------------------------------------------------------------------;
- Compare_totals: ;Check if total===> lines match
- MOV AX,CS ;Set DS back to datasegment
- MOV DS,AX
- MOV SI,OLD_Tot_Loc ;Point to location of totals
- OR SI,SI ;Check if totals line non-exist (SI=0)
- JNE Continue_totals_1 ; If it exists, chk other totals line
- RET ; ELSE pack up and go home
- Continue_totals_1:
- MOV DI,NEW_Tot_Loc ;Point to location of totals
- OR DI,DI ;Check if totals line non-exist (DI=0)
- JNE Continue_totals_2 ; If it exists, compare the totals
- RET ; ELSE pack up and go home
- Continue_totals_2:
- CMP BH,0FFh ;See if page mode is off (= FFh)
- JE Continue_totals_3 ; IF turned off, skip page control
- MOV AL,1 ; Else Set lines to be output to 2
- CALL Page_Control ; + check if its time to pause
- Continue_totals_3:
- MOV AX,ES ;NEW file segment
- SUB AX,File_Size_PARAs ;Backup 64K
- MOV DS,AX ;DS is OLD file segment register again
- MOV CX,9 ;Compare 9 characters
- REPE CMPSB ;Compare
- MOV AX,CS ;Set DS back to datasegment
- MOV DS,AX
- MOV BP,BX ;Save highest errorlevel + line ct
- MOV BX,1 ;Handle for std output device
- JE Totals_Match
- MOV DX, offset Tot_nomatch_MSG
- MOV CX,21 ;Length of msg is 21 chars
- MOV AH,40h ;DOS Write func
- INT 21h ;Tell user that totals don't match
- MOV BX,BP ;Restore saved BX (ERRLVL + LINEct)
- RET
- Totals_match:
- MOV DX, offset Tot_match_MSG
- MOV CX,19 ;Length of msg
- MOV AH,40h ;DOS Write func
- INT 21h ;Tell user file totals are equal
- MOV BX,BP ;Restore saved BX (ERRLVL + LINEct)
- OR BL,BL ;Check if any file chgs,dels or adds
- ; (IE, BL not = 0)
- JE Totals_Return ; If no changes then we are done...
- MOV BL,4 ; ELSE, indicate probable rename
- Totals_Return:
- RET
-
- ;----------------------------------------------------------------------------;
- ; Display CHANGED Message: ;
- ; ;
- ;ENTRY: DS:SI points to OLD version of report record to format + display. ;
- ; ES:DI points to NEW version of report record to format + display. ;
- ;EXIT: ;
- ; Displays a message to standard output device informing user that a change;
- ; has occured between the OLD and NEW files. IF /P was selected then ;
- ; we check line count and pause every 24 lines. ;
- ;----------------------------------------------------------------------------;
- Display_changed_MSG: ;Display message announcing changed record
- PUSH BP
- PUSH CX
- PUSH DX
- PUSH DS ;Save (OLD) file segment
- MOV AX,CS ;Used to access normal DATA segment
- MOV DS,AX ;DS=CS (normal DATA segment)
- OR BL,BL ;Check if highest error level (BL) = 0
- JNZ Check_CHG_Page_mode ; If not 0, then header msg alrdy out
- CALL Display_Header_MSG ; Else Display the header message
- Check_CHG_Page_mode:
- CMP BH,0FFh ;See if page mode is off (= FFh)
- JE Display_changed_cont ; IF turned off, skip page control
- MOV AL,2 ; Else Set lines to be output to 2
- CALL Page_Control ; + check if its time to pause
- Display_changed_cont:
- MOV BP,BX ;Save BX in BP
- MOV DX, offset CHGD_MSG_1 ;First part of changed messaged
- MOV CX,10 ;Length of msg is 10 chars
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;BX=1 = Handle for std output device
- INT 21h ;Write beginning of OLD file chngd msg
- POP DS ;Use file segment again (OLD file)
- SUB SP,2 ;Leave DS on stack
- MOV DX,SI ;Point to OLD record
- MOV CX,DSP_Rec_Len ;Length of display record
- MOV AH,40h ;DOS Write func
- INT 21h ;Write actual OLD record out
- MOV AX,CS ;Used to access normal DATA segment
- MOV DS,AX ;Back to normal data segment again
- MOV DX, offset CHGD_MSG_2 ;First part of changed messaged
- MOV CX,10 ;Length of msg is 10 chars
- MOV AH,40h
- INT 21h ;Write beginning of OLD file chngd msg
- MOV AX,ES ;Use file segment again (NEW file)
- MOV DS,AX
- MOV DX,DI ;Point to NEW record
- MOV CX,DSP_Rec_Len ;Length of display record
- MOV AH,40h
- INT 21h ;Write actual OLD record out
- MOV BX,BP ;Restore Saved version of BX
- POP DS ;Restore addressability to OLD file
- POP DX
- POP CX
- POP BP
- MOV BL,12 ;Indicate a record has changed
- RET
-
- ;---------------------------------------------------------------------------;
- ; Display DELETED Message ;
- ; ;
- ; Entry: DS:SI must point to 51 chr DSP_REC (display record) to be displayed;
- ; ;
- ; Displays a message to standard output device informing user that a file ;
- ; has been deleted from the OLD file list. IF /P was selected then ;
- ; we check line count and pause every 24 lines. ;
- ;---------------------------------------------------------------------------;
- Display_Deleted_MSG: ;Display message announcing deleted records
- PUSH BP
- PUSH CX ;Save used registers
- PUSH DX
- PUSH DS ;Save (OLD) file segment
- MOV AX,CS ;Used to access normal DATA segment
- MOV DS,AX ;DS=CS (normal DATA segment)
- CMP Changes_only,'Y' ;Does user want only changes?
- JNE Display_Deleted_continue ; If not continue
- POP DS ; ELSE restore DS and return
- JMP Display_Deleted_Exit2 ; to caller
- Display_Deleted_continue:
- OR BL,BL ;Check if highest error level (BL) = 0
- JNZ Check_DEL_Page_mode ; If not 0, then header msg alrdy out
- CALL Display_Header_MSG ; Else Display the header message
- Check_DEL_Page_mode:
- CMP BH,0FFh ;See if page mode is off (= FFh)
- JE Display_deleted_continue2 ; IF turned off, skip page control
- MOV AL,1 ; Else Set lines to be output to 2
- CALL Page_Control ; + check if its time to pause
- Display_deleted_continue2:
- MOV BP,BX ;Save BX
- MOV DX, offset DELETED_MSG ;First part of deleted message
- MOV CX,10 ;Length of msg is 10 chars
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;Handle for std output device
- INT 21h ;Write beginning of OLD file deltd msg
- POP DS ;Use file segment again (OLD file)
- MOV DX,SI ;Point to OLD record
- MOV CX,DSP_Rec_Len ;Length of each display record
- MOV AH,40h ;DOS Write func
- INT 21h ;Write actual OLD record out
- Display_Deleted_Exit:
- MOV BX,BP ;Restore saved version of BX
- CMP BL,8 ;Check if Delete or chg already hapnd
- JAE Display_Deleted_Exit2 ; Do not change if already set
- MOV BL,8 ;Flag that Deleted record detected
- Display_Deleted_Exit2:
- POP DX
- POP CX
- POP BP
- RET
-
-
- ;---------------------------------------------------------------------------;
- ;Display ADDED Message -Indicate that a file has been added since OLD reprt;
- ; ;
- ;ENTRY: ES:DI points to NEW version of report record to format + display. ;
- ;EXIT: ;
- ; Prints a message to standard output device informing user that a file ;
- ; has been added to the NEW file list. IF /P was selected then ;
- ; we check line count and pause every 24 lines. ;
- ;---------------------------------------------------------------------------;
- Display_Added_MSG: ;Display message announcing additional files
- PUSH BP
- PUSH CX ;Save used registers
- MOV AX,CS ;Used to access normal DATA segment
- MOV DS,AX ;DS=CS (normal DATA segment)
- OR BL,BL ;Check if highest error level (BL) = 0
- JNZ Check_ADD_Page_mode ; If not 0, then header msg alrdy out
- CALL Display_Header_MSG ; Else Display the header message
- Check_ADD_Page_mode:
- CMP BH,0FFh ;See if page mode is off (= FFh)
- JE Display_Added_continue ; IF turned off, skip page control
- MOV AL,1 ; Else Set lines to be output to 2
- CALL Page_Control ; + check if its time to pause
- Display_Added_continue:
- MOV BP,BX ;Save BX
- MOV DX, offset Added_MSG ;First part of deleted message
- MOV CX,10 ;Length of msg is 10 chars
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;Handle for std output device
- INT 21h ;Write beginning of OLD file added msg
- MOV AX,ES ;Use file segment again (NEW file)
- MOV DS,AX ;DS=ES (both are seg reg for NEW file)
- MOV DX,DI ;Point to rec on NEW file (Added rec)
- MOV CX,DSP_Rec_Len ;Length of display record
- MOV AH,40h ;DOS Write func
- INT 21h ;Write actual OLD record out
- MOV BX,BP ;Restore saved version of BX
- POP CX
- POP BP
- CMP BL,8 ;Chk if Del, add or chg already hapnd
- JAE AD_or_CHG_happened ; Do not change if already set
- MOV BL,8 ;Flag that Deleted record detected
- AD_or_CHG_happened:
- RET
-
- ;---------------------------------------------------------------------------;
- ; Allocate Memory ;
- ; ;
- ; ENTRY: BX contains starting offset of buffer area. ;
- ; (Note, this area contains initialization code and data which will ;
- ; be overlaid once we start reading into the buffers.) ;
- ; ;
- ; Release memory used by initialization routine and allocate 2000h pages ;
- ; (128k) memory for use as file buffers. If this fails get as much as ;
- ; possible. Divide memory allocated into 2 buffers - 1 for each file. ;
- ; Leaves ES as segment pointer to first file segment (OLD file) ;
- ;---------------------------------------------------------------------------;
- Allocate_Memory:
-
- ; Now determine how many paragraphs (16 bytes) program plus stack needs:
- ADD BX,15 ;Round up to nearest PARA
- MOV CL,4
- SHR BX,CL ;Divide bytes of storage by 16
-
- MOV AH,4Ah ;Dealloc all but needed (BX) paras
- INT 21h
-
- MOV BX,2000h ;Request 128K for input buffers
- MOV AH,48h ;DOS request mem function
- INT 21h
- JNC Mem_OK ;If memory is available
-
- MOV DX,offset Mem_loss_Msg ;Display msg informing lack of mem
- MOV AH,09H ;DOS display string function
- INT 21H
- ; Attempt to allocate what little memory is available and use that
- MOV AX,BX ;Paragraphs of memory free
- SHR AX,1 ;Divide by two: Space for each file
- MOV File_Size_PARAs,AX ;Each file's size in pargraphs
- MOV CL,4 ;Prepare to shift left 4 bits (*16)
- SHL AX,CL ;Mult by 16 = number of bytes per file
- MOV File_Size_Bytes,AX ;Space for each file in bytes
- MOV AH,48h ;DOS alloc mem func:BX = para avail
- INT 21h ;Get what memory we can get
- JNC Mem_OK ;If Alloc worked 2nd time around
-
- ; Fatal memory error:
- MOV DX,offset Mem_ERR_Msg ;Else: give message and give up
- MOV AH,09H ;DOS display string function
- INT 21H
- CALL Page_Wait ;Beep and force user to hit a key
- MOV AX,4C14h ; terminate with 20 error level
- INT 21h
-
- Mem_OK:
- MOV ES,AX ;ES points to start of allcoated block
- RET
-
- ;---------------------------------------------------------------------------;
- ; Read and Validate Files ;
- ; 1) Read both files into file buffers. ;
- ; 2) Validate that files are of correct type ;
- ; 3) Determine offset of first record and total number of records ;
- ; check if a total line exists on each file ;
- ; 4) Calc offset of beginning of last record for the NEW file ;
- ; ;
- ; On Entry ES must point to OLD_FILE segment ;
- ; ;
- ; On Exit ES will point to NEW_FILE segment and DS will DATA SEG (=CS) ;
- ;---------------------------------------------------------------------------;
- Read_and_Validate_Files:
-
- ; Read "OLD" file (first of two files specified)
- MOV BX,OLD_File_Handle ;Get handle for the first file
- PUSH OLD_Filename_end ;Save end of Filename on stack
- PUSH OLD_Filename_Loc ;Save start of filename for error msgs
- MOV AX,ES ;ES points to beginning of file SEG
- MOV DS,AX ;DS=ES = seg reg for OLD file
- CALL Read_File ;Do actual read of file + error chking
- CALL Validate_File ;Check file and locate 1st + last recs
- ;DS=CS after return from Validate_File
- ADD SP,4 ;Remove filename end + loc from stack
- MOV OLD_File_Start,BP ;Save 1st record address
- MOV OLD_Rec_count,CX ;Save number of records
- MOV OLD_Tot_Loc,BX ;Save location of totals (if existing)
-
- ; Read "NEW" file (2nd of two files specified)
- MOV BX,NEW_File_Handle ;Get handle for the first file
- PUSH NEW_Filename_end ;Save end of Filename on stack
- PUSH NEW_Filename_Loc ;Save start of filename for error msgs
- MOV AX,ES ;DS points to beginning of file SEG
- ADD AX,File_Size_PARAs ;point DS to NEW file segment
- MOV DS,AX ;DS is segment register for NEW file
- CALL Read_File ;Do actual read of file + error chking
- MOV AX,DS ;Validate_file needs
- MOV ES,AX ; ES for file seg
- CALL Validate_File ;Check file and locate 1st + last recs
- ;DS = CS after return from Validate_Fi
- ADD SP,4 ;Remove filename end + loc from stack
- MOV NEW_File_Start,BP ;Save 1st record address
- MOV NEW_Rec_count,CX ;Save number of records
- MOV NEW_Tot_Loc,BX ;Save location of totals (if existing)
- MOV New_End_Of_File,DI ;Save start of last rec on NEW file
- RET
-
- ;---------------------------------------------------------------------------;
- ; READ FILE - will read the file specified by the following parameters ;
- ; BX contains file handle, Stack contains end and start of filespec ;
- ; DS contains segment to read file into (file buffer is at offset zero) ;
- ; On EXIT: File will be read into file buffer pointed to by DS and closed. ;
- ; CX will contain number of characters read in from the file. ;
- ;---------------------------------------------------------------------------;
- Read_file:
- CMP CS:Missing_Old_File,'Y' ;Are we attempting to read from a
- ; Non existant OLD file?
- JNE Normal_File_Read ; If not, do normal file read
- XOR CX,CX ; Else, indicate file is empty
- MOV CS:Missing_Old_File,0 ; Turn off missing file switch
- RET ; All done for missing file
-
- Normal_File_Read:
- XOR DX,DX ;DX=0 = start of file buffer
- MOV SI,DX ;SI is for BUFFER reads later
- MOV CX,CS:File_Size_Bytes ;MAX # of bytes to read (64k-1)
- MOV AH,3FH ;Setup to read from file
- INT 21H ;Call DOS to do actual read
- JC Read_error ;Quit on any error or EOF
- OR AX,AX ;Check if ax=0 no records read
- JZ File_size_error ;If no records, close this file..
- CMP AX,CX ;See if max number of chars read
- JE File_size_error ;If we have compltly filled buffer
- MOV CX,AX ;Save total # of chars read
- MOV AH,3Eh ;Prepare to close the file
- INT 21H ;Let DOS close file
- RET
-
- ;---------------------------------------------------------------------------;
- ; READ ERROR - report read error message - call with: ;
- ; Stack contains the END and (LOC) start of the filespec for error msgs ;
- ;---------------------------------------------------------------------------;
- Read_error: ;Report error reading a file
- MOV AX,CS
- MOV DS,AX ;Restore datasegment addresability
- MOV DX, offset Read_Err_MSG ;indicate read failed
- MOV CX,15 ;Length of msg is 15 chars
- MOV SI,4C14h ;DOS term with error level 20
- JMP Report_file_errors
- SUBTTL General Purpose subroutines
-
- ;---------------------------------------------------------------------------;
- ; FILE SIZE ERROR - Report on an error - with file have too many records ;
- ; Stack contains the END and (LOC) start of the filespec for error msgs ;
- ;---------------------------------------------------------------------------;
- File_size_error: ;File has more than 64k records
- MOV AX,CS
- MOV DS,AX ;Restore datasegment addresability
- MOV DX, offset size_Err_MSG ;indicate record has an invalid size
- MOV CX,20 ;Length of msg is 20 chars
- MOV SI,4C10h ;DOS term with error level 16 (dec)
- JMP Report_file_errors
-
- ;---------------------------------------------------------------------------;
- ; FILE TYPE ERROR - Report on an error - with file being invalid type ;
- ; Stack contains the END and (LOC) start of the filespec for error msgs ;
- ;---------------------------------------------------------------------------;
- File_type_error: ;Report this is wrong type of file
- ADD SP,2 ;Remove CX from the stack; this way:
- ; filespec_end + loc are stack top
- MOV AX,CS
- MOV DS,AX ;Restore datasegment addresability
- MOV DX, offset type_Err_MSG ;indicate invalid record type
- MOV CX,20 ;Length of msg is 20 chars
- MOV SI,4C10h ;DOS term with error level 16 (dec)
- JMP Report_file_errors
-
- ;---------------------------------------------------------------------------;
- ; VALIDATE FILE - will examine file and locate 1st and last records in file ;
- ; On Entry: ;
- ; Stack contains the END and (LOC) start of the filespec for error msgs ;
- ; ES contains File buffer SEGMENT ;
- ; CX contains number of characters read in the buffer ;
- ; On EXIT: (if file is of valid type:) ;
- ; BP will be beginning of 1st record on file (offset) ;
- ; CX will be count of number of records on file ;
- ; BX will be = offset of CHKSUM field on final total=====> record ;
- ; DI will be offset of last char in last 51 char record on the file (EOF) ;
- ; DS will be code/data segment register rather than File segment ;
- ;---------------------------------------------------------------------------;
- Validate_File:
- MOV AX,CS ;XFER OLD data SEG(=CS)
- MOV DS,AX ; back into DS
-
- CMP CX,0 ;Is this a pretend file (empty) ?
- JNE Its_a_Real_File ;If not, do actual validation
- XOR DI,DI ;Set EOF offset to empty
- XOR BX,BX ;Indicate for totals record
- RET ;All done
-
- Its_a_Real_File:
- PUSH CX ;Save copy of offset of EOF
- XOR DI,DI ;Start at beginning of buffer
- MOV AL,254 ;Search for teltale of CHKfile (box)
- REPNE SCASB ;Search until match
- JNZ File_type_error ;If no match found
- MOV AL,'W' ;Search for teltale of CHKfile
- REPNE SCASB ;Search until match
- MOV BX,CX ;Save copy of CX
- MOV CX,4 ;Compare 8 characters
- MOV SI,offset Check_String
- REPE CMPSW ;File should match exactly
- JNZ File_type_error ;If mismatch found
- MOV CX,BX ;Restore CX to
- SUB CX,8 ; reflect chars left
- MOV AL,'-' ;Search for a
- REPNE SCASB ; minus sign
- MOV AL,LF ;Search for a
- REPNE SCASB ; linefeed character
- JNZ File_type_error ;If no match found
- MOV BP,DI ;Save this location (1st record)
- ; BP now points to the first 51 char display record on this file
-
- ; Now check for existance of TOTALS==> record and locate beginning of last rec
- XOR DX,DX ;Zero upper part of dividend (DX:AX)
- MOV AX,CX ;# of chars after start of 1st record
- MOV BX,DSP_Rec_Len ;Prepare to divide by record len (51)
- DIV BX ;Divide chars from 1st rec by rec len
- ; After divide: # of 51 char recs is in AX; # of chars in last rec in DX
- MOV CX,AX ;# of 51 character records on file
- XOR BX,BX ; Initially indicate no totals line
- OR DX,DX ;Check if, no total line (no last rec)
- JZ No_totals_line ;Skip totals line checking
- CMP DX,24 ;Totals line should be 24 characters
- JE Tot_line_exists ; If length is correct for tot line
- JMP File_type_error ; If length of final line is wrong
- Tot_line_exists:
- POP DI ;Get address of EOF (PUSHed CX)
- SUB DI,10 ;first char in CHKSUM field of TOT rec
- MOV BX,DI ; Return this location to caller
- SUB DI,13 ;Point DI past end of last 51 chr rec
- RET
- No_totals_line:
- POP DI ;Get address of EOF (PUSHed CX)
- ;DI= offset past last 51 char record
- RET ;End of VALIDATE_FILE routine
-
- PAGE
- ;******************************************************************************;
- ;** General purpose subroutines follow **;
- ;******************************************************************************;
-
- ;---------------------------------------------------------------------------;
- ; Report File errors - General purpose error presenter used by ;
- ; the specific error subroutines such as file_size_error + read_error. ;
- ; Stack contains the END and (LOC) start of the filespec which had error. ;
- ; DX = offset to error msg, CX has length of message ;
- ; SI = contains DOS terminate code with specific ERRORLEVEL in lower part ;
- ;---------------------------------------------------------------------------;
- Report_File_errors: ;General purpose error display routine
- ;DOS term func + errlvl must be in SI
- MOV AX,CS ;Point ES back
- MOV ES,AX ; to normal data segment
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;Handle for std output device
- INT 21h ;Write beginning of error message
- ADD SP,2 ;Remove return address from stack
- POP BP ;Get starting offset of filespec
- POP DI ;1 character after end of filespec
- MOV AX,CRLF ;Terminate file name with CR,LF
- STOSW
- SUB DI,BP ;Calc filename length + 2 for CRLF
- MOV CX,DI
- MOV DX,BP ;Start of file name to output
- MOV AH,40h ;DOS Write func
- INT 21H
- CALL Page_Wait ;Beep and force user to hit a key
- MOV AX,SI ;SI contains 4Ch with error lvl
- INT 21h
-
-
- ;---------------------------------------------------------------------------;
- ; Page_control: (and *PAGE WAIT* alternate entry point) ;
- ; Called only if user specified /P option (BH will be not = to FFh). ;
- ; Page control will increment the line counter and pause every 24 lines ;
- ; giving the user a prompt to -Hit any KEY - ;
- ;ENTRY: ;
- ; AL contains number of lines waiting to be displayed. ;
- ; BH contains line count for this page already. ;
- ; DS points to normal data segment (=CS) ;
- ;EXIT: ;
- ; BH contains updated line count which is reset if page wait happened ;
- ; ;
- ;PAGE WAIT - simply puts out -HIT ANY KEY- message and waits for user ;
- ; to hit any key. ;
- ;---------------------------------------------------------------------------;
- Page_control:
- ADD BH,AL ;Increment line counter
- CMP BH,24 ;Are we over one page of output?
- JA Page_Wait ; If over 1 page then do page wait
- RET
- Page_Wait: ;Alternate entry point (here)
- MOV BH,AL ;Reset the line counter
-
- PUSH BP ;Save all corrupted registers
- PUSH BX
- PUSH CX
- PUSH DI
- PUSH DX
- PUSH SI
- ; Produce a beep to alert the user: (use BIOS TTY func to write an ASCII BELL)
- MOV AX,0E07H ;BIOS func (0Eh) to write (07H) beep
- XOR BH,BH ;Select page zero for output
- INT 10H ;BIOS video function (0Eh=write char)
-
- ;Find out what attribute is being used for display
- MOV AH,08h ;read attrib + char function
- INT 10h ;Call BIOS
- PUSH AX ;Save AH=attribute byte
-
- ;Find out what line the cursor is on
- MOV AH,03h ;Read cursor position function
- INT 10h ;BIOS video services
- PUSH DX ;DH contains row (line #) Save it!
-
- ; Position cursor to current line + column 28: (TO BIOS row 27)
- MOV AH,02 ;BIOS int 10h set cursor position func
- XOR BH,BH ;Set page to zero
- ;DH contains current row
- MOV DL,1Bh ;Set cusor current row and col 27
- INT 10h ;BIOS video services
-
- ; Put -Hit any key- message out with inverse video attribute type on
- ; XOR BH,BH ;Set page to zero (BH is still 0)
- MOV BL,0F0h ;Inverse video attribute
- MOV CX,1 ;Character count
- MOV SI,offset Hit_Key_Msg ;The hit-any-key message
- Display_next_video_char:
- MOV AH,09H ;BIOS int 10h write attrib + char func
- LODSB ;Get next character for output
- PUSH SI ;Save SI (int 10h may corrupt it)
- INT 10h ;Put character and attribute out
- INC DX ;Advance cursor position
- MOV AH,02 ;Adv cursor function
- INT 10h ; advance the cursor (BIOS)
- POP SI ;Restore saved SI
- CMP SI,offset Hit_key_Msg_end ;are we at end of message?
- JB Display_next_video_char ; If not get next char for display
- ; Else, wait for key press by user
- ; Wait for user to hit any key
- XOR AX,AX
- INT 16h ;Wait for user to hit a key
-
- ; Erase HIT ANY KEY message
- POP DX ;DH=current line number
- POP BX ;BH=user's screen attribute
- MOV AH,06h ;INIT window function
- XOR AL,AL ;Zero AL to clear window
- MOV CH,DH ;Current row (y coor upr lft)
- MOV CL,00 ;Start in first char position
- MOV DL,79 ;Last char pos - blank entire line
- INT 10h ;Blank out line
-
- ; Position cursor to start of blanked line
- MOV AH,02 ;BIOS int 10h set cursor position func
- XOR DL,DL ;DH=cur line, DL=0: first char pos
- XOR BX,BX ;Use video page zero
- INT 10h ;BIOS video services
-
- POP SI ;Restore all corrupted registers
- POP DX
- POP DI
- POP CX
- POP BX
- POP BP
- RET ;Return to caller
-
- ;---------------------------------------------------------------------------;
- ; Display HEADER MSG - displays column headers the first time CFCOMP decides;
- ; it needs to display a changed record. ;
- ;ENTRY: ;
- ; DS points to normal data segment (=CS) ;
- ;EXIT: ;
- ; DX,CX,AX are corrupted. ;
- ;---------------------------------------------------------------------------;
- Display_Header_MSG:
- PUSH BX ;Save BX (error level in BL)
- MOV BX,1 ;Write to STD output device (=1)
- MOV DX, offset Header_MSG ;beginning loc of directory string
- MOV CX,179 ;179 chars in header message
- MOV AH,40h ;DOS write
- INT 21h
- POP BX
- RET
- SUBTTL Definition of Data structures
- PAGE
- ;******************************************************************************;
- ;** Definition of Data areas follow **;
- ;******************************************************************************;
- File_Size_PARAs DW 1000h ;Size of each REP file in paragraphs
- File_Size_Bytes DW 0FFFFh ;Size of each REP file in bytes
- OLD_Filename_Loc DW 0 ;offset of filespec for OLD file
- OLD_Filename_end DW 0 ;end of filespec for OLD file
- OLD_File_Handle DW 0 ;File handle for OLD file
- OLD_File_Start DW 0 ;Offset of 1st record on file
- OLD_Rec_count DW 0 ;Number of 51 character recs on file
- OLD_Tot_Loc DW 0 ;Offset of CHKSUM on totals records
- NEW_Filename_Loc DW 0 ;offset of filespec for NEW file
- NEW_Filename_end DW 0 ;end of filespec for NEW file
- NEW_File_Handle DW 0 ;File handle for NEW file
- NEW_File_Start DW 0 ;Offset of 1st record on file
- NEW_Rec_count DW 0 ;Number of 51 character recs on file
- NEW_Tot_Loc DW 0 ;Offset of CHKSUM on totals records
- New_End_Of_File DW 0 ;Offset beginning of last record
- Changes_Only DB 0 ;="Y" if user wants only changes
- Missing_Old_File DB 0 ;="Y" if OLD report file not found
- Page_Mode DB 0FFh ;=00h means stop after each page
- Check_String DB 'olfgang '
- Mem_Err_Msg DB 'Error in MEM ALLOC'
- CRLF_Msg DB CR,LF,'$'
- Mem_loss_Msg DB 'Memory lack limits file size'
- DB CR,LF,'$'
- Read_Err_MSG DB 'Error reading: '
- Type_Err_MSG DB 'Wrong type of file: '
- Size_Err_MSG DB 'File size invalid: '
- CHGD_MSG_1 DB 'Chgd: OLD:'
- CHGD_MSG_2 DB ' NEW:'
- Deleted_MSG DB 'Deleted-->'
- Added_MSG DB 'NEW Fil-->'
- Tot_match_MSG DB 'File totals match',CR,LF
- Tot_nomatch_MSG DB 'File totals unequal',CR,LF
- Hit_Key_MSG DB '-Hit any key-'
- Hit_Key_MSG_end EQU $
- Header_MSG DB ' File Name + Check Check File Update Update'
- DB CR,LF
- DB ' Extension: Val1: Val2: Size: Date: Time:'
- DB CR,LF
- DB ' ---------- ---- ---- ----- ------ ------'
- DB CR,LF
-
- SUBTTL INIT data + code (also input BUFFERs + stack)
- PAGE
- ;******************************************************************************;
- ;** Definition of file buffer Data areas and code follow: **;
- ;** All the following storage will be overlaid when records are read in **;
- ;******************************************************************************;
-
- EVEN
- Buffer_area label byte ;All storage + code following is in
- ; the input file buffer.
-
- ; ----------------------------------------------------------------------------;
- ; Initialization code - parse parms + put out msgs and open both files ;
- ; ----------------------------------------------------------------------------;
- Parse_Parms_Open_Files: ;Parse input parameters + displ header
- MOV SI,80H ;Parameter area in PSP
- MOV CL,[SI] ;Get # of chars in input parm
- XOR CH,CH ;Clear upper byte of char count
- INC SI ;point to first char
-
- ;---------------------------------------------------------------------------;
- ; Conventions for command line parsing: ;
- ; SI points to next char to be checked in the parm field at DS:80 ;
- ; CX is count of characters left to be scanned ;
- ; BP points to start of current processed filespec. ;
- ;---------------------------------------------------------------------------;
-
- Call Parse_Filespec ;exract 1st filespec from parm area
- MOV OLD_Filename_Loc,BP ;Store location of file name
- MOV OLD_Filename_end,DI ;Store char loc after end of filespec
- ; Adjust CX to reflect actual characters left to be scanned
- JCXZ Skip_decrement ;Don't decrement CX if already = 0
- DEC CX
- Skip_decrement:
- Call Parse_Filespec ;exract 2nd filespec from parm area
- MOV NEW_Filename_Loc,BP ;Store location of 2nd file name
- MOV NEW_Filename_end,DI ;Store char loc after end of filespec
-
- CALL Parse_parms ;Process any "/" parms
- CALL Put_Out_Initial_MSGs ;Display header and start messages
-
- MOV DX,OLD_Filename_Loc ;Open the first ("OLD") file
- MOV AX,3D00H ;DOS open file (handle) for read cmnd
- INT 21H ;invoke DOS
- JNC Continue_Open ;If no errors continue processing
-
- ; If open fails for OLD file, treat it as if file were empty - keep going
- MOV Missing_Old_File,'Y' ;Else, Indicate old file was gone
- MOV DI,OLD_Filename_end
- CALL File_Open_Error ;Put out file open error message
- MOV DX, OFFSET Empty_OLD_MSG ;Tell user we will pretend file is MT
- MOV AH,09H ;DOS display string function
- INT 21H
-
- Continue_Open:
- MOV OLD_File_handle,AX ;Save DOS file handle
- MOV DX,NEW_Filename_Loc ;Open the 2nd (AKA "NEW") file
- MOV AX,3D00H ;DOS open file (handle) for read cmnd
- INT 21H ;invoke DOS
- JNC Open_done ;If no errors continue processing
- MOV DI,NEW_Filename_end
- CALL File_Open_Error ;Put out file open error message
- CALL Page_Wait ;Force user to acknoledge error
- MOV AX,4C14h ; terminate with 20 error level
- INT 21h
-
- Open_done:
- MOV NEW_File_handle,AX ;Save DOS file handle
-
- RET
-
- ;---------------------------------------------------------------------------;
- ; Parse filespec: ;
- ; Input: ;
- ; SI points to next char to be checked in the parm field at DS:80 ;
- ; CX is count of characters left to be scanned ;
- ; ;
- ; Returns: ;
- ; BP points to start of filespec ;
- ; DI points to byte after last char in filespec ;
- ; Filespec is zero terminated in the parameter area ;
- ;---------------------------------------------------------------------------;
- Parse_Filespec: ;Extract and zero terminate filename
- OR CL,CL ;Check for 0 chars (NO INPUT)
- JZ ERR_EXIT ;If no parms put out error msg
- DEL_SPACES:
- LODSB ;Get byte at DS:SI and inc SI
- CMP AL,' ' ;Is it a space?
- JNE Set_File_name ;If not, we should have a file name..
- LOOP DEL_SPACES ;Cont checking until last char
- ERR_EXIT:
- MOV DX, OFFSET No_File_Msg ;Prepare error message
- MOV AH,09H ;DOS display string function
- INT 21H
- JMP SHORT Give_Syntax_and_Quit ;Give correct syntax and terminate
-
- ;--------------------------------------------;
- ; Parse file spec and zero byte terminate it ;
- ;--------------------------------------------;
- Set_File_Name:
- DEC SI ;point back to 1ST letter of filespec
- MOV BP,SI ;Save a copy of filespec start
-
- Scan_To_File_Spec_End:
- ; start scanning the file specification and transfer into output field
- LODSB ;Get next char of file spec
- CMP AL,' ' ;check valid separator character
- JBE file_spec_end_found
- CMP AL,'/' ;check for valid separator
- JE file_spec_end_found
- CMP AL,',' ;check for valid separator
- JE file_spec_end_found
- LOOP Scan_To_File_Spec_End
- INC SI ;Adjust SI if no separator char found
-
- File_Spec_End_Found:
- ; SI is pointing 2 characters past end of filespec at this time
- MOV DI,SI
- DEC DI ;DI points to 1st char after filespec
- MOV BYTE PTR [DI],00 ;zero terminate the filespec: ASCIIZ
- RET
-
- ;----------------------------------------------------------------;
- ; Parse Parms: parse /P and /C parameters ;
- ; Input: SI must point to next character to process ;
- ; CX contains # of chars left in paramter area ;
- ;----------------------------------------------------------------;
- Parse_Parms:
- Check_parm_chars_left: ;Check if enough chars left for a parm
- CMP CX,01 ;Check if we out of chars to scan
- JA Parm_Scan ; If Not, continue checking
- RET ; If no more chars, we are done
- Parm_Scan: ;Check for presence of a /_ parm
- CMP AL,'/' ;check for "/" parm character
- JE Parm_found
- CMP AL,' ' ;check for blanks
- JNE Unrecog_parm ;If other than blank its illegal...
- LODSB ;Keep checking next character
- LOOP Parm_Scan
- RET ;finished (parsing parms)
-
- Parm_Found: ;Check if parm is valid
- DEC CX ;Adjust chars remaining counter
- JCXZ Unrecog_parm ;IF no chars left then parm is invalid
- LODSB ;Get next char
- DEC CX ;Adjust chars remaining counter
- AND AL,5Fh ;Capitalize char
- CMP AL,'P' ;Is it the "Totals wanted" parm?
- JE P_parm ;T parameter detected
- CMP AL,'C' ;Is it alternate Check Sum parm?
- JE C_parm ;C parameter detected..
- CMP AL,'O' ;Is it "Only chk field compare parm"?
- JE O_parm ;C parameter detected..
-
- Unrecog_parm: ; an illegal paramter:
- MOV DX, offset Bad_Parm_MSG ;indicate illegal parm was found
- MOV AH,09H ;DOS display string function
- INT 21H
- Give_Syntax_and_Quit:
- CALL Page_Wait ;Force user to acknoledge error
- MOV DX, offset Syntax_MSG ;Give user the correct syntax
- MOV AH,09H ;DOS display string function
- INT 21H
- MOV AX,4C80h ; terminate with 128 error level
- INT 21h
-
- P_parm:
- MOV Page_Mode,03h ;Indicate user wants page mode
- ;Std out already has 3 line header
- ;Originally =FFh to turn page mode off
- LODSB ;Keep checking next character
- JMP SHORT Check_Parm_chars_left ;Check for additional parms
-
- C_parm:
- MOV Changes_Only,'Y' ;User wants only changes (no add/del)
- LODSB ;Keep checking next character
- JMP SHORT Check_Parm_chars_left ;Check for additional parms
-
- O_parm: ;"Only" check file size + check fields
- ; IF the /O option is selected, we will patch the length field of two
- ; MOV CX,19 instructions in the COMPARE_FILES subroutine labeled PATCH1 and
- ; PATCH2. The modified routine will then only compare 9 words (the CHECK fields
- ; + file size ) rather than the entire remaining record.
- MOV BYTE PTR[PATCH1+1],09 ;Patch length field of MOV CX, instr
- MOV BYTE PTR[PATCH2+1],09 ;Patch length field of MOV CX, instr
- LODSB ;Keep checking next character
- JMP SHORT Check_Parm_chars_left ;Check for additional parms
-
-
- ;----------------------------------------------------------------;
- ; File Open Error - put out file open error message + terminate;
- ; Input: DX must point to start of filespec ;
- ; DI must point to end of filespec ;
- ;----------------------------------------------------------------;
- File_Open_Error:
- PUSH DX ;Save filename
- MOV DX, offset Open_Err_MSG ;indicate open failed
- MOV CX,23 ;Length of msg is 23 chars
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;Handle for std output device
- INT 21h ;Write beginning of open error message
- POP DX ;restore name of file loc to DX
- SUB DI,DX ;Calc length of filename + CR,LF
- MOV CX,DI
- MOV AH,40h ;DOS Write func
- INT 21h
- MOV DX,OFFSET CRLF_Msg ;Put out Carriage return + line-feed
- MOV AH,09h
- INT 21h
- RET
-
- Put_Out_Initial_MSGs: ;Display header and start messages
- MOV DX, offset Start_MSG ;beginning of start message
- MOV CX,SM_End-Start_MSG ;# of chars in start message
- MOV AH,40h ;DOS Write func
- MOV BX,1 ;Handle for std output device
- INT 21h ;Write Start message
-
- MOV SI,offset Start_Dir ;Place to store current directory
- XOR DL,DL ;Zero DL in order to use default drive
- MOV AH,47h ;Get current directory (path) func
- INT 21h
- CLD ;Scan in forward direction
- MOV DI,offset Start_Dir ;Scan dir strng to determine length
- XOR AX,AX ;Scan for zero termination of dir
- MOV CX,64 ;Scan up to 64 chars of directory
- REPNE SCASB ;Find 1st zero byte
- MOV AX,CRLF
- STOSW ;Terminate dir string with CR LF
- MOV DX, offset Start_Dir ;beginning loc of directory string
- SUB DI,SI ;Calc length of directory string
- MOV CX,DI ;Length reg for DOS write function
- MOV AH,40h ;DOS Write func
- INT 21h ;Write Dir string to finish start msg
- RET
-
- ; --------------------------------------------------;
- ; Initialization DATA STORAGE ;
- ; --------------------------------------------------;
- Start_MSG DB CR,LF,"CFCOMP 1.0 ",BOX," PCDATA TOOLKIT (c) 1990"
- DB " Ziff Communications Co.",CR,LF
- DB "PC Magazine ",BOX," Wolfgang Stiller - In directory: \"
- SM_End LABEL BYTE ;End of the Start message
- Start_Dir DB 66 DUP (0)
- Open_ERR_Msg DB 'CFCOMP unable to open: '
- Empty_Old_Msg DB 'OLDfile assumed empty - execution continues.',CR,LF,'$'
- Bad_Parm_MSG DB 'Unrecognized parameter detected.',CR,LF,LF,'$'
- NO_FILE_Msg DB 'You must specify at least OLD and NEW file names to compare.'
- DB CR,LF,'$'
- Syntax_Msg DB "CFCOMP 1.0 ",BOX," PCDATA TOOLKIT Copyright (c) 1990"
- DB " Ziff Communications Co.",CR,LF
- DB "PC Magazine ",BOX," Wolfgang Stiller",CR,LF
- DB CR,LF,'CFCOMP does a high speed compare of the compressed'
- DB ' report files produced',CR,LF
- DB 'by CHKfile. It displays all changes between the OLD and '
- DB 'NEW report files.',CR,LF,LF
- DB 'Syntax is: CFCOMP OLDfile NEWfile [/C] [/O] [/P]'
- DB CR,LF,LF
- DB ' OLDfile and NEWfile are files created by CHKFILE.COM.'
- DB CR,LF,LF
- DB ' "/C" Display only changed files not additions or '
- DB 'deletions.',CR,LF
- DB ' "/O" Only use check fields and file size in comparing '
- DB 'files.'
- DB CR,LF
- DB ' DOS time and Date stamps are not used for compare.'
- DB CR,LF
- DB ' "/P" Pause between pages if changes found.'
- DB CR,LF,'$'
- CSEG EndS
- END CFCOMP