summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMP/COMP2.ASM
blob: e4e719afbc227d465ab63c8ee075c934cd0658dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
	PAGE	,132			;
	title	COMP2.SAL - COMPARES FILES
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: COMP2.ASM
;
; DESCRIPTIVE NAME: Compare two files to show they are identical or not.
;
; FUNCTION:  The paths and names of each pair of files is
;	 displayed as the comparing process proceeds.  An
;	 error message will follow the names if:
;	     (1) a file matching the second filename can't be found,
;	     (2) the files are different sizes,
;	     (3) either path is invalid, or.
;	     (4) CHCP=Yes (CODE PAGE active) and code page of files
;		do not match.
;
;	 During the comparison, an error message will appear for any
;	 location that contains mismatching information in the 2
;	 files.  The message indicates the offset into the files of
;	 the mismatching bytes, and the contents of the 2 bytes
;	 themselves (all in hex).  This will occur for up to 10
;	 mismatching bytes - if more than 10 compare errors are
;	 found, the program assumes that further comparison would be
;	 useless, and ends its compare of the 2 files at that point.
;
;	 If all bytes in the 2 files match, a "Files compare OK"
;	 message will appear.
;
;	 In all cases, after the comparing of 2 files ends, comparing
;	 will proceed with the next pair of files that match the 2
;	 filenames, until no more files can be found that match the
;	 first filename.  You are then asked if you want to compare
;	 any more files.  Replying "N" returns you to the DOS prompt
;	 (such as A>); a reply of "Y" results in prompts for new
;	 primary and secondary filenames.
;
;	 In all compares, COMP looks at the last byte of one of the
;	 files being compared to assure that it contains a valid
;	 end-of-file mark (CTRL-Z, which is the hex character 1A).
;	 If found, no action is taken by COMP.	If the end-of-file
;	 mark is NOT found, COMP produces the message "EOF mark not
;	 found".  This is done because some products produce files
;	 whose sizes are always recorded in the directory as a
;	 multiple of 128 bytes, even though the actual usable data in
;	 the file will usually be a few bytes less than the directory
;	 size.	In this case, COMP may produce "Compare error"
;	 messages when comparing the few bytes beyond the last real
;	 data byte in the last block of 128 bytes (COMP always
;	 compares the number of bytes reflected in the directory).
;	 Thus, the "EOF mark not found" message indicates that the
;	 compare errors may not have occurred in the usable data
;	 portion of the file.
;
;	 Multiple compare operations may be performed with one load
;	 of COMP.  A prompt, "Compare more files (Y/N)?" permits additional
;	 executions.
;
; ENTRY POINT: "INIT", jumped to by COMP1 at the DOS entry point.
;
; INPUT: (DOS command line parameters)
;	[d:][path] COMP [d:][path][filenam1[.ext]] [d:][path][filenam2[.ext]]
;
;	 Where
;	 [d:][path] before COMP to specify the drive and path that
;		    contains the COMP command file.
;
;	 [d:][path][filenam1[.ext]] -  to specify the FIRST (or primary)
;		    file or group of files to be compared
;
;	 [d:][path][filenam2[.ext]]  - to specify the SECOND file or group
;		    of files to be compared with the corresponding file
;		    from the FIRST group
;
;	 Global filename characters are allowed in both filenames,
;	 and will cause all of the files matching the first filename
;	 to be compared with the corresponding files from the second
;	 filename.  Thus, entering COMP A:*.ASM B:*.BAK will cause
;	 each file from drive A:  that has an extension of .ASM to be
;	 compared with a file of the same name (but with an extension
;	 of .BAK) from drive B:.
;
;	 If you enter only a drive specification, COMP will assume
;	 all files in the current directory of the specified drive.
;	 If you enter a path without a filename, COMP assumes all
;	 files in the specified directory.  Thus, COMP A:\LEVEL1
;	 B:\LEVEL2 will compare all files in directory A:\LEVEL1 with
;	 the files of the same names in directory B:\LEVEL2.
;
;	 If no parameters are entered with the COMP command, you will
;	 be prompted for both.	If the second parm is omitted, COMP
;	 will prompt for it.  If you simply press ENTER when prompted
;	 for the second filename, COMP assumes *.* (all files
;	 matching the primary filename), and will use the current
;	 directory of the default drive.
;
;	 If no file matches the primary filename, COMP will prompt
;	 again for both parameters.
;
; EXIT-NORMAL: Errorlevel = 0, Function completed successfully.
;
; EXIT-ERROR: Errorlevel = 1, Abnormal termination due to error, wrong DOS,
;	      invalid parameters, unrecoverable I/O errors on the diskette.
;
; EFFECTS: Files are not altered.  A Message will show result of compare.
;
; INTERNAL REFERENCES:
;    ROUTINES:
;	SENDMSG - passes parms to regs and invokes the system message routine.
;	EXTERR - get extended error and display message.
;	INIT_CP - record chcp switch then turn off. Allows COMP to open first
;		  or second file regardless of the system code page.
;	RESTORE_CP - resets the chcp switch to the initial value.
;	COMP_CODEPAGE - verify matching code pages.
;	GET_CP - do an extended open, get code page, then close.
;
;    DATA AREAS:
;	WORKAREA - Temporary storage
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;	SYSDISPMSG - Uses the MSG parm lists to construct the messages
;		 on STDOUT.
;	SYSLOADMSG - Loads messages, makes them accessable.
;	SYSPARSE - Processes the DOS Command line, finds parms.
;
;    DATA AREAS:
;	 PSP - Contains the DOS command line parameters.
;	 COMPSM.SAL - Defines the control blocks that describe the messages
;	 COMPPAR.SAL - Defines the control blocks that describe the
;		DOS Command line parameters.
;
; NOTES:
;	 This module should be processed with the SALUT preprocessor
;	 with the re-alignment not requested, as:
;
;		SALUT COMP2,NUL
;
;	 To assemble these modules, the alphabetical or sequential
;	 ordering of segments may be used.
;
;	 For LINK information, reference Prolog of COMP1.SAL.
;
; COPYRIGHT: The following notice is found in the OBJ code generated from
;	     the "COMPSM.SAL" module:
;
;	     "The DOS COMP Utility"
;	     "Version 4.0  (C) Copyright 1988 Microsoft"
;	     "Licensed Material - Property of Microsoft"
;
; Modification History:
;
;   Version   Author	       date	 comment
;   -------   ------	       ----	 -------
;   V0.0      Dave L.			 Original author
;
;   V3.3      Russ W.
;
;   V4.0      Edwin M. K.		 ;AN000; Extended attribute support,
;	      Bill L.	     7/10/87	 parser, message retriever support
;
;   V4.0      Bill L.	     9/17/87	 ;AN001; - DCR 201 enhancements to the
;					 extended attribute support
;
;   V4.0      Bill L.			 ;AN002; - PTM 708
;					 ;AN003; - PTM 728
;					 ;AN004; - PTM 1610
;					 ;AN005; - PTM 274
;					 ;AN006; - PTM 2205 (DBCS support)
;					 ;AN007; - PTM 3056 (y/n -> STDERR)
;					 ;AN008; -	    optimizations
;					 ;AN009; - PTM 4076 network hang
;
;****************** END OF SPECIFICATIONS *****************************
	page

	if1
	    %OUT    COMPONENT=COMP, MODULE=COMP2.SAL
	endif

;***********************************
; Macro definitions
;***********************************

fill_name1 macro pfcb			;AN000;
	push	dx			;AN000;
	push	di			;AN000;
	push	si			;AN000;
	mov	dx,offset name1 	;AN000;
	mov	si,offset path1 	;AN000;
	mov	di,offset pfcb		;AN000;
	call	fill_n			;AN000;
	pop	si			;AN000;
	pop	di			;AN000;
	pop	dx			;AN000;
	endm				;AN000;

fill_name2 macro			;AN000;
	push	dx			;AN000;
	push	di			;AN000;
	push	si			;AN000;
	mov	dx,offset name2 	;AN000;
	mov	si,offset path2 	;AN000;
	mov	di,offset outfcb	;AN000;
	call	fill_n			;AN000;
	pop	si			;AN000;
	pop	di			;AN000;
	pop	dx			;AN000;
	endm				;AN000;

print_msg macro msg,handle		;AC003;
	push	ax			;AN000;
	mov	dx,offset msg		;AN000; ;dx: ptr to msg descriptor
	ifnb	<handle>		;AN003; ;check if new handle given
	    push    di			;AN003; ;put new handle in msg structure
	    mov     di,dx		;AN003;
	    mov     [di].msg_handle,handle ;AN003;
	    pop     di			;AN003;
	endif				;AN003;
	call	sendmsg 		;AC000;
	pop	ax			;AN000;
	endm				;AN000;

doscall macro	func,subfunc		;AN000;
	ifnb	<func>			;AN000; ;are there any parms at all ?
	    ifnb    <subfunc>		;AN000; ;is there a sub-function ?
		mov	ax,(func shl 8)+subfunc ;AN000; ;yes, ah=func, al=subfunc
	    else			;AN000; ;no sub-function
		mov	ah,func 	;AN000;
	    endif			;AN000;
	endif				;AN000;
	int	21h			;AN000;
	endm				;AN000;

;***********************************
; Include equates
;***********************************

	include compeq.inc		;AN000; ;include some equates

;***********************************
; Extended attribute structures
;***********************************

ea	struc				;AN001; ;extended attr. structure
ea_type db	EAISBINARY		;AN001;
ea_flags dw	EASYSTEM		;AN001;
ea_rc	db	?			;AN001;
ea_namelen db	2			;AN001;
ea_vallen dw	2			;AN001;
ea_name db	"CP"			;AN001;
ea_value dw	?			;AN001;
ea	ends				;AN001;

qea	struc				;AN001; ;query extended attr. name
qea_type db	EAISBINARY		;AN001;
qea_flags dw	EASYSTEM		;AN001;
qea_namelen db	2			;AN001;
qea_name db	"CP"			;AN001;
qea	ends				;AN001;

;***********************************
; Code Segment
;***********************************

cseg	segment para public 'CODE'	;AC000;
	assume	cs:cseg,ds:cseg,es:cseg,ss:cseg ;as set by DOS loader

	extrn	parser:near		;AN000;
	extrn	sysloadmsg:near 	;AN000;
	extrn	sysdispmsg:near 	;AN000;
	extrn	memory_size:word
	extrn	fcb:byte
	extrn	parms:word		;AN000;
	extrn	parm_area:byte
	extrn	parm_count:word 	;AN000;
	extrn	current_parm:word	;AN000;
	extrn	ordinal:word		;AN000;
	extrn	msgnum_mem:word 	;AN000;
	extrn	msgnum_para:word	;AN000;
	extrn	msgnum_tenmsg:word	;AN000;
	extrn	msgnum_baddrv:word	;AN000;
	extrn	msgnum_bad:word 	;AN000;
	extrn	msgnum_adr:word 	;AN000;
	extrn	msgnum_bdr:word 	;AN000;
	extrn	msgnum_eor:word 	;AN000;
	extrn	msgnum_done:word	;AN000;
	extrn	msgnum_fnf:word 	;AN000;
	extrn	msgnum_bad_path:word	;AN000;
	extrn	msgnum_share:word	;AN000;
	extrn	msgnum_too_many:word	;AN000;
	extrn	msgnum_prinam:word	;AN000;
	extrn	msgnum_secnam:word	;AN000;
	extrn	msgnum_badsiz:word	;AN000;
	extrn	msgnum_nother:word	;AN000;
	extrn	msgnum_and_msg:word	;AN000;
	extrn	msgnum_crlf:word	;AN000;
	extrn	msgnum_accessdenied:word ;AN000;
	extrn	msgnum_cp_mismatch:word ;AN000;
	extrn	msgnum_ok:word		;AN000;
	extrn	msgnum_exterr:word	;AN000;
	extrn	msgnum_pparse:word	 ;AN000;
	extrn	sublist_6:word		;AN000;
	extrn	sublist_7:word		;AN000;
	extrn	sublist_8:word		;AN000;
	extrn	sublist_11:word 	;AN000;
	extrn	sublist_12:word 	;AN000;
	extrn	sublist_13:word 	;AN000;
	extrn	sublist_19a:word	;AN000;
	extrn	sublist_19b:word	;AN000;
	extrn	sublist_21:word 	;AN000;
	extrn	sublist_exterr:word	;AN000;
	extrn	sublist_24:word 	;AN000;

;***********************************
; Data area in code segment
;***********************************

	public	path1			;AN000;
	public	path2			;AN000;
	public	name1			;AN000;
	public	name2			;AN000;
	public	cur_name		;AN000;
	public	exitfl			;AN000;

	even				;AN000; ;align stack on word boundary

stack_area db	512 dup ("S")		;Added in DOS 3.20 to support hardware requiring
End_Stack_Area db 00h			;large stacks. DO NOT PUT DATA ABOVE THIS !

clear	db	00h			;AN000; ;clear path2
cur_name dw	00h			;AN000; ;ptr to current filename
input_buf db	130 dup (0)		;AN000; ;input buffer for keyb input
name1	db	130 dup (0)		;AN000; ;source file name
name2	db	130 dup (0)		;AN000; ;target file name
byte1	db	00h			;AN000; ;on compare: bad byte for source
byte2	db	00h			;AN000; ;on compare: bad byte for target
fcb2	db	16 dup (0)		;entered target filespec
;--------KEEP NEXT VARIABLes IN ORIGINAL ORDER-------------
oldp1	db	67 dup (0)		;original path for the first drive    1 KEEP IN ORDER
path1	db	130 dup (0)		;path we'll use for the first drive   2
infcb	db	37 dup (0)		;source fcb			      3
oldp2	db	67 dup (0)		;original path for second drive       4
path2	db	130 dup (0)		;path we'll use for second drive      5
outfcb	db	37 dup (0)		;target fcb			      6
;--------KEEP ABOVE VARIABLes IN ORIGINAL ORDER------------
sav	db	2 dup (0)
mem	db	2 dup (0)		;size of large buffer in bytes
curfcb	db	4 dup (0)		;first 2 bytes = addr of fcb for large buffer,
					;last 2 bytes = addr of fcb for small buffer
curpos	dw	00h			;current byte offset in large buffer
buf2	dw	00h			;seg address of large buffer
siz	dw	512			;# bytes of data left to compare in large buffer
swt	db	00h			;Bit switch:
					; 1   = read file to eof
					; 4   = had compare error
					; 8   = eof mark not found
					; 16  = secondary dir path has been found
					; 32  = primary file opened
					; 64  = secondary file opened
					; 128 = zero suppress switch
swt2	db	00h			;Bit switch:
					; 1 = oldp1 setup
					; 2 = oldp2 setup
offs	db	00h,00h,00h,00h 	;count of bytes compared
cnt	db	00h			;# of bad compares
offp	db	8 dup(0)		;AC000; ;offset of mis-compare between bytes
off_byte db	8 dup (0)		;AN000; ;same as offp, but the words are reversed
curdrv	db	00h			;actual number of default drive
cdrv	db	" :"			;ascii letter of default drive
pathchar db	"\",00h
tbl	db	"0123456789ABCDEF"
openpath db	15 dup (0)		;An fcb will be parsed into this path.
cpsw_orig db	00h			;AN000; ;save original cpsw value
exitfl	db	EXOK			;AN000; ;errorlevel return code
handle	dw	00h			;AN000;

dbcs_off dw	0			;AN006;
dbcs_seg dw	0			;AN006;
dbcs_len dw	0			;AN006;
string_off dw	0			;AN006;
string_seg dw	0			;AN006;
dstring db	128 dup(0)		;AN006;

parm_list label word			;AN001;
	dd	-1			;AN001;
	dw	1			;AN001;
	db	6			;AN001;
	dw	2			;AN001;

querylist label byte			;AN001; ;query general list
	dw	1			;AN001; ;# of entries
querylist_qea qea <EAISBINARY,EASYSTEM,2,"CP"> ;AN001;

qlist	label	byte			;AN001; ;general get/set list
	dw	1			;AN001; ;count of attr entries
qlist_ea ea	<EAISBINARY,EASYSTEM,?,2,2,"CP",?> ;AN001; ;return code page in this structure

;***********************************
; Code area in code segment
;***********************************


;-----------------------------------------------------------------------------
; INIT - Fill in fill_seg, fill_off in all msg sublists with current seg_id
;	 and offset. Also calls the system load massage function so it can
;	 establish addressability to the system messages, and for it to verify
;	 the DOS version
;-----------------------------------------------------------------------------
init	proc	near			;AC000;
	public	init			;AN000;

	mov	sp,offset End_Stack_Area ;Big Stack
	push	ax			;AN000; ;on entry--ax (should) = valid drive parm
	call	setfill 		;AN000; ;init fill_seg, fill_off in sublists
	call	sysloadmsg		;AN000; ;init sysmsg handler

;	$if	c			;AN000; ;if there was a problem
	JNC $$IF1
	    call    sysdispmsg		;AN000; ;let him say why we had a problem
	    mov     exitfl,EXVER	;AN000; ;tell errorlevel bad DOS version
;	$else				;AN000; ;since sysdispmsg is happy
	JMP SHORT $$EN1
$$IF1:
	    call    get_dbcs_vector	;AN006; ;get DOS DBCS table vector
;;(deleted for AN009)		 call	 init_cp	     ;AN000; ;get current setting of CHCP
	    pop     ax			;AN000; ;restore valid drive parm
	    call    more_init		;AN000; ;do more init
	    call    main		;AN000; ;do rest of utility as normal
;;(deleted for AN009)		 call	 restore_cp	     ;AN000; ;set CHCP back to normal
;	$endif				;AN000; ;ok with sysdispmsg?
$$EN1:
	mov	al,exitfl		;AN000; ;pass back errorlevel ret code
	doscall RET_FN			;AN000; ;return to DOS with ret code
	int	20h			;AN000; ;if above not work,
					;AN000; ;take stick and kill it
init	endp				;AN000;


;------------------------------------------------------------------------------
; MAIN - Does the compare for two sets of files
;------------------------------------------------------------------------------
;
main	proc	near			;AN000;
	public	main			;AN000;

	mov	clear,0 		;clear it
;	$do				;AN000;
$$DO4:
	    cmp     byte ptr path1,0	;was first parm given?
;	$leave	ne			;AN000; ;Yes, LEAVE INPUT loop
	JNE $$EN4
	    mov     byte ptr path2,0	;AN000; ;make sure that we get the second file name
rpt:
	    mov     dx,offset msgnum_prinam ;AC000; ;to ask user for first parm
	    mov     parm_count,FIRST_PARM_CT ;AN000; ;THIS IS FIRST PARM (ONLY ONE ACTUALLY)
	    call    getnam		;get first parm from user in  path1  and  fcb
	    mov     di,offset fcb	;AN000; ;es:di=ptr TO UNOPENED fcb
	    mov     si,offset path1	;AN000; ;ds:si=ptr TO COMMAND LINE TO PARSE
					;AN000; ;AL-BIT VALUE CONTROLS PARsiNG
	    doscall PARSE_FILENAME,01H	;AN000; ;AND GO MAKE AN fcb, SCAN OFF LEAdiNG SEPARATORS
	    cmp     AL,255		;AN000; ;INVALID DRIVE?
;	    $if     e			;AN000; ;Yes
	    JNE $$IF6
		print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec."
		mov	byte ptr path1,00 ;AN000; ;BLANK FIRST CHAR. SO TO loop AGAIN
;	    $endif			;AN000;
$$IF6:
;	$enddo				;AC000; ;REPEAT UNTIL FIRST PARM OK
	JMP SHORT $$DO4
$$EN4:

;chek2: 				;GET/SET SECOND FILENAME
	cmp	clear,1
;	$if	e
	JNE $$IF9
	    mov     byte ptr path2,0
	    mov     clear,0
;	$endif
$$IF9:
;	$do				;AN000;
$$DO11:
	    cmp     byte ptr path2,0	;was second parm given?
;	$leave	ne			;AN000; ;Yes, LEAVE INPUT loop
	JNE $$EN11
	    mov     dx,offset msgnum_secnam ;AC000; ;to ask for second parm
	    mov     parm_count,TRICK_PARM_CT ;AN000; ;THIS IS FIRST PARM (ONLY ONE ACTUALLY)
					;AN000; ;BUT PUT FILENAME IN path2 INSTEAD OF path1
	    call    getnam		;get second parm in path2 and fcb2
	    mov     di,offset fcb2	;AN000; ;es:di=ptr TO UNOPENED fcb
	    mov     si,offset path2	;AN000; ;ds:si=ptr TO COMMAND LINE TO PARSE
					;AN000; ;AL-BIT VALUE CONTROLS PARsiNG
	    doscall PARSE_FILENAME,01H	;AN000; ;AND GO MAKE AN fcb, SCAN OFF LEAdiNG SEPARATORS
	    cmp     AL,255		;AN000; ;INVALID DRIVE?
;	    $if     e			;AN000; ;Yes
	    JNE $$IF13
		print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec."
		mov	byte ptr path2, 00 ;AN000; ;BLANK FIRST CHAR. SO TO loop AGAIN
;	    $endif			;AN000;
$$IF13:
;	$enddo				;AC000; ;SECOND PARM?
	JMP SHORT $$DO11
$$EN11:
	mov	si,offset path1 	;AN000; ;si = ptr TO PATH NAME TO FIND "\" IN
	call	findfs			;AN000; ;FIND LAST "\" AND SAVE ADDR
	mov	si,offset path2 	;AN000; ;si = ptr TO PATH NAME TO FIND "\" IN
	call	findfs			;AN000; ;FIND LAST "\" AND SAVE ADDR
	mov	al,curdrv		;get default drive
	cmp	byte ptr fcb,0		;source on default?
;	$if	e			;AC000; ;Yes
	JNE $$IF16
	    mov     fcb,al		;yes, set to actual drive
;	$endif				;AC000;
$$IF16:
	cmp	byte ptr fcb2,0 	;target on default?
;	$if	e			;AC000; ;Yes
	JNE $$IF18
	    mov     fcb2,al		;yes, set to actual drive
;	$endif				;AC000; ;***** FIND PRI FILE
$$IF18:
	mov	si,offset path1
	mov	di,offset fcb
	call	findpath		;locate primary's specified dir
;	$if	ne			;AC000;
	JE $$IF20
	    fill_name1 fcb		;AN000; ;get full path name
	    mov     sublist_12.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Invalid path - %0:
	    mov     dx,offset msgnum_bad_path ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY
					;AN000; ;VALUE IN di,si,dx PAssED TO BADFIL CODE
	    jmp     badfil		;dir not found - tell user
;	$endif				;AC000;
$$IF20:
	mov	dx,offset infcb
	doscall SETDTA			;AC000; ;diR FOUND, SET DTA TO SOURCE fcb
	mov	dx,di			;fcb
	doscall SEARCHF 		;AC000; SEARCH FIRST SOURCE FILE
	or	al,al			;find one?
;	$if	nz			;AC000; ;Yes
	JZ $$IF22
	    fill_name1 fcb		;AN000; ;get full path name
	    mov     sublist_11.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "File not found - %0"
	    mov     dx,offset msgnum_fnf ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY
					;AN000; ;VALUE IN di,si,dx PAssED TO BADFIL CODE
	    jmp     badfil
;	$endif				;AC000;
$$IF22:
f1ok:					;OPEN, PRIME PRIMARY FILE
	and	swt,09Fh		;clear file open flags
	mov	dx,offset infcb
	doscall FCBOPEN 		;AC000; OPEN SOURCE FILE
	or	al,al			;Error ?

					;Try to open the same file using a handle open with read access
;	$if	nz			;AC000; ;IF fcb OPEN FAILED, THEN SHARING ERROR
	JZ $$IF24
	    jmp     shrerr
;	$endif				;AC000;
$$IF24:
	mov	si,offset infcb 	;Take this fcb...
	mov	di,offset OpenPath	; and in this area...
	call	MakePathFromfcb 	; make an ASCIIZ path.
	mov	dx,offset OpenPath
	doscall HANDLEOPEN,READONLYACCESS ;AC000; TRY TO OPEN IT WITH READONLY ACCEss
;	$if	c			;AC000;
	JNC $$IF26
	    jmp     accessdenied1	;ERROR OPENING FILE. AssUME ACCEss DENIED.
;	$endif				;AC000;
$$IF26:
	mov	bx,ax			;Put the handle in bx...
	doscall HANDLECLOSE		;AC000; AND CLOSE IT
	cmp	byte ptr path1,0	;using current dir?
;	$if	ne			;AC000; ;NO
	JE $$IF28
	    mov     dx,offset oldp1
	    doscall CHDIR		;AN000; change directory
;	$endif				;AC000;
$$IF28:
;p1ok:
	mov	word ptr infcb+14,1	;set record size
	xor	ax,ax
	mov	di,offset infcb+33
	stosw				;set rr fields
	stosw
	Mov	dx,offset infcb
	call	get			;and prime big buffer from first file
	print_msg msgnum_crlf,STDOUT	;AN000; ;dispLAY CRLF
	print_msg msgnum_crlf,STDOUT	;AN000; ;dispLAY CRLF
	fill_name1 infcb		;AN000; ;get full path name
	mov	sublist_19a.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist FOR "%1 AND %2" MSG
	mov	al,fcb2 		;target drive
	mov	outfcb,al		;to target fcb

					;****** FIND SECONDARY diR
	mov	si,offset path2
	test	byte ptr swt,16 	;has secondary path already been found?
;	$if	z			;AC000; ;NO
	JNZ $$IF30
	    mov     di,offset fcb2
	    call    findpath		;no, find its path now
;	$else				;AC000; ;siNCE SECONDARY PATH ALREADY BEEN FOUND
	JMP SHORT $$EN30
$$IF30:
	    cmp     byte ptr [si],0	;is there a path?
;	    $if     ne			;AC000; ;Yes
	    JE $$IF32
					; BUT IF NOT, WILL USE CURRENT DIR
		mov	dx,si
		doscall CHDIR		;AC000; ;yes, set the secondary dir to proper node

		cmp	al,al		;force eq
;	    $endif			;AC000;
$$IF32:
;	$endif				;AC000;
$$EN30:
	pushf				;save status of secondary dir search
	mov	cx,11
	mov	di,offset outfcb+1	;target filename field
	mov	si,offset fcb2+1	;current target filename
	mov	bx,offset infcb+1	;current source filename
;	$do				;AC000;
$$DO35:
	    lodsb			;get target name char
	    cmp     al,"?"		;is it ambiguous?
;	    $if     E			;AC000; ;Yes
	    JNE $$IF36
		mov	al,[bx] 	;yes, copy char from source
;	    $endif			;AC000;
$$IF36:
	    stosb			;build target name
	    inc     bx			;next source char
;	$enddo	loop			;AC000;
	LOOP $$DO35
	fill_name2			;AN000; ;get full path name
	mov	sublist_19b.sub_value,offset name2 ;AN000; ;SET UP %2 IN sublist FOR "%1 AND %2" MSG
	print_msg msgnum_and_msg,STDOUT ;AN000; ;dispLAY " AND "
	print_msg msgnum_crlf,STDOUT	;AN000; ;dispLAY CRLF
	popf				;return from getting secondary dir
;	$if	ne			;AC000; ;diD NOT GET IT
	JE $$IF39
	    fill_name2			;AN000; ;get full path name
	    mov     sublist_12.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist FOR "%1 - INVALID PATH" ;AN000;
	    print_msg msgnum_bad_path,STDERR ;AN000; ;"Invalid path - %0"
	    mov     dx,offset oldp2	;Get back to current dir on sec drive
	    doscall CHDIR		;AC000;
	    jmp     quit5

;	$endif				;AC000;
$$IF39:
	mov	dx,offset outfcb
	doscall SETDTA			;AC000; diR FOUND, SET DTA TO TARGET fcb
	mov	dx,offset outfcb
	doscall SEARCHF 		;AC000; FIND FIRST TARGET FILE
	or	al,al			;Find one?
;	$if	NZ			;AC000; ;Yes
	JZ $$IF41
	    print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF
	    fill_name2			;AN000; ;get full path name
	    mov     sublist_11.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF MSG
	    print_msg msgnum_fnf,STDERR ;AN000; ;"File not found - %0"
	    mov     dx,offset oldp2	;Get back to current dir on sec drive
	    doscall CHDIR		;AC000;
	    jmp     quit3		;and get the next source file

;	$endif				;AC000;
$$IF41:
	mov	dx,offset outfcb
	doscall FCBOPEN 		;AC000; OPEN TARGET FILE
	or	al,al			;Was the fcb open ok?

	jnz	ShrViolation		;If fcb open failed, then SHARING ERROR
	mov	si,offset outfcb	;Take this fcb...
	mov	di,offset OpenPath	; and in this area...
	call	MakePathFromfcb 	; make an ASCIIZ path.
	mov	dx,offset OpenPath
	doscall HANDLEOPEN,READONLYACCESS ;AC000; TRY TO OPEN IT WITH READONLY ACCEss
	jc	accessdenied2
	mov	bx,ax			;Put the handle in bx...
	doscall HANDLECLOSE		;AC000; AND CLOSE IT.
	call	RestoreDir
	jmp	filopn			;If successful then continue
accessdenied2:				;Oops, there was an error. AssUME it was Access Denied
	call	RestoreDir
	print_msg msgnum_crlf,STDERR	;AN000; ;dispLAY CRLF
	fill_name2			;AN000; ;get full path name
	mov	sublist_21.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF "Access Denied - %0"
	mov	dx,offset oldp2 	;Get back to current dir on sec drive
	doscall CHDIR			;AC000;
	print_msg msgnum_accessdenied,STDERR ;AN000; ;"Access Denied - %0"
	jmp	quit3			;and get the next source file

ShrViolation:
	call	RestoreDir
	print_msg msgnum_crlf,STDERR	;AN000; ;dispLAY CRLF
	fill_name2			;AN000; ;get full path name
	mov	sublist_13.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF "Sharing violation - %0"
	mov	dx,offset oldp2 	;Get back to current dir on sec drive
	doscall CHDIR			;AC000;
	print_msg msgnum_share,STDERR	;AN000; ;"Sharing violation - %0"
	jmp	quit3			;and get the next source file
filopn:
	mov	word ptr outfcb+14,1	;record size
	xor	ax,ax
	mov	di,offset outfcb+33
	stosw
	stosw
	mov	ax,word ptr infcb+16	;low part of file size
	mov	dx,word ptr infcb+18	;high part
	cmp	ax,word ptr outfcb+16	;are files the same size?
	jne	invsiz			;no, error
	cmp	dx,word ptr outfcb+18
	je	sizok			;yes, ok
invsiz:
	print_msg msgnum_badsiz,STDOUT	;AN000; ;"Files are different sizes"
	jmp	quit3			;tell user sizes are different and process next source file
sizok:
;;(deleted for AN009)	     call    comp_codepage	     ;AN000; ;VERIFY BOTH FILes HAVE THE SAME CODEPAGE
;;(deleted for AN009)	     $if     c			     ;AN000; ;ERROR WITH CODEPAGE
;;(deleted for AN009)		 jmp	 quit3		     ;AN000; ;go on to other files if any
;;(deleted for AN009)	     $endif			     ;AN000;
	mov	dx,offset infcb
	mov	word ptr curfcb,dx	;get fcb's in proper order
	mov	dx,offset outfcb
	mov	word ptr curfcb+2,dx
	mov	word ptr offs,0 	;set constants
	mov	word ptr offs+2,0
	mov	byte ptr cnt,0		;and fall through to process
process:				;**** PREPARE TO COMPARE DATA
	mov	dx,word ptr curfcb+2	;small buffer's file
	cmp	word ptr siz,0		;any data left in large buffer?
	jne	getsec			;yes, use it
	test	byte ptr swt,1		;no, have we reached eof yet?
	jz	large			;no - fill large buffer from other file
	doscall FCBCLOSE		;AC000; CLOSE THE FILE FILLING SMALL BUFFER
	test	byte ptr swt,8		;yes, files are done - did we find eof mark?
;	$if	z			;AC000; ;NO
	JNZ $$IF43
	    print_msg msgnum_eor,STDOUT ;AN000; ;"Eof mark not found"
;	$endif				;AC000;
$$IF43:
	test	byte ptr swt,4		;any compare errors?
;	$if	Z			;AC000;
	JNZ $$IF45
	    print_msg msgnum_ok,STDOUT	;AN000; ;"FILes COMPARE OK"
;	$endif				;AC000;
$$IF45:
	jmp	quit3			;had compare errors - no "ok" msg

large:					;Fill large buffer
	xchg	dx,word ptr curfcb	;AC000; ;switch fcbs' association with buffers
	xchg	dx,word ptr curfcb+2
	call	get			;fill large buffer from currently mounted file
	jmp	process 		;and now fill small buffer from other file
getsec:
	call	getf2			;fill small buffer with 1024 bytes
	sub	siz,cx			;# bytes left in big buffer after this compare
	mov	bp,cx			;save # bytes of compare
	les	di,dword ptr curpos	;current byte in large buffer
	mov	si,offset buf		;current byte in small buffer
comp:
	jcxz	compok			;all done and equal
	repe	cmpsb
	jne	cmp1			;bytes don't match
compok:
	push	ds
	pop	es			;get es back
	mov	curpos,di		;next byte to compare in large buffer
	mov	ax,word ptr offs+2	;low part of bytes compared so far
	add	ax,bp			;increment count of bytes compared
	adc	word ptr offs,0 	;adjust high part
	mov	word ptr offs+2,ax	;save low part
	jmp	process 		;and keep going
cmp1:					;***** FOUND UNEQUAL BYTes
	or	byte ptr swt,4		;indicate had compare error
	dec	si			;point to the bad bytes
	dec	di
	mov	al,[si] 		;bad byte from small buffer
	mov	ah,es:[di]		;bad byte from large buffer
	mov	dx,offset infcb 	;AC000; ;FIND OUT WHICH byte CAME FROM WHICH FILE
					;AN000; ;SO THAT "File 1 = %1" AND "File 2 = %1"
					;AN000; ;MEssAGes WILL BE CORRECT.
	cmp	word ptr curfcb+2,dx	;is first file in small buffer?
;	$if	ne			;AC000; ;NO
	JE $$IF47
	    xchg    ah,al		;no, reverse the bad bytes
;	$endif				;AC000;
$$IF47:
	mov	byte1,al		;AN000; ;SAVE FIRST FILE BAD byte
	mov	byte2,ah		;AN000; ;SAVE SECOND FILE BAD byte
					;AN000; ;COMPUTE offset IN FILE OF BAD BYTes
	mov	bx,word ptr offs	;high part of byte count
	mov	ax,si			;addr of the bad byte in small buffer
	sub	ax,offset buf		;bad byte's offset in this buffer
	add	ax,word ptr offs+2	;offset into file
	adc	bx,0			;adjust high part if needed
	mov	word ptr offp,bx	;AC000; ;SAVE HIGH PART OF offset
	mov	word ptr off_byte+2,bx	;AN000; ;SAVE HIGH PART OF offset
	mov	word ptr offp+2,ax	;AN000; ;SAVE LOW PART OF offset
	mov	word ptr  off_byte,ax	;AN000; ;SAVE LOW PART OF offset
	inc	si			;back to correct position
	inc	di
	push	cx			;save remaining byte count
	push	si			;save next data byte addr

mdone:
	mov	sublist_6.sub_value,offset OFF_byte ;AN000; ;sublist OF MSG DesC
	print_msg msgnum_bad,STDOUT	;AN000; ;"Compare error at offset %1"
	mov	sublist_7.sub_value,offset byte1 ;AN000; ;sublist OF MSG DesC. (ptr TO BAD byte IN FIRST FILE)
	print_msg msgnum_adr,STDOUT	;AN000; ;"File 1 = %1"
	mov	sublist_8.sub_value,offset byte2 ;AN000; ;sublist OF MSG DesC. (ptr TO BAD byte IN SECOND FILE)
	print_msg msgnum_bdr,STDOUT	;AN000; ;"File 2 = %1"
	pop	si			;get regs back
	pop	cx
	inc	byte ptr cnt		;count errors
	cmp	byte ptr cnt,10 	;10 errors yet?
	je	gotten			;yes, further compare is useless
	jmp	comp			;no, go on with following byte
gotten:
	push	ds
	pop	es			;get es back
	print_msg msgnum_tenmsg,STDOUT	;AN000; ;"10 Mismatches - ending compare"

quit3:					;terminate
	mov	byte ptr swt,16 	;say we've found the secondary dir
	cmp	byte ptr path1,0	;is primary file in the drive's current dir?
;	$if	ne			;AN000; NO
	JE $$IF49
	    mov     dx,offset path1	;no,
	    doscall CHDIR		;AC000;
;	$endif				;AC000;
$$IF49:
	mov	dx,offset infcb
	doscall SETDTA			;AC000; ;DTA = SOURCE fcb
	mov	dx,offset fcb
	doscall SEARCHN 		;AC000; ;12H FIND NEXT SOURCE FILE
	or	al,al			;find one?
	jnz	quit4			;no
	jmp	f1ok			;yes, go process it
AccessDenied1:				;Oops, there was an error. AssUME it was Access Denied
	fill_name1 INfcb		;AN000; ;get full path name
	mov	sublist_21.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Access Denied - %0"
	mov	dx,offset msgnum_accessdenied ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY
					;AN000; ;VALUES IN dx,si,di PAssED TO BADFIL CODE
	jmp	short badfil

ShrErr:
	fill_name1 INfcb		;AN000; ;get full path name
	mov	sublist_13.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Sharing violation - %0"
	mov	dx,offset msgnum_SHARE	;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY
					;AN000; ;VALUes IN dx,si,di PAssED TO BADFIL CODE
badfil: 				;assume si = path, di = fcb , dx = MSG DesCRIPTOR
	push	dx
	push	cx
	print_msg msgnum_crlf,STDERR	;AN000; ;dispLAY CRLF
	print_msg msgnum_crlf,STDERR	;AN000; ;dispLAY CRLF
	pop	cx
	pop	dx
;	DISPLAY MSG THAT WAS POINTED TO BY DX
	push	ax
	push	di			;AN003;
	mov	di,dx			;AN003;
	mov	[di].msg_handle,STDERR	;AN003;
	pop	di			;AN003;
	call	sendmsg 		;AC000; ;dispLAY IT
	pop	ax			;AN000;
quit4:					;no more primary files
;;;;;;	 cmp byte ptr path1,0 ;current dir on pri drive?
;;;;;;	 je quit5	 ;yes
	mov	dx,offset oldp1
	doscall CHDIR			;AC000; ;no, restore it now
quit5:
	mov	byte ptr path2,0	;force get of second name - leave this here
	mov	byte ptr swt,0
;	$do				;AC000; ;REPEAT UNTIL A VALID Y/N REspONSE
$$DO51:
	    mov     dx,offset msgnum_nother ;AN000; ;dispLAY (Y/N) MEssAGE
	    push    di			;AN007;  save DI
	    mov     di,dx		;AN007;  DI -> message struct
	    mov     [di].msg_handle,STDERR ;AN007; display to STDERR
	    pop     di			;AN007; restore DI
	    call    sendmsg		;AC000; ;dispLAY IT
	    push    ax			;SAVE REspONSE
	    print_msg msgnum_crlf,STDERR ;AC003; ;dispLAY CRLF
	    print_msg msgnum_crlf,STDOUT ;AC009; ;dispLAY CRLF
	    pop     dx			;AN000; ;GET REspONSE BACK
	    doscall GET_EXT_CNTRY_INFO,YESNO_CHECK ;AC000; ;CHECK REspONSE, dx=REspONSE
	    cmp     al,YES		;AN000; ;Yes REspONSE
;	$leave	e			;AN000; ;LEAVE loop
	JE $$EN51
	    cmp     al,0		;AN000; ;NO REspONSE
;	$leave	e
	JE $$EN51
;	$enddo				;AN000; ;REPEAT UNTIL A VALID Y/N REspONSE
	JMP SHORT $$DO51
$$EN51:
	cmp	al,YES			;AC000; ;ax=0=NO, ax=1=Yes   (CHECK REspONSE)
;	$if	e			;AC000; ;GOT A Yes REspONSE, REPEAT COMP
	JNE $$IF55
	    xor     ax,ax		;AN008; ;AN000; ;CHAR TO USE TO CLEAR BUFFER
	    mov     di,offset path1	;AN000; ;CLEAR OLD PATH, FILE NAMes TO START AGAIN
	    mov     cx,129		;AN000; ;LENGTH OF BUFFER
;	    $do 			;AN000;
$$DO56:
		stosb			;AN000;
;	    $enddo  loop		;AN000;
	    LOOP $$DO56
	    mov     di,offset path2	;AN000; ;CLEAR OLD PATH, FILE NAMes TO START AGAIN
	    mov     cx,129		;AN000; ;LENGTH OF BUFFER
;	    $do 			;AN000;
$$DO58:
		stosb			;AN000;
;	    $enddo  loop		;AN000;
	    LOOP $$DO58
	    mov     clear,1		;set clear
	    jmp     rpt 		;AC000; ;REPEAT COMP
;	$endif				;AC000;
$$IF55:
	ret				;AN000; ;QUIT


;--------------------------------------------
; CONTROL BREAK EXIT CODE (INTERRUPT HANDLER)
;--------------------------------------------
CBExit:
	test	swt2,2			;oldp2 set?
;	$if	nz			;AC000; ;no, restore it now
	JZ $$IF61
	    mov     dx,offset oldp2
	    doscall CHDIR		;AC000; ;no, restore it now
;	$endif				;AC000;
$$IF61:

	test	swt2,1			;oldp1 set?
;	$if	nz			;AC000; ;if it was
	JZ $$IF63
	    mov     dx,offset oldp1
	    doscall CHDIR		;AC000; ;no, restore it now
;	$endif				;AC000;
$$IF63:

;;(deleted for AN009)	     call    restore_cp 	     ;AN000; ;restore the codepage
	mov	al,EXCB 		;AN000; ;errorlevel: control break exit
	doscall RET_FN			;AN000; ;return to DOS with ret code

	int	20h			;AC000; ;if exit didn't work, kill it
main	endp				;AN000;

;------------------------------------------------------------------------------
;  -----------------------------SUBROUTINES----------------------------------
;------------------------------------------------------------------------------


;------------------------------------------------------------------------------
; FINDFS - Finds the last "\" in the path name given. This is done so that the
;	   path and not the filename can be derived from the path name.
;
;   INPUT  - SI = ptr to path name to work on
;   OUTPUT - saves address of last "\" at end of buffer that SI points to.
;	     (this is tricky)
;------------------------------------------------------------------------------
findfs	proc	near			;AN000;
	mov	string_off,si		;AN006;  save addr of string for Check_DBCS_slash
	mov	string_seg,cs		;AN006;
	push	dx			;AN000;
	push	si			;AN000;
	xor	dx,dx			;AN008; ;AN000; ;CLEAR dx IN THE CASE THAT NO "\" IS FOUND
;	$do				;AN000;
$$DO65:
	    lodsb			;AN000; ;GET A CHARACTER
	    cmp     al,0		;AN000; ;AT END OF STRING YET ?
;	$leave	z			;AN000; ;Yes, LEAVE
	JZ $$EN65
	    push    si			;AN006; Check the character in AL == '\'
	    dec     si			;AN006;  and the character in front of
	    call    Check_DBCS_slash	;AN006;  the '\' is not DBCS.
	    pop     si			;AN006;

;	    $if     z			;AN000; ;Yes, SAVE ADDR OF IT IN dx
	    JNZ $$IF67
		mov	dx,si		;AN000;
		dec	dx		;AN000;
;	    $endif			;AN000;
$$IF67:
;	$enddo				;AN000;
	JMP SHORT $$DO65
$$EN65:
	pop	si			;AN000;
	mov	[si+128],dx		;AN000; ;SAVE ADDR OF LAST "\" IN THE LAST TWO BYTes OF PATH
	pop	dx			;AN000;
	ret				;AN000;
findfs	endp				;AN000;


;------------------------------------------------------------------------------
; GETNAM - Inputs a filename from STDIN to be used as either the first or second
;	   parameter for COMP.
;
;   INPUT  - PARM_COUNT = ordinal number for parser
;	     DX = ptr to msg descriptor of message to display
;	     BX = ptr to FCB of file
;	     SI = ptr to FCB structure
;------------------------------------------------------------------------------
getnam	proc	near
	mov	input_buf,INPUT_LEN	;AN000; ;PUT LENGTH OF BUFFER AS FIRST byte OF BUFFER
	mov	di,dx			;AN000; ;FILL IN offset OF INPUT BUFFER IN MSG DesC.
	mov	[di].msg_input, offset input_buf ;AN000; ;ptr TO INPUT BUFFER
	mov	[di].msg_handle, STDERR
	push	ax			;AN000;
	call	sendmsg 		;AC000; ;dispLAY MEssAGE, GET BUFFERED INPUT
	pop	ax			;AN000;
	xor	ch,ch			;AN000; ;CLEAR HIGH byte OF cx
	mov	cl,input_len		;AN000; ;CL = LENGTH OF INPUT BUFFER
					;get offset into input buffer (to skip length word)
	mov	current_parm,offset INPUT_BUF+2 ;AN000; ;CURRENT_PARM = offset OF INPUT BUFFER
	mov	ordinal,ZERO_PARM_CT	;AN000; ;TELL PARSER THAT THIS IS FIRST PARAMETER (ONLY ONE)
	call	parser			;PUT NEW STRING AT WHERE di POINTS TO
	ret				;then go back
getnam	endp				;AC000;


;------------------------------------------------------------------------------
; FINDPATH - Check if path is a directory. If yes, then CHDIR to it and set the
;	     FCB to ????????.???. If no, check for "\". If no "\", then assume
;	     we are in the correct directory and set FCB to ????????.??? if blank.
;	     If "\" is found, then strip last name off path into FCBYTE (?'s if
;	     nothing follows "\") and try to find the directory again.
;
;   INPUT  - SI = ptr to path string
;	     DI = ptr to FCB (drive byte is valid)
;   OUTPUT - if path found then set ZERO flag and CHDIR to directory and FCB set.
;	     else FCB set and reset ZERO flag.
;------------------------------------------------------------------------------
findpath proc	near
	mov	dl,[di] 		;drive number from fcb
	push	di
	push	si
	mov	di,si
	sub	di,67			;where to put current dir for the drive
	mov	al,dl			;AN005; ;get drive number
	add	al,64			;AN005; ;convert to ascii letter
	stosb				;AN005;
	mov	al,':'			;AN005;
	stosb				;AN005;
	mov	al,pathchar		;get path separator
	stosb				;and put in beginning of path
	mov	si,di
	doscall CURDIR			;AC000; ;GET DRIVE'S CURRENT diR
	cmp	di,offset oldp1+3	;See if pri cur dir is set up
;	$if	e			;AC000;
	JNE $$IF70
	    or	    swt2,1
;	$endif				;AC000;
$$IF70:
	cmp	di,offset oldp2+3	;See if sec cur dir is set up
;	$if	e			;AC000;
	JNE $$IF72
	    or	    swt2,2
;	$endif				;AC000;
$$IF72:
	pop	si			;path string
	pop	di			;fcb
	cmp	byte ptr [si],0 	;is there a path?
	jne	fp3			;yes
fp0:
	cmp	byte ptr [di+1]," "	;no, is there a name in the fcb?
	jne	fp2			;yes, use current dir
fp1:
	call	setq			;no, set it to ????????.???
fp2:
	cmp	al,al			;force eq on return
	ret
fp3:					;there's a path
	mov	dx,si			;path
	doscall CHDIR			;AC000; ;see if it's a dir
	jnc	fp1			;yes, set fcb to ?'s - path found and set
	mov	bx,[si+128]		;no - get last \ in string
	or	bx,bx			;is there a \?
	jnz	fp4			;yes, go strip off last name
	mov	byte ptr [si],0 	;no, there's only 1 name in path - must be filename
	jmp	short fp0		;go use current dir
fp4:
	call	backoff 		;strip last name off line into fcb
	mov	dx,si
	doscall CHDIR			;AC000; ;noword ptr  is result line a valid path?
	jnc	fp2			;yes, fcb and path are set
fp5:
	cmp	ax,1234h		;no, pass back error - path has first part of name,
	ret				;remainder is in fcb
findpath endp				;AN000;


;------------------------------------------------------------------------------
; BACKOFF - Removes the last name of a path and puts it into an FCB. Assumes at
;	    least one "\" in path. If no name is found then set the FCB to
;	    ????????.??? and
;
;   INPUT  - SI = ptr to path string.
;	     DI = ptr to FCB to format.
;   OUTPUT -
;------------------------------------------------------------------------------
backoff proc	near
	push	si
	mov	bx,[si+128]		;address of last \ in path
	cmp	byte ptr [si+1],":"	;AN002;
;	$if	e			;AN002;
	JNE $$IF74
	    add     si,2		;char following d: in path name
;	$endif				;AN002;
$$IF74:
	cmp	si,bx			;is it the only \ and is it at beg of line?
	mov	si,bx
;	$if	e			;AC000; ;Yes
	JNE $$IF76
	    inc     bx			;yes, going to root - leave \ alone
;	$endif				;AC000;
$$IF76:
	inc	si			;char following \
	cmp	byte ptr [si],0 	;are there any?
	jne	bo4			;yes
	call	setq			;no, use ????????.??? in root
	jmp	short bo3		;AC008;
bo4:
	push	di
					;AC000; ;ds:si=POINTER TO COMMAND LINE TO PARSE
					;AC000; ;es:di=POINTER TO UNOPENED fcb
					;AC000; ;AL-BIT VALUE CONTROLS PARsiNG
	doscall PARSE_FILENAME,02h	;AC000; ;PARSE LAST NAME ON LINE INTO fcb, LEAVE DRIVE byte ALONE
	pop	di
	cmp	byte ptr [di+1]," "	;is there a file name?
;	$if	ne			;AC000; ;Yes, TRUNCATE PATH AND LEAVE
	JE $$IF78
bo3:
	    mov     byte ptr [bx],0	;truncate the path name
	    pop     si
;	$else				;AC000; ;siNCE NO FILE NAME,
	JMP SHORT $$EN78
$$IF78:
	    pop     si			;no, restore si
	    pop     ax			;strip return to findpath
	    call    setq		;fill fcb with ?'s
	    cmp     ax,1234h		;AN000; ;SET ERROR retURN
;	$endif				;AC000;
$$EN78:
	ret
backoff endp				;AN000;


;------------------------------------------------------------------------------
; SETQ - Set an FCB filename field to ????????.???
;
;   INPUT  - DI = ptr to FCB
;   OUTPUT - FCB is changed.
;------------------------------------------------------------------------------
setq	proc	near
					;di = ^ fcb
	push	di
	mov	al,"?"
	mov	cx,11
	inc	di			;point to filename
;	$do				;AC000;
$$DO81:
	    stosb
;	$enddo	loop			;AC000;
	LOOP $$DO81
	pop	di
	ret
setq	endp				;AC000;


;------------------------------------------------------------------------------
; GET - Fill large buffer
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
get	proc	near
	push	dx			;save fcb address
	mov	ds,buf2 		;point to large buffer
	xor	dx,dx
	doscall SETDTA			;AC000; ;SET DTA TO LARGE BUFFER
	push	cs
	pop	ds			;get ds back
	pop	dx			;and get fcb addr back
	mov	cx,word ptr mem 	;# bytes of avail mem in large buffer
	doscall FCBRNDBLKREAD		;AC000; ;FILL LARGE BUFFER
	mov	siz,cx			;# bytes we read
	mov	word ptr curpos,0	;current byte position offset in large buffer
	or	al,al			;get eof?
;	$if	nz			;AC000; ;Yes, AT EOF
	JZ $$IF83
	    call    fileend		;AC000;
;	$endif				;AC000;
$$IF83:
	ret				;No, keep on going
get	endp				;AC000;


;------------------------------------------------------------------------------
; FILEEND - Check for EOF char on last read into large buffer (?)
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
fileend proc	near
	or	byte ptr swt,1		;yes, flag it
	mov	bx,cx			;# bytes just read
	mov	ds,buf2
	cmp	byte ptr [bx-1],26	;is the last char of file an eof?
	push	cs
	pop	ds
;	$if	e			;AC000; ;Yes
	JNE $$IF85
	    or	    byte ptr swt,8	;yes, say we found the eof
;	$endif				;AC000;
$$IF85:
	doscall FCBCLOSE		;AC000; ;Close the file filling large buffer
	ret
fileend endp				;AN000;


;------------------------------------------------------------------------------
; GETF2 -  Read 8 sectors from file that FCB points to.
;
;   INPUT  - DX = ptr to FCB
;   OUTPUT - fills small buffer
;------------------------------------------------------------------------------
getf2	proc	near
					;fill small buffer from fcb at [dx]
	push	dx
	mov	dx,offset buf		;small buffer addr
	doscall SETDTA			;AC000; ;SET THE DTA
	pop	dx
	mov	cx,4096 		;ask for 8 sectors
	doscall FCBRNDBLKREAD		;AC000; ;GET THE DATA
	ret
getf2	endp				;AN000;


;------------------------------------------------------------------------------
; FILL_N - This routine fills the buffer NAME1 or NAME2 with the full path name
;	   of the corresponding file.
;
;   INPUT  - DX = ptr to buffer to put full path name in
;	     DI = ptr to FCB to get drive letter,filename,extension from
;	     SI = ptr to PATH1 or PATH2 depending on whether first or second file
;   OUTPUT -
;------------------------------------------------------------------------------
fill_n	proc	near
	push	ax			;AN000;
	push	cx			;AN000;
	mov	string_off,dx		;AN006; pass whole string to Check_DBCS_slash
	mov	string_seg,cs		;AN006;
;get drive letter & colon		;AN000;
	xchg	dx,si			;AN000; ;make dx=fcb ptr, si=buffer ptr
	mov	al,[di] 		;AN000; ;drive byte from fcb
	inc	di			;AN000; ;point to filename
	add	al,64			;AN000; ;drive to ascii
	mov	[si],al 		;AN000; ;save letter in string
	inc	si			;AN000; ;increment ptr
	mov	byte ptr [si],":"	;AN000; ;add colon to drive letter
	inc	si			;AN000;
	xchg	dx,si			;AN000;
;get full path				;AN000;
	xchg	dx,di			;AN000;
	cmp	byte ptr [si],0 	;AN000; ;is there a path?
;	$if	ne			;AN000; ;Yes
	JE $$IF87
	    cmp     byte ptr [si+1],':' ;is thera a drive letter ?
;	    $if     e
	    JNE $$IF88
		add	si,2		;AN000; ;yes, skip drive id in path
;	    $endif
$$IF88:
;	    $do 			;AC000;
$$DO90:
		lodsb			;AN000; ;get a path char
		or	al,al		;AN000; ;end of path?
;	    $leave  Z			;AN000; ;Yes
	    JZ $$EN90
		stosb			;AN000; ;copy character
;	    $enddo			;AC000;
	    JMP SHORT $$DO90
$$EN90:
	    push    si			;AN006; Check the character in AL == '\'
	    mov     si,di		;AN006;  and the character in front of
	    dec     si			;AN006;  the '\' is not DBCS.
	    call    Check_DBCS_slash	;AN006;
	    pop     si			;AN006;

;	    $if     NE			;AC000; ;NO
	    JE $$IF93
		mov	al,"\"		;AC000; ;no, display separator ahead of filename
		stosb			;AN000;
;	    $endif			;AC000;
$$IF93:
;	$endif				;AC000;
$$IF87:
;get filename				;AN000;
	xchg	dx,si			;AC000; ;dx=path1 or path2, si=ptr buffer, di=ptr fcb
	mov	cx,8			;AN000;
;	$do				;AC000;
$$DO96:
	    lodsb			;AC000; ;display filename
	    cmp     al," "		;AC000; ;Is it end of filename
;	$leave	e			;AC000; ;Yes, GET EXTENsiON
	JE $$EN96
	    stosb			;AN000;
;	$enddo	loop			;AC000; ;GET MORE CHARS, IF ANY
	LOOP $$DO96
$$EN96:
	and	cx,cx			;AC008;
;	$if	ne
	JE $$IF99
	    dec     cx			;AC000; ;# of spaces left to skip in filename
;	    $do 			;AC000; ;step thru spaces to get to file extension
$$DO100:
		inc	si		;AN000;
;	    $enddo  loop		;AC000; ;until cx=0
	    LOOP $$DO100
;	$endif
$$IF99:
;get filename extension 		;AN000;
	cmp	byte ptr [si]," "	;AC000; ;is there an extension?
;	$if	ne			;AC000; ;Yes, DO PERIOD
	JE $$IF103
	    mov     al,"."		;AN000;
	    stosb			;AN000;
	    mov     cx,3		;AN000;
;	    $do 			;AC000;
$$DO104:
		lodsb			;AC000; ;display extension
		cmp	al," "		;AC000; ;is it end of extension?
;	    $leave  e			;AC000; ;Yes
	    JE $$EN104
		stosb			;AN000;
;	    $enddo  loop		;AC000;
	    LOOP $$DO104
$$EN104:
;	$endif				;AC000; ;EXTENsiON?
$$IF103:
	mov	al,0			;AN000;
	stosb				;AC000; ;end of string marker
	xchg	dx,si			;AN000;
	xchg	dx,di			;AN000;
	pop	cx			;AN000;
	pop	ax			;AN000;
	ret
fill_n	endp				;AN000;


;------------------------------------------------------------------------------
; MAKEPATHFROMFCB - Creates an ASCIIZ path at DI from the FCB pointed to by SI.
;
;   INPUT  - SI = ptr to FCB
;	     DI = buffer for path name to be stored.
;   OUTPUT -
;------------------------------------------------------------------------------
MakePathFromFcb proc near
	push	si			;Save fcb address
	mov	al,byte ptr [si]	;Get drive letter from fcb (0=A,1=B,...)
	add	al,64			;Convert it to ASCII
	stosb				;Store it in the PATH
	mov	al,":"			;Put a drive separator
	stosb				; in the PATH.
	inc	si
	mov	cx,8			;Copy [1..8] bytes
					; GET FILENAME
;	$do				;AC000;
$$DO108:
	    movsb			;Move the char from the fcb
	    cmp     byte ptr [si]," "	;Is the next char a blank ?
;	$leave	e			;AC000; ;Yes, NO MORE CHARS IN FILENAME
	JE $$EN108
;	$enddo	loop			;AC000; ;NO, GET NEXT CHAR, IF ANY
	LOOP $$DO108
$$EN108:
					; InsertPeriod
	mov	byte ptr [di],"."	;Stick a period in there...
	inc	di			; and increment the pointer
	mov	cx,3			;Copy [0..3] bytes...
	pop	si			; from the fcb's
	add	si,9			; extension area
;	$do				;AC000;
$$DO111:
	    cmp     byte ptr [si]," "	;Is the next char a blank?
;	$leave	e			;AC000; ;Yes, THEN WE ARE DONE
	JE $$EN111
	    movsb			; No, move it
;	$enddo	loop			;AC000; ;AND GET THE NEXT ONE, IF ANY
	LOOP $$DO111
$$EN111:
	mov	al,00
	stosb				;Copy in a byte of Hex 0
	ret
MakePathFromFcb endp


;------------------------------------------------------------------------------
; RESTOREDIR - Do a CHDIR to the original directory this program started in.
;
;   INPUT  - OLDP2 = path string of original directory (for target filespec)
;	     PATH2 = path string of target filespec.
;   OUTPUT - changes the current directory
;------------------------------------------------------------------------------
RestoreDir proc near
	cmp	byte ptr path2,0	;working with current dir on secondary file?
;	$if	ne			;AC000; ;NO,
	JE $$IF114
	    push    ax			;restore old current directory
	    mov     dx,offset oldp2
	    doscall CHDIR		;AC000;
	    pop     ax
;	$endif				;AC000;
$$IF114:
	ret
RestoreDir endp 			;AN000;


;------------------------------------------------------------------------------
; INIT_CP - To permit "COMP" to open the first and second files regardless of
;	    the system codepage, and to avoid any codepage mismatch critical
;	    error from occurring from the open, we temporarily suspend codepage
;	    support. It will be restored at the end of COMP.
;
;   INPUT  -
;   OUTPUT - CPSW_ORIG byte will have the CPSW bit set on if cpsw = on
;------------------------------------------------------------------------------
init_cp proc	near			;AN000;
	public	init_cp 		;AN000;

	doscall CPSW_CHECK,GET_CPSW_STATE ;AN000; ;IS CODEPAGE SUPPORT LOADED
	and	dl,dl			;AC008; ;AN000;
;	$if	ne			;AN000; ;IF CPSW IS LOADED
	JE $$IF116
	    or	    cpsw_orig,CPSW	;AN000; ;SET FLAG TO INdiCATE CPSW=ON
	    mov     dl,CPSW_OFF 	;AN000; ; TO CPSW=OFF
	    doscall CPSW_CHECK,SET_CPSW_STATE ;AN000; ;SET CPSW=OFF
;	$endif				;AN000; ;CPSW LOADED?
$$IF116:
	ret				;AN000; ;retURN TO callER
init_cp endp				;AN000;


;------------------------------------------------------------------------------
; RESTORE_CP - Restore chcp status (codepage support to original values)
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
restore_cp proc near			;AN000;
	public	restore_cp		;AN000;

	test	cpsw_orig,CPSW		;AN000; ;WAS CPSW ON WHEN WE STARTED?
;	$if	nz			;AN000; ;IF CPSW WAS ON
	JZ $$IF118
	    mov     dl,CPSW_ON		;AN000; ; TO CPSW=ON
	    doscall CPSW_CHECK,SET_CPSW_STATE ;AN000; ;SET CPSW=ON
;	$endif				;AN000; ;CPSW WAS ON?
$$IF118:
	ret				;AN000; ;retURN TO callER
restore_cp endp 			;AN000;


;------------------------------------------------------------------------------
; COMP_CODEPAGE - If chcp=on, verify that the codepage of the two files agree.
;
;   INPUT  - PATH1 has the asciiz of the first path\filename
;	     PATH2 has the asciiz of the second path\filename
;   OUTPUT -
;------------------------------------------------------------------------------
comp_codepage proc near 		;AN000;
	public	comp_codepage		;AN000;

	test	cpsw_orig,CPSW		;AN000; ;WAS CPSW=ON WHEN WE STARTED?
;	$if	nz			;AN000; ;IF CPSW IS LOADED
	JZ $$IF120
	    fill_name1 infcb		;AN000; ;get full path name
	    mov     cur_name,offset name1 ;AN000; ;PAss INPUTED FILENAME OF FIRST FILE
	    call    getcp		;AN000; ;GET CODEPAGE OF FIRST FILE
	    mov     ax,qlist_ea.ea_value ;AC001; ;SAVE	ITS CODEPAGE
	    push    ax			;AN000; ;ON THE STACK
	    fill_name2			;AN000; ;get full path name
	    mov     cur_name,offset name2 ;AN000; ;PAss INPUTED FILENAME OF SECOND FILE
	    call    getcp		;AN000; ;GET CODEPAGE OF SECOND FILE
	    pop     ax			;AN000; ;GET FIRST FILE CODEPAGE
	    mov     bx,qlist_ea.ea_value ;AC001; ;GET SECOND FILE CODEPAGE
	    and     ax,ax		;AC008; ;AN000; ;COMPARE TO ZERO CP
;	    $if     ne			;AN000; ;FIRST FILE HAS NON-ZERO CODE PAGE
	    JE $$IF121
		and	bx,bx		;AC008; ;AN000; ;COMPARE TO ZERO CP
;		$if	ne		;AN000; ;SECOND FILE HAS NON-ZERO CODE PAGE
		JE $$IF122
		    cmp     ax,bx	;AN000; ;COMPARE CP OF 1ST WITH CP OF 2ND
;		    $if     e		;AN000; ;CP ARE ALIKE
		    JNE $$IF123
			clc		;AN000; ;INdiCATE MATCHING CP
;		    $else		;AN000; ;siNCE CP ARE NOT ALIKE
		    JMP SHORT $$EN123
$$IF123:
			stc		;AN000; ;INdiCATE NON-MATCHING CP
;		    $endif		;AN000; ;CP ARE ALIKE
$$EN123:
;		$else			;AN000; ;siNCE 2ND HAS NO CODE PAGE
		JMP SHORT $$EN122
$$IF122:
		    stc 		;AN000; ;INdiCATE NON-MATCHING CP
;		$endif			;AN000; ;2ND FILE HAS CODE PAGE?
$$EN122:
;	    $else			;AN000; ;siNCE 1ST FILE HAS NO CODE PAGE
	    JMP SHORT $$EN121
$$IF121:
		and	bx,bx		;AC008; ;AN000; ;COMPARE TO ZERO CP
;		$if	ne		;AN000; ;2ND FILE HAS NO CODE PAGE
		JE $$IF129
		    stc 		;AN000; ;INdiCATE NON-MATCHING CP
;		$else			;AN000; ;siNCE 2ND FILE HAS NO CODE PAGE EITHER
		JMP SHORT $$EN129
$$IF129:
		    clc 		;AN000; ;INdiCATE OK, NO CP TO COMPARE
;		$endif			;AN000; ;2ND FILE HAS CP?
$$EN129:
;	    $endif			;AN000; ;1ST FILE HAS CODE PAGE?
$$EN121:
;	    $if     c			;AN000; ;IF CARRY
	    JNC $$IF133
		print_msg msgnum_cp_mismatch,STDERR ;AN000; ;"CODE PAGE MISMATCH"
		stc			;AN000; ;PAss INdiCATOR OF NON-MATCH CP
;	    $endif			;AN000;
$$IF133:
;	$else				;AN000; ;siNCE CODE PAGE NOT ACTIVE
	JMP SHORT $$EN120
$$IF120:
	    clc 			;AN000; ;PAss INdiCTOR OF OK CP
;	$endif				;AN000; ;CODEPAGE LOADED?
$$EN120:
	ret				;AN000; ;retURN TO callER
comp_codepage endp			;AN000;


;------------------------------------------------------------------------------
; GETCP - Does an extended open, gets codepage #, closes file.
;
;  INPUT  - AX = ptr to real filename to open
;	    CUR_NAME = ptr to inputed filename to open (display this if error)
;  OUTPUT -
;------------------------------------------------------------------------------
getcp	proc	near			;AN000;
	public	getcp			;AN000;

;	SET   UP INPUTS TO EXTENDED OPEN:
;	REQUesT FUNCTIONS: READ,COMPATABILITY,NO INHERIT,INT 24H ret ERR,
;	NO    COMMIT, NO ATTR, FAIL IF NOT EXIST, OPEN IF EXIST
;	NO    CODE PAGE CHECK

	mov	bx,OPEN_MODE		;AN000; ;SET READ MODE TO CORRECT VALUE FOR EXTENDED OPEN
	xor	cx,cx			;AC008; ;AN000; ;NO ATTRIBUTE TO WORRY ABOUT (00H = NO_ATTR)
	mov	dx,FUNC_CNTRL		;AN000; ;SET FUNCTION CONTROL FOR EXTENDED OPEN
	mov	di,offset parm_list	;AN000; ;PAss offset TO PARM_LIST
	mov	si,cur_name		;AN000; ;ptr to name of file to open
	doscall EXT_OPEN,EXT_OPEN_RD	;AN000;
	mov	handle,ax		;AN000; ;SAVE HANDLE
;	$if	c			;AN000; ;IF ERROR
	JNC $$IF137
	    call    exterr		;AN000; ;GET EXTENDED ERROR, SHOW MSG
;	$else				;AN000; ;siNCE NO ERROR ON OPEN
	JMP SHORT $$EN137
$$IF137:
					;AN000; ;GET_EXT_ATTR_LIST (5702), GET
					;AN000; ;EXTENDED ATTR. TO LIST
	    mov     bx,handle		;AN000; ;bx=HANDLE
	    mov     di,offset qlist	;AC001; ;es:di=QLIST
	    mov     cx,13		;AN001; ;size of QLIST returned
	    mov     si,offset querylist ;AN001; ;get code page attr. only
	    doscall EXT_ATTR_LIST,GET_EXT_ATTR_LIST ;AN000;
					;AN000; ;CY SET IF ERROR
;	    $if     c			;AN000; ;IF ERROR
	    JNC $$IF139
		call	exterr		;AN000; ;GET EXTENDED ERROR, SHOW MSG
;	    $endif			;AN000;
$$IF139:
	    mov     bx,handle		;AN000; ;PAss HANDLE TO CLOSE FILE
	    doscall HANDLECLOSE 	;AN000; ;CLOSE THIS EXTENDED OPEN OF THE FILE
;	$endif				;AN000;
$$EN137:
	ret				;AN000; ;retURN TO callER
getcp	endp				;AN000;


;------------------------------------------------------------------------------
; EXTERR - Displays the extended error message and filename.
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
exterr	proc	near			;AN000;
	public	exterr			;AN000;

	xor	bx,bx			;AC008; ;AN000; ;bx = MINOR VERsiON # OF DOS
	doscall EXTERROR		;AN000; ;GET EXTENDED ERROR
	mov	msgnum_exterr.msg_num,ax ;AN000; ;PUT EXT. ERROR # IN MSG DesCRIPTOR STRUCT.
	mov	msgnum_exterr.msg_sublist,offset sublist_EXTERR ;AN000; ;ptr TO sublist
	mov	msgnum_exterr.msg_count,NO_SUBS ;AN000; ;ONE sublist WILL BE USED.
	mov	ax,cur_name		;AN000; ;GET CURRENT FILENAME
	mov	sublist_exterr.sub_value,ax ;AN000; ;FILL IN offset OF FILENAME TEXT
	print_msg msgnum_exterr,STDERR	;AN000; ;dispLAY EXTENDED ERROR MEssAGE

	mov	exitfl,EXVER		;AN000; ;INdiCATE AN ERROR
	ret				;AN000;
exterr	endp				;AN000;


;------------------------------------------------------------------------------
; GET_DBCS_VECTOR - Get the DOS double byte character table segment and offset
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
bufferDB db	6 dup(0)

get_dbcs_vector proc near		;AN006;
	push	es			;AN006;
	push	di			;AN006;
	push	ax			;AN006;
	push	bx			;AN006;
	push	cx			;AN006;
	push	dx			;AN006;
;
	mov	ax,cs			;AN006; ;segment of return buffer
	mov	es,ax			;AN006;
	mov	di,offset bufferDB	;AN006; ;offset of return buffer
	mov	ah,65h			;AN006; ;get extended country info
	mov	al,07h			;AN006; ;get DBCS environment table
	mov	bx,0ffffh		;AN006; ;use active code page
	mov	cx,5			;AN006; ;number of bytes returned
	mov	dx,0ffffh		;AN006; ;default country ID
	int	21h			;AN006; ;DOS function call,vector returned
					;AN006; ; in ES:DI
	inc	di			;AN006; ;skip over id byte returned
	mov	ax,word ptr es:[di]	;AN006; ;get offset of DBCS table
	mov	cs:dbcs_off,ax		;AN006; ;save it
;
	add	di,2			;AN006; ;skip over offset to get segment
	mov	bx,word ptr es:[di]	;AN006; ;get segment of DBCS table
	mov	cs:dbcs_seg,bx		;AN006; ;save it
;
	mov	di,ax			;AN006; ;Point to DBCS table to get length
	mov	es,bx			;AN006;
	mov	ax,word ptr es:[di]	;AN006;
	mov	cs:dbcs_len,ax		;AN006;
	add	cs:dbcs_off,2		;AN006; ;change offset to point to table
;
	pop	dx			;AN006;
	pop	cx			;AN006;
	pop	bx			;AN006;
	pop	ax			;AN006;
	pop	di			;AN006;
	pop	es			;AN006;
;
	ret				;AN006;
get_dbcs_vector endp			;AN006;


;------------------------------------------------------------------------------
;  Check_DBCS_slash - given SI pointing to string, check if the character SI
;		      points to is a slash and that the preceeding character
;		      is not DBCS.
;
;   INPUT  - SI = ptr to possible slash character
;	     STRING_SEG:STRING_OFF points to the beginning of string
;   OUTPUT - set ZERO flag if [SI-1] != DBCS character AND [SI] == '\',
;	     else resets ZERO flag.
;------------------------------------------------------------------------------
Check_DBCS_slash proc near		;AN006;
	push	es			;AN006;
	push	di			;AN006;
	push	si			;AN006;
	push	ax			;AN006;
	push	bx			;AN006;
	push	cx			;AN006;
;
	cmp	byte ptr [si],'\'	;AN006; ;Is character a slash ?
	jne	reset_zero		;AN006; ;no, quit.
;
	cld				;AN006;
	mov	cx,128			;AN006; ;clear darray to zeroes
	mov	di,offset dstring	;AN006; ;dstring will correspond to the string pointed to by
	mov	al,00			;AN006; ;string_seg:string_off and for each character in the string
	rep	stosb			;AN006; ;that is DBCS a corresponding "D" will be stored in dstring.
					;AN006; ;example:    string : [c:\�\�\ ]
					;	     dstring: [   D D  ] (there are two DBCS characters)
;
	sub	si,string_off		;AN006; ;si will equal length of string from beginning to character that may be a slash.
	and	si,si			;AC008; ;AN006; ;is character in first position ?
	jbe	set_zero		;AN006; ;yes, quit.
	mov	cx,si			;AN006; ;cx will contain the count of characters to check DBCS status of.
	push	cx			;AN006; ;save for later
	mov	si,string_off		;AN006; ;si points to beginning of string.
;
	mov	bx,cs:dbcs_seg		;AN006; ;ES:SI -> DOS dbcs table (segment)
	mov	es,bx			;AN006;
;
	mov	bx,offset dstring	;AN006; ;bx points to dstring
DB_loop:				;AN006;
	mov	di,cs:dbcs_off		;AN006; ;ES:SI -> DOS dbcs table (offset)
	lodsb				;AN006; ;get character into al
;
; Two consecutive 00 bytes signifies end of table
;

is_loop:				;AN006;
	cmp	word ptr es:[di],00h	;AN006; ;Check for two consecutive 00 bytes
	jne	is_next1		;AN006; ;no, continue
	jmp	short DB_inc		;AC008; ;AN006; ;yes, found them, quit
;
; Check if byte is within range values of DOS dbcs table
;
is_next1:				;AN006;
	cmp	al,byte ptr es:[di]	;AN006; ;is byte >= first byte in range?
	jae	is_next2		;AN006; ;yes, continue
	jmp	short is_again		;AC008; ;AN006; ;no, loop again
is_next2:				;AN006;
	cmp	al,byte ptr es:[di+1]	;AN006; ;is byte <= last byte in range?
	jbe	is_found		;AN006; ;yes, found a lead byte of db char
is_again:				;AN006;
	add	di,2			;AN006; ;no, increment ptr to next range
	jmp	is_loop 		;AN006;
is_found:				;AN006;
	mov	byte ptr ds:[bx],'D'	;AN006; ;byte is lead byte of db char, set [BX] = 'D'
	inc	bx			;AN006; ;skip over second part of double byte char.
	inc	si			;AN006; ; "     "    "     "   "    "	  "     "
DB_inc: 				;AN006;
	inc	bx			;AN006;
	dec	cx			;AN006;
	and	cx,cx			;AC008; ;AN006; ;are we done check characters for DBCS
	jne	DB_loop 		;AN006; ;no, check next character
;
; end of loop
;
	pop	cx			;AN006; ;restore offset into string
	dec	cx			;AN006; ;check character preceeding slah to see if it is DBCS
	mov	si,offset dstring	;AN006; ;get beginning of string
	add	si,cx			;AN006; ;si now point to char preceeding slash
	cmp	byte ptr [si],'D'	;AN006; ;Is it DBCS ?
	je	reset_zero		;AN006; ;yes
set_zero:				;AN006;
	cmp	al,al			;AN006; ;set ZERO flag
	jmp	short is_bye		;AC008; ;AN006;
reset_zero:				;AN006;
	mov	bx,01h			;AN006;
	cmp	bx,0ffh 		;AN006; ;reset ZERO flag
is_bye: 				;AN006;
	pop	cx			;AN006;
	pop	bx			;AN006;
	pop	ax			;AN006;
	pop	si			;AN006;
	pop	di			;AN006;
	pop	es			;AN006;
;					;AN006;
	ret				;AN006;
Check_DBCS_slash endp			;AN006;


;------------------------------------------------------------------------------
; SENDMSG - Transfer msg descriptor info to registers and call the msg retriever
;
;   INPUT  - DX = ptr to msg descriptor for this message
;   OUTPUT - DX, AX altered, others ok.
;------------------------------------------------------------------------------
sendmsg proc	near			;AN000;
	public	sendmsg 		;AN000;

	push	bx			;AN000; ;SAVE callER'S REGS
	push	cx			;AN000;
	push	si			;AN000;
	push	di			;AN000;
	mov	di,dx			;AN000; ;PUT ptr TO MSG DesC. IN di
	mov	dx,[di].msg_input	;AN000; ;GET ptr TO INPUT BUFFER AND PUT IN dx
	push	dx			;AN000; ;SAVE IT ON THE STACK FOR LATER

;		 PAss PARMS TO MEssAGE HANDLER IN
;		 THE APPROPRIATE REGISTERS IT NEEds.
	mov	ax,[di].msg_num 	;AN000; ;MEssAGE NUMBER
	mov	bx,[di].msg_handle	;AN000; ;HANDLE TO dispLAY TO
	mov	si,[di].msg_sublist	;AN000; ;offset IN es: OF sublist, OR 0 IF NONE
	mov	cx,[di].msg_count	;AN000; ;NUMBER OF %PARMS, 0 IF NONE
	mov	dx,[di].msg_class	;AN000; ;CLAss IN HIGH byte, INPUT FUNCTION IN LOW
	pop	di			;AN000; ;GET OLD dx VALUE (ptr TO INPUT BUFFER)
	call	sysdispmsg		;AN000; ;dispLAY THE MEssAGE
;	$if	c			;AN000; ;IF THERE IS A PROBLEM
	JNC $$IF142
					;AN000; ;ax=EXTENDED ERROR NUMBER
	    mov     bx,STDERR		;AN000; ;HANDLE TO dispLAY TO
	    xor     si,si		;AC008; ;AN000; ;offset IN es: OF sublist, OR 0 IF NONE
	    xor     cx,cx		;AC008; ;AN000; ;NUMBER OF %PARMS, 0 IF NONE
	    mov     dh,CLASS_1		;AN000; ;CLAss IN HIGH byte, INPUT FUNCTION IN LOW
	    call    sysdispmsg		;AN000; ;TRY TO SAY WHAT HAPPENED
	    stc 			;AN000; ;REPORT PROBLEM
;	$endif				;AN000; ;PROBLEM WITH dispLAY?
$$IF142:

	pop	di			;AN000; ;ResTORE callER'S REGISTERS
	pop	si			;AN000;
	pop	cx			;AN000;
	pop	bx			;AN000;

	ret				;AN000;
sendmsg endp				;AN000;



;------FIND BOUNDARY--------------
	if	($-cseg) mod 16 	;AN000; ;IF NOT ALREADY ON 16 byte BOUNDARY
	    org     ($-cseg)+16-(($-cseg) mod 16) ;AN000; ;ADJUST TO 16 byte BOUNDARY
	endif				;AN000;
;---------------------------------

buf	label	byte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;ALL CODE BELOW THIS POINT WILL BE OVERLAID WITH DATA BEING COMPARED;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;------------------------------------------------------------------------------
; SETFILL - sets the fill_seg, fill_off with the current seg_id, offset in
;	    sublists of msg.
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
setfill proc	near			;AN000;
	public	setfill 		;AN000;
	push	ax			;AN000; ;save registers
	mov	ax,cs			;AN000; ;get the code segment
	mov	sublist_6.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_7.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_8.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_11.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_12.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_13.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_19a.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_19b.sub_value_seg,ax ;AN000; ;save seg_id in sublist
	mov	sublist_24.sub_value_seg,ax ;AN000; ;FILL IN CODE SEGMENT
	mov	sublist_exterr.sub_value_seg,ax ;AN000; ;FILL IN CODE SEGMENT
	pop	ax			;AN000; ; GET OLD VALUE IN ax BACK
	ret				;AN000;
setfill endp				;AN000;


;------------------------------------------------------------------------------
; MORE_INIT - finishes the initialization. this code will be overlaid with data
;	      after it executes.
;
;   INPUT  -
;   OUTPUT -
;------------------------------------------------------------------------------
more_init proc	near			;AC000;
	public	more_init		;AN000;

	cld
	or	ah,al
	cmp	ah,-1			;was either drive specified invalid?
;	$if	e			;AC000; ;one or both of drives are invalid
	JNE $$IF144
	    print_msg msgnum_baddrv,STDERR ;AN000; ;"INVALID DRIVE SPEC."
	    int     20h 		;and quit
;	$endif				;AC000;
$$IF144:
	mov	ax, offset buf+4096	;end of pgm
	add	ax,16
	mov	cl,4
	shr	ax,cl			;in seg form
	push	cs
	pop	dx
	add	ax,dx			;seg addr of buf2
	mov	buf2,ax
	mov	dx,Memory_Size		;# paragraphs in machine
	cmp	ax,dx			;does start of buf2 exceed mem?
	jnb	badmem			;yes, can't do nothin' without mem
	sub	dx,ax			;# avail paragraphs
	cmp	dx,256			;have at least 4k?
	jnb	havmem			;yes
badmem:
	print_msg msgnum_mem,STDERR	;AN000; ;"INSUFFICIENT MEMORY"
	int	20h			;and quit
havmem:
	cmp	dx,3840 		;over 61440 bytes avail?
	jbe	cmem			;no
	mov	dx,3840 		;yes, set to max of 61440 bytes
cmem:
	mov	cl,4
	shl	dx,cl			;# bytes avail
	and	dx,0f000h		;round down to a 4096-byte boundary
	mov	word ptr mem,dx 	;and save buf2 size in bytes
	mov	byte ptr swt,0		;initialize master switch
	doscall DEFDRV			;AC000; ;get default drive
	inc	al
	mov	curdrv,al		;and save
	or	al,64			;drive to ascii
	mov	cdrv,al 		;save
	xor	ch,ch
	mov	cl,Parm_Area		;length of input parms
	mov	si,129			;where parms are

	mov	current_parm,si 	;AN000; ;pass to parser ptr to input parm buffer
	mov	ordinal,ZERO_PARM_CT	;AN000; ;pass ordinal #, this is begin of parse
	mov	parm_count,FIRST_PARM_CT ;AN000; ;parse the first parm and second parm
	call	parser			;AC000; ;returns first filename in path1, and the
					;AN000; ;second filename in path2.
					;fcb is already formatted with correct drive
	mov	si,offset path2
	mov	di,offset fcb2
	doscall PARSE_FILENAME,01H	;AC000; ;build 2nd fcb from 2nd parm,
					;AC000; ;scan off leading separators
	cmp	al,-1			;invalid drive?
;	$if	e			;AC000; ;Yes, invalid drive
	JNE $$IF146
	    print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec."
	    int     20h 		;and quit
;	$else				;AC000;
	JMP SHORT $$EN146
$$IF146:
	    mov     dx,offset CBExit
	    doscall SETVECTOR,23H	;AC000; ;change control break vector, #23h
;	$endif				;AC000;
$$EN146:

	ret				;AN000; ;return to main
more_init endp				;AN000;

cseg	ends
	end