1 title
File Compare Routine for MSDOS
2.0
3 ;-----------------------------------------------------------------------;
6 ; V1.0 Rev. 0 10/27/82 M.A.Ulloa ;
8 ; Rev. 1 10/28/82 M.A.Ulloa ;
9 ; Changed switch names and added binary compare using the ;
12 ; Rev. 1 11/4/82 A.R. Reynolds ;
13 ; Messages in separate module ;
14 ; Also added header for MSVER ;
16 ; Rev. 2 11/29/82 M.A. Ulloa ;
17 ; Corrected sysntex problem with references to [base...] ;
19 ; Rev. 3 01/03/83 M.A. Ulloa ;
20 ; Stack is right size now. ;
22 ;-----------------------------------------------------------------------;
28 buf_size equ
4096 ;buffer size
31 ;-----------------------------------------------------------------------;
34 ; FC [-# -b -w -c] <file1> <file2> ;
38 ; -# were # is a number from 1 to 9, how many lines have to ;
39 ; before the end of an area of difference ends. ;
41 ; -b will force a binary comparation of both files. ;
43 ; -w will cause all spaces and tabs to be compressed to a single ;
44 ; space before comparing. All leading and trailing spaces and/or tabs ;
45 ; in a line are ignored. ;
47 ; -c will cause FC to ignore the case of the letters. ;
49 ; Algorithm for text compare: (The one for binary comp. is trivial) ;
51 ; The files are read into two separate buffers and the ;
52 ; comparation starts. If two lines are found to be different in the ;
53 ; two buffers, say line i of buffer A and line j of buffer B differ. ;
54 ; The program will try to match line i with line j+1, then with line ;
55 ; j+2 and so on, if the end of buffer is reached the program will ;
56 ; recompact the buffer and try to read more lines into the buffer, if ;
57 ; no more lines can be read because either the buffer is full, or the ;
58 ; end of file was reached, then it will revert and try to match line ;
59 ; j of buffer B to line i+1, i+2 and so on of buffer A. If an end of ;
60 ; buffer is found, it tries to refill it as before. If no matches are ;
61 ; found, then it will try to match line i+1 of buffer A to line j+1, ;
62 ; j+2, j+3, .... of buffer B, if still no matches are found, it reverts ;
63 ; again and tries to match line j+1 of buffer B with lines i+2, i+3,... ;
64 ; of buffer A. And so on till a match is found. ;
66 ; Once a match is found it continues chcking pairs of lines till ;
67 ; the specified number are matched (option #, 3 by default), and then ;
68 ; it prints the differing area in both files, each followed by the ;
69 ; first line matched. ;
71 ; If no match is found (the difference is bigger than the buffer) ;
72 ; a "files different" message is printed. ;
74 ; If one of the files finishes before another the remaining ;
75 ; portion of the file (plus any ongoing difference) is printed out. ;
77 ;-----------------------------------------------------------------------;
106 b1 db "------ buffer 1",0dh,0ah,"$"
107 b2 db "------ buffer 2",0dh,0ah,"$"
110 cmp bx,offset dg
:buf1
112 mov dx,offset
code:b2
114 a1: mov dx,offset
code:b1
135 subttl General Definitions
142 ;-----------------------------------------------------------------------;
143 ; Offsets to buffer structure
144 ; For text comparations:
146 fname equ
0 ;file name ptr
147 fname_len equ
2 ;file name length
149 curr equ
6 ;current line ptr
150 lst_curr equ
8 ;last current line ptr
151 fst_sinc equ
10 ;first line towards a sinc ptr
152 fst_nosinc equ
12 ;first line out of sinc ptr
153 dat_end equ
14 ;ptr to last char of the buffer
154 buf_end equ
16 ;pointer to the end of the buffer
155 buf equ
18 ;pointer to the buffer
157 ; For binary comparations:
159 by_read equ
6 ;bytes read into buffer
161 ;-----------------------------------------------------------------------;
167 const
segment public word
173 dg group
code,const
,data
176 subttl Constants Area
179 const
segment public word
181 make db "MAUlloa/Microsoft/V10"
184 ;----- CAREFULL WITH PRESERVING THE ORDER OF THE TABLE -----
185 opt_tbl equ
$ ;option table
191 ;-----------------------------------------------------------
193 ib_first1 db FALSE
;flags used when comparing lines
194 ib_first2 db FALSE
; while in ignore white mode.
196 m_num dw 3 ;lines that have to match before
199 mtch_cntr dw 0 ;matches towards a sinc
201 mode db FALSE
;If false then trying to match a line
202 ; from buf1 to lines in buf2. If true
205 sinc db TRUE
;Sinc flag, start IN SINC
207 bend db 0 ;binary end of file flag, 0= none yet,
208 ; 1= file 1 ended, 2= file 2 ended
210 base dd 0 ;base address of files for binary
213 bhead_flg db false
;true if heading for binary comp.
214 ; has been printed already.
216 ;-----------------------------------------------------------
217 bp_buf equ
$ ;binary compare difference template
219 bp_buf1 db 8 dup(' ') ;file address
221 bp_buf2 db 2 dup(' ') ;byte of file 1
223 bp_buf3 db 2 dup(' ') ;byte of file 1
226 bp_buf_len equ
$ - bp_buf
;length of template
227 ;-----------------------------------------------------------
229 EXTRN vers_err
:byte,opt_err
:byte,opt_e
:byte,crlf
:byte,opt_err_len
:byte
231 EXTRN found_err_pre
:byte,found_err_pre_len
:byte
232 EXTRN found_err_post
:byte,found_err_post_len
:byte
233 EXTRN read_err_pre
:byte,read_err_pre_len
:byte
234 EXTRN read_err_post
:byte,read_err_post_len
:byte
235 EXTRN file_err
:byte,file_err_len
:byte
236 EXTRN bf1ne
:byte,bf1ne_len
:byte,bf2ne
:byte,bf2ne_len
:byte,bhead
:byte
237 EXTRN int_err
:byte,int_err_len
:byte,dif_err
:byte,dif_err_len
:byte
238 EXTRN args_err
:byte,args_err_len
:byte,fname_sep
:byte,fname_sep_len
:byte
239 EXTRN diff_sep
:byte,diff_sep_len
:byte
250 com_buf db 128 dup(?
) ;command line buffer
252 ;----- Buffer structures
256 ; two extra for guard in case of need to insert a CR,LF pair
257 b1 db buf_size
dup(?
)
259 b2 db buf_size
dup(?
)
270 assume
cs:dg
,ds:nothing
,es:nothing
,ss:stack
274 ;-----------------------------------------------------------------------;
275 ; Check version number
277 HEADER
DB "Vers 1.00"
280 ;Code to print header
284 ; MOV DX,OFFSET DG:HEADER
285 ; mov ah,std_con_string_output
293 mov dx,offset dg
:vers_err
294 mov ah,std_con_string_output
296 push es ;bad vers, exit a la 1.x
311 ;-----------------------------------------------------------------------;
314 mov si,80h
;command line address
316 lodsb ;get char count
319 inc cx ;include the CR
320 mov di,offset dg
:com_buf
331 ;-----------------------------------------------------------------------;
332 ; Initialize buffer structures
334 mov bx,offset dg
:buf1
335 mov word ptr [bx].buf
,offset dg
:b1
336 mov word ptr [bx].buf_end
,offset dg
:end_b1
337 mov bx,offset dg
:buf2
338 mov word ptr [bx].buf
,offset dg
:b2
339 mov word ptr [bx].buf_end
,offset dg
:end_b2
342 ;-----------------------------------------------------------------------;
347 int 21h
;get switch character
348 mov si,offset dg
:com_buf
352 jc bad_args
;arguments missing
353 cmp al,dl ;switch character?
354 jne get_file
;no, process file names
357 call make_caps
;capitalize option
358 mov bx,offset dg
:opt_tbl
368 cmp al,'1' ;a number option?
372 and al,0fh ;a number option, convert to binary
373 xor ah,ah ;zero high nibble
377 bad_opt: ;a bad option:
378 push dx ; save switch character
379 mov [opt_e
],al ; option in error
380 mov dx,offset dg
:opt_err
382 call prt_err
; print error message
384 jmp short cont_opt
; process rest of options
388 jmp short opt_dispatch
392 jmp short opt_dispatch
396 jmp short opt_dispatch
402 mov byte ptr dg
:[bx+di],TRUE
;set the corresponding flag
407 mov dx,offset dg
:args_err
413 ;-----------------------------------------------------------------------;
417 dec si ;adjust pointer
418 call find_nonb
;find first non blank in com. buffer
419 jc bad_args
;file (or files) missing
420 mov byte ptr [di],0 ;nul terminate
421 mov dx,si ;pointer to file name
422 mov bx,offset dg
:buf1
423 mov word ptr [bx].fname
,dx ;save pointer to file name
424 mov word ptr [bx].fname_len
,cx ;file name length
426 mov al,0 ;open for reading
429 mov word ptr [bx].handle
,ax ;save the handle
432 inc si ;point past the nul
433 call kill_bl
;find other file name
434 jc bad_args
;a CR found: file name missing
435 dec si ;adjust pointer
437 mov byte ptr [di],0 ;nul terminate the file name
439 mov bx,offset dg
:buf2
440 mov word ptr [bx].fname
,dx ;save pointer to file name
441 mov word ptr [bx].fname_len
,cx ;file name length
443 mov al,0 ;open for reading
446 mov word ptr [bx].handle
,ax ;save the handle
450 cmp ax,error_file_not_found
452 mov dx,offset dg
:int_err
456 push cx ;save file name length
457 mov dx,offset dg
:found_err_pre
458 mov cl,found_err_pre_len
461 mov dx,si ;pointer to file name length
463 mov dx,offset dg
:found_err_post
464 mov cl,found_err_post_len
467 mov al,-1 ;return an error code
473 ;-----------------------------------------------------------------------;
477 cmp [flg_b
],true
;do we do a binary comparation?
482 subttl
Binary Compare Routine
485 ;-----------------------------------------------------------------------;
486 ; COMPARE BUFFERS IN BINARY MODE
490 ;----- Fill in the buffers
492 mov bx,offset dg
:buf1
;pointer to buffer structure
493 mov dx,word ptr[bx].buf
;pointer to buffer
494 mov si,dx ;save for latter comparation
495 call read_dat
;read into buffer
496 jc bad_datj
;an error
497 mov word ptr[bx].by_read
,AX ;save ammount read
498 push ax ;save for now
500 mov bx,offset dg
:buf2
;pointer to buffer structure
501 mov dx,word ptr[bx].buf
;pointer to buffer
502 mov di,dx ;save for comparation
503 call read_dat
;read into buffer
504 bad_datj: jc bad_dat
;an error
505 mov word ptr[bx].by_read
,AX ;save ammount read
507 pop cx ;restore byte count of buffer1
508 cmp ax,cx ;compare byte counts
511 or ax,ax ;the same ammount, is it 0?
512 jne go_bcomp
;no,compare
513 jmp go_quit
;yes, all done....
516 mov [bend
],1 ;file 1 ended
520 mov [bend
],2 ;file 2 ended
523 ;----- Compare data in buffers
526 mov ax,word ptr [base
] ;load base addrs. to AX,BX pair
527 mov bx,word ptr [base
+2]
528 add bx,cx ;add to base num. of bytes to
530 mov word ptr [base
],ax ;save total
531 mov word ptr [base
+2],bx
536 repz cmpsb ;compare both buffers
537 jz end_check
;all bytes match
538 push cx ;save count so far
542 sub bx,cx ;get file address of bytes that
543 sbb ax,0 ; are different.
544 call prt_bdif
;print difference
547 pop cx ;restore on-going comparation count
554 cmp [bend
],0 ;have any file ended yet?
555 je bnot_yet
;no, read in more data
556 cmp [bend
],1 ;yes, was it file 1?
557 je bf1_ended
;yes, data left in file 2
558 mov dx,offset dg
:bf1ne
563 mov dx,offset dg
:bf2ne
573 subttl Text Compare Routine
576 ;-----------------------------------------------------------------------;
577 ; Fill in the buffers
580 mov dx,offset dg
:file_err
587 mov bx,offset dg
:buf1
588 mov dx,word ptr [bx].buf
589 mov word ptr [bx].fst_nosinc
,dx
590 mov word ptr [bx].curr
,dx
595 mov bx,offset dg
:buf2
596 mov dx,word ptr [bx].buf
597 mov word ptr [bx].fst_nosinc
,dx
598 mov word ptr [bx].curr
,dx
604 ;-----------------------------------------------------------------------;
605 ; COMPARE BUFFERS IN TEXT MODE
608 call go_match
;try to match both current lines
610 jmp no_match
;no match, continue....
612 cmp byte ptr[sinc
],true
;are we in SINC?
615 or ax,ax ;first line of a possible SINC?
617 mov bx,offset dg
:buf1
618 mov word ptr [bx].fst_sinc
,si ;yes, save curr line buffer 1
619 mov bx,offset dg
:buf2
620 mov word ptr [bx].fst_sinc
,di ;save curr line buffer 2
622 inc ax ;increment match counter
623 mov [mtch_cntr
],ax ;save number of matches
624 cmp m_num
,ax ;enough lines matched for a SINC?
625 jne sj04
;not yet, match some more
626 mov [sinc
],true
;yes, flag we are now in sinc
627 call print_diff
;print mismatched lines
631 ;-----------------------------------------------------------------------;
632 ; Advance current line pointer in both buffers
635 mov bx,offset dg
:buf1
640 mov word ptr[bx].curr
,si
641 mov bx,offset dg
:buf2
646 mov word ptr[bx].curr
,si
647 jmp another_line
;continue matching
651 ;-----------------------------------------------------------------------;
655 cmp [sinc
],true
;are we in SINC?
657 mov [sinc
],false
;not any more....
658 mov bx,offset dg
:buf1
659 mov word ptr [bx].fst_nosinc
,si ;save current lines
660 mov word ptr [bx].lst_curr
,si
661 mov bx,offset dg
:buf2
662 mov word ptr [bx].fst_nosinc
,di
663 mov word ptr [bx].lst_curr
,di
665 mov [mtch_cntr
],0 ;reset match counter
670 mov bx,offset dg
:buf2
671 call adv_b
;get next line in buffer (or file)
672 jc sj08
;no more lines in buffer
674 mov word ptr [bx].curr
,si
677 mov [mode
],true
;change mode
678 mov si,word ptr [bx].lst_curr
679 mov word ptr [bx].curr
,si
680 mov bx,offset dg
:buf1
681 mov si,word ptr [bx].lst_curr
682 mov word ptr [bx].curr
,si
683 call adv_b
;get next line
684 jc no_more1
;no more lines fit in buffer 1
685 mov word ptr [bx].lst_curr
,si
690 mov bx,offset dg
:buf1
691 call adv_b
;get next line in buffer (or file)
692 jc sj11
;no more lines in buffer
694 mov word ptr [bx].curr
,si
699 mov si,word ptr [bx].lst_curr
700 mov word ptr [bx].curr
,si
701 mov bx,offset dg
:buf2
702 mov si,word ptr [bx].lst_curr
703 mov word ptr [bx].curr
,si
704 call adv_b
;get next line
705 jc no_more2
;no more lines fit in buffer 2
706 mov word ptr [bx].lst_curr
,si
711 ;-----------------------------------------------------------------------;
712 ; Process end of files
715 cmp ax,0 ;end of file reached?
717 jmp dif_files
;no, difference was too big
719 cmp [sinc
],true
;file1 ended, are we in SINC?
723 mov bx,offset dg
:buf2
724 call adv_b
;advance current line in buf2
726 jmp go_quit
;file2 ended too, terminate prog.
729 ;----- File 1 ended but NOT file 2
730 mov bx,offset dg
:buf1
732 mov bx,offset dg
:buf2
734 call print_all
;print the rest of file2
739 cmp ax,0 ;end of file reached?
741 jmp dif_files
;no, difference was too big
743 cmp [sinc
],true
;file1 ended, are we in SINC?
747 mov bx,offset dg
:buf1
748 call adv_b
;advance current line in buf2
750 jmp go_quit
;file2 ended too, terminate prog.
753 ;----- File 2 ended but NOT file 1
754 mov bx,offset dg
:buf1
756 call print_all
;print the rest of file1
757 mov bx,offset dg
:buf2
764 mov bx,offset dg
:buf1
767 mov bx,offset dg
:buf2
775 mov dx,offset dg
:dif_err
785 subttl Subroutines
: make caps
788 ;-----------------------------------------------------------------------;
789 ; CAPIALIZES THE CHARACTER IN AL ;
792 ; AL has the character to Capitalize ;
795 ; AL has the capitalized character ;
797 ; Called from MAIN and go_match ;
798 ;-----------------------------------------------------------------------;
808 subttl Subroutines
: kill_bl
811 ;-----------------------------------------------------------------------;
812 ; Get rid of blanks in command line. ;
815 ; SI points to the first character on the line to scan. ;
818 ; SI points to the next char after the first non-blank ;
820 ; Carry Set if a CR found ;
826 ;-----------------------------------------------------------------------;
829 sb1: lodsb ;get rid of blanks
837 stc ;a CR found, set carry
841 subttl Subroutines
: find_nonb
844 ;-----------------------------------------------------------------------;
845 ; Find the first non-blank in a line ;
848 ; SI points to the line buffer ;
851 ; DI pointer to the first blank found (incl. CR) ;
852 ; CX character count of non-blanks ;
853 ; Carry Set if a CR was found ;
859 ;-----------------------------------------------------------------------;
861 push si ;save pointer
862 xor cx,cx ;zero character count
872 inc cx ;inc character count
887 subttl Subroutines
: prt_bdif
890 ;-----------------------------------------------------------------------;
891 ; Print a binary difference ;
894 ; AX,BX file address of diference ;
895 ; SI pointer to one past byte in buffer1 ;
896 ; DI pointer to one past byte in buffer2 ;
901 ; called from bin_compare ;
902 ;-----------------------------------------------------------------------;
904 cmp [bhead_flg
],true
;have we peinted head yet?
906 mov [bhead_flg
],true
;no, set flag
907 push ax ;print heading
908 mov dx,offset dg
:bhead
915 mov dx,di ;conver file address
916 mov di,offset dg
:bp_buf1
927 mov di,offset dg
:bp_buf2
;convert byte from file 1
928 mov al, byte ptr[si-1]
931 mov di,offset dg
:bp_buf3
;convert byte from file 2
934 mov al, byte ptr[si-1]
938 mov di,dx ;print result
939 mov dx,offset dg
:bp_buf
945 subttl Subroutines
: bin2hex
948 ;-----------------------------------------------------------------------;
949 ; Binary to ASCII hex conversion ;
952 ; AL byte to convert ;
953 ; DI pointer to were the two result ASCII bytes should go ;
956 ; DI points to one past were the last result byte whent ;
961 ; Called from prt_bdif ;
962 ;-----------------------------------------------------------------------;
965 ror ax,cl ;get the high nibble
966 and al,0fh ;mask of high nible
968 rol ax,cl ;get the low nibble
972 cmp al,0ah ;is it past an A ?
979 stosb ;place in buffer
983 subttl Subroutines
: go_match
986 ;-----------------------------------------------------------------------;
987 ; Match current lines ;
990 ; Carry set if the match reset otherwise ;
991 ; SI Current line of buff1 ;
992 ; DI Current line of buff2 ;
996 ; AX,BX,CX,DX and BP ;
998 ; Called from txt_compare ;
999 ;-----------------------------------------------------------------------;
1001 mov bx,offset dg
:buf1
1002 mov si,word ptr[bx].curr
1004 mov bp,si ;save line pointer
1006 mov dx,cx ;save length of line
1007 mov bx,offset dg
:buf2
1008 mov si,word ptr[bx].curr
1012 cmp cx,dx ;compare lengths
1013 jne sd1
;they do not match
1014 mov si,bp ;restore line pointer
1015 jcxz sd4
;both length = 0, they match
1016 push cx ;save the length
1018 repz cmpsb ;compare strings
1019 pop cx ;restore the length
1022 cmp [flg_w
],true
;do we ignore multiple whites?
1023 je ib_compare
;yes, go compare
1024 cmp [flg_c
],true
;do we ignore case differences?
1025 je ic_compare
;yes, go compare
1027 clc ;they don't match
1039 ;-----------------------------------------------------------------------;
1040 ; Compare ignoring case differences.
1043 pop di ;get pointer to lines
1045 push si ;re-save pointers
1048 mov al,byte ptr [si] ;get next char. of first line
1050 mov bl,al ;save capitalized char
1051 mov al,byte ptr [di] ;get next chra. of second line
1054 jne sd3
;they do not match....
1055 inc si ;advance pointers
1057 loop sd8
;loop for the line lengths
1058 jmp short sd4
;they match
1063 ;-----------------------------------------------------------------------;
1064 ; Compare compressing whites and ignoring case differences if
1068 mov [ib_first1
],true
;we start by the first char in the
1069 mov [ib_first2
],true
; in the lines.
1070 pop di ;get pointer to lines
1072 push si ;re-save pointers
1075 mov al,byte ptr [si] ;get next char. of first line
1076 call isa_white
;is it a white?
1077 jnc sd12
;no, compare....
1079 mov al,byte ptr [si+1] ;peek to next,
1080 call isa_white
; it is a white too?
1083 jmp short sd10
; compress all whites to a blank
1085 cmp [ib_first1
],true
;is this the first char. of the line?
1086 jne sd111
;no, it stays a white
1087 inc si ;ignore the white
1090 cmp al,CR
;is this the last char. of the line
1091 jne sd112
;no, it stays a white
1092 inc si ;yes, ignore the whites
1095 mov al,' ' ;no more whites found
1098 cmp [ib_first1
],true
;is this the first char. of the line?
1099 jne sd121
;no, continue
1100 mov [ib_first1
],false
;yes, reset the flag
1102 cmp [flg_c
],true
;do we ignore case?
1106 mov bl,al ;save char
1107 mov al,byte ptr [di] ;get next chra. of second line
1111 mov al,byte ptr [di+1] ;peek to next as before
1117 cmp [ib_first2
],true
;is this the first char. of the line?
1118 jne sd141
;no, it stays a white
1119 inc di ;ignore the white
1122 cmp al,CR
;is this the last char. of the line
1123 jne sd142
;no, it stays a white
1124 inc si ;yes, ignore the whites
1130 cmp [ib_first2
],true
;is this the first char. of the line?
1131 jne sd151
;no, continue
1132 mov [ib_first2
],false
;yes, reset the flag
1134 cmp [flg_c
],true
;do we ignore case?
1140 jmp sd3
;they do not match....
1142 cmp al,CR
;have we reached the end?
1143 jne sd154
;no, continue....
1144 jmp sd4
;yes, they match
1146 inc si ;no, advance pointers
1148 jmp sd9
;loop for the line lengths
1152 cmp al,' ' ;is it a space?
1154 cmp al,09h ;is it a tab?
1156 clc ;if not a white return with carry clear
1159 stc ;is a white return with carry set
1165 ;-----------------------------------------------------------------------;
1167 xor cx,cx ;zero count
1179 subttl Subroutines
: adv_b
1182 ;-----------------------------------------------------------------------;
1183 ; Get the next line in the buffer ;
1185 ; It will attempt to get the next current line from the buffer ;
1186 ; if it fails, it will force a refill, and if some data is read in ;
1187 ; then it will return the next current line. ;
1190 ; BX pointer to buffer structure ;
1193 ; SI pointer to next line (if any) ;
1194 ; Carry set if no more lines available. If carry set then: ;
1195 ; AX End Code: 0 = end of file reached ;
1196 ; 1 = no room in buffer for a line ;
1201 ; Called from txt_compare ;
1202 ;-----------------------------------------------------------------------;
1216 subttl Subroutines
: get_nextl
1219 ;-----------------------------------------------------------------------;
1220 ; Returns the next line in a buffer ;
1221 ; (next from current or next from pointer) ;
1224 ; BX pointer to buffer structure ;
1225 ; (SI pointer to line, if calling get_next) ;
1228 ; SI pointer to next line ;
1229 ; Carry set if no more lines available ;
1234 ; Called from adv_b and print_diff (in the case of get_next) ;
1235 ;-----------------------------------------------------------------------;
1237 mov si,word ptr [bx].curr
1239 mov cx,word ptr [bx].dat_end
1245 mov si,di ;pointer to next line
1250 inc si ;point past the LF
1255 subttl Subroutines
: refill
1258 ;-----------------------------------------------------------------------;
1261 ; It will refill a buffer with data from the corresponding ;
1262 ; file. It will first recompact the buffer to make room for the new ;
1263 ; data. If in SINC then it will move the current line to the top of ;
1264 ; the buffer, and read the data from the end of this line till the ;
1265 ; end of the buffer. ;
1266 ; If NOT in SINC then it will recompact the buffer by moving ;
1267 ; all lines between the first to go out of SINC till the current line ;
1268 ; to the top of the buffer, and then reading data after the current ;
1270 ; When recompacting the buffer it relocates all pointers to ;
1271 ; point to the new locations of the respective lines. ;
1272 ; Some of the pointers may be pointing to meaningless locations ;
1273 ; before the relocation, and consecuently they will be pointing to ;
1274 ; even less meaningfull locations after relocation. ;
1275 ; After reading the data it normalizes the buffer to make sure ;
1276 ; that no partially full lines are present at the end of the buffer. If ;
1277 ; after recompacting and reading some character it is found that the ;
1278 ; characters read do not constitute a full line, then it will return ;
1279 ; with an error code. It will also return with an error code if it ;
1280 ; attempts to read past the end of file. ;
1283 ; BX pointer to buffer structure ;
1286 ; Carry set if no chars read into the buffer. If carry set then: ;
1287 ; AX End Code: 0 = end of file reached ;
1288 ; 1 = no room in the buffer for a line ;
1293 ; Called from adv_b ;
1294 ;-----------------------------------------------------------------------;
1297 ;----- Calculate ammount to move & pointer relocation factor.
1301 mov si,word ptr [bx].curr
1304 mov si,word ptr [bx].fst_nosinc
1306 mov di,word ptr [bx].buf
1307 mov cx,word ptr [bx].dat_end
1309 mov dx,si ;calculate pointer relocation factor
1310 sub dx,di ;DX = factor
1311 jz sf3
;no room in buffer
1312 sub cx,si ;calculate ammount of data to move
1313 inc cx ;CX = ammount
1320 ;----- Relocate pointers
1322 sub word ptr [bx].curr
,dx
1323 sub word ptr [bx].lst_curr
,dx
1324 sub word ptr [bx].fst_sinc
,dx
1325 sub word ptr [bx].fst_nosinc
,dx
1326 sub word ptr [bx].dat_end
,dx
1329 mov dx,word ptr [bx].dat_end
1330 inc dx ;empty part starts here
1332 ;----- fill the buffer
1338 subttl Subroutines
: fill_buffer
1341 ;-----------------------------------------------------------------------;
1342 ; Fill the data buffers ;
1344 ; It will fill the buffer from the pointer to the end of buffer ;
1345 ; and normalize the buffer. ;
1348 ; BX pointer to buffer structure ;
1349 ; DX pointer to buffer (or part of buffer) ;
1352 ; Carry set if no chars read into the buffer. If carry set then: ;
1353 ; AX End Code: 0 = end of file reached ;
1354 ; 1 = no room in the buffer for a line ;
1359 ; Called from txt_compare and refill ;
1360 ;-----------------------------------------------------------------------;
1363 call read_dat
;get data
1365 or ax,ax ;zero chars read?
1368 mov di,cx ;save normalized char. count
1369 mov bp,dx ;save data end for now
1371 ;----- seek for old partial line
1373 or ax,ax ;is the seek value = 0 ?
1374 jz sg1
;yes, do not seek
1378 mov al,1 ;seek from current position
1381 jc bad_read
;error mesage (BX already in stack)
1384 mov cx,di ;restore normalized char count.
1385 or cx,cx ;char count = 0 due to normalization?
1389 mov word ptr [bx].dat_end
,bp
1394 mov dx,offset dg
:read_err_pre
1395 mov cl,read_err_pre_len
1396 call prt_err
;print error message
1398 mov dx,word ptr[bx].fname
1399 mov cx,word ptr[bx].fname_len
1400 call prt_err
;print file name
1401 mov dx,offset dg
:read_err_post
1402 mov cl,read_err_post_len
1417 subttl Subroutines
: read_dat
1420 ;-----------------------------------------------------------------------;
1423 ; DX pointer to data area (buffer or part of buffer) ;
1426 ; AX character count or error code (from DOS read) ;
1427 ; Carry set if error condition ;
1432 ; Called from fill_buffer, print_all and bin_compare ;
1433 ;-----------------------------------------------------------------------;
1435 mov cx,word ptr [bx].buf_end
1436 mov bx,word ptr [bx].handle
1437 sub cx,dx ;ammount to read to buff1
1443 subttl Subroutines
: nor_buf
1446 ;-----------------------------------------------------------------------;
1447 ; Normalize buffers so they do not have partially full ;
1448 ; lines at the end. If character count is less than the buffer size ;
1449 ; then it checks that the last line is terminated by a CR,LF pair. ;
1450 ; If it is not it inserts a CR,LF at the end. It returns a seek value ;
1451 ; for the buffer corresponding to the number of characters in the ;
1452 ; incomplete line at the end of the buffer (if any). This can be used ;
1453 ; to start reading from the beggining of the incomplete line on next ;
1454 ; time the buffer is loaded. ;
1457 ; DX buffer pointer ;
1458 ; AX character count read ;
1459 ; CX character count requested ;
1462 ; DX pointer to last char in buffer (normalized) ;
1463 ; CX character count (normalized) ;
1469 ; Called from fill_buffer ;
1470 ;-----------------------------------------------------------------------;
1474 dec di ;points to last char in buffer
1475 cmp ax,cx ;were all chars. requested read?
1476 je sm7
;yes, buffer full
1477 cmp byte ptr[di],1
ah ;terminated with a ^Z ?
1479 dec di ;point to previous character
1480 dec ax ;decrement character count
1481 sm1: cmp byte ptr[di],lf
;is last char a LF?
1483 cmp byte ptr[di],cr
;is it a CR then?
1485 add ax,2 ;two more chars in buffer
1487 sm2: mov byte ptr[di],cr
1490 sm4: mov cx,ax ;new character count
1491 mov dx,di ;pointer to last char
1496 inc ax ;one more char in buffer
1500 cmp byte ptr[di-1],cr
;is previous char a CR?
1502 inc ax ;no, one more char in buffer
1506 push ax ;save char count
1510 repnz scasb ;search for last LF
1511 pop ax ;restore char count
1512 jnz bad_line
;none found, line too big
1513 inc di ;point to last LF
1515 inc cx ;ammount of chars in buffer
1516 sub ax,cx ;seek value
1519 bad_line: ;full line not possible, return
1520 mov dx,di ; with AX=count, CX=0 and DX=
1521 ret ; old last char in buffer pointer.
1525 subttl Subroutines
: print_diff
1528 ;-----------------------------------------------------------------------;
1529 ; print the difference between buffers ;
1531 ; It will print the mismatched lines. First it prints a heading ;
1532 ; with the first file name, then the lines that differ from file 1, ;
1533 ; then a heading with the second file name, and then the lines that ;
1534 ; differ in file 2 . ;
1535 ; The lines that differ are considered to start from fst_nosinc ;
1538 ; Called from txt_compare ;
1539 ;-----------------------------------------------------------------------;
1541 mov bx,offset dg
:buf1
1542 call print_head
;print heading for file 1
1543 mov dx,word ptr [bx].fst_nosinc
1544 mov si,word ptr [bx].fst_sinc
1545 call get_next
;get pointer to next line
1547 sub cx,dx ;get character count
1549 mov bx,offset dg
:buf2
1550 call print_head
;print heading for file 1
1551 mov dx,word ptr [bx].fst_nosinc
1552 mov si,word ptr [bx].fst_sinc
1553 call get_next
;get pointer to next line
1555 sub cx,dx ;get character count
1557 mov dx,offset dg
:diff_sep
1560 call prout
;print difference separator
1564 subttl Subroutines
: print_head
1567 ;-----------------------------------------------------------------------;
1568 ; Print heading for difference ;
1571 ; BX pointer to buffer structure ;
1576 ; Called from txt_compare and print_diff ;
1577 ;-----------------------------------------------------------------------;
1579 mov dx,offset dg
:fname_sep
1580 mov cl,fname_sep_len
1583 mov dx,word ptr [bx].fname
1584 mov cx,word ptr [bx].fname_len
1586 mov dx,offset dg
:CRLF
1592 subttl Subroutines
: print_all
1595 ;-----------------------------------------------------------------------;
1596 ; Print the rest of a file ;
1598 ; If in SINC it will print the file from the fst_nosinc line ;
1599 ; till the end of the file. If NOT in SINC then it will print from ;
1600 ; the current line of the buffer to the end of the file. ;
1603 ; BX pointer to buffer structure ;
1608 ; Called from txt_compare ;
1609 ;-----------------------------------------------------------------------;
1611 cmp [sinc
],true
;are we in SINC?
1613 mov dx,word ptr [bx].curr
1616 mov dx,word ptr [bx].fst_nosinc
1618 mov cx,word ptr [bx].dat_end
1622 sub cx,dx ;ammount of data to write
1623 call prout
;write it out
1625 ;----- Read more data to the buffer
1626 push bx ;save pointer to buffer struct
1627 mov dx,word ptr [bx].buf
1630 jmp bad_read
;print error (BX in stack)
1632 or ax,ax ;zero chars read?
1634 pop bx ;all done writting
1638 mov cx,word ptr [bx].buf_end
1639 jmp short prt_again
;print next buffer full
1642 subttl Subroutines
: prout
and prt_err
1645 ;-----------------------------------------------------------------------;
1647 ;-----------------------------------------------------------------------;
1657 ;-----------------------------------------------------------------------;
1659 ;-----------------------------------------------------------------------;