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
|
PAGE 90,132 ;AN000;A2
TITLE TREE.SAL - DISPLAY THE SUBDIRECTORY TREE ;AN000;
LISTPARM = 1 ;AN000;0=SUPPRESS LIST; 1=ALLOW LIST
; .XLIST
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: TREE
; DESCRIPTIVE NAME: Tree structure of subdirectories is displayed.
; FUNCTION: Displays to standard output a graphic representation
; of the subdirectory tree structure, beginning
; with the specified subdirectory, and optionally
; displaying all filenames in that tree.
; ENTRY POINT: START
; INPUT: (DOS COMMAND LINE PARAMETERS)
; [d:][path] TREE [D:][path] [/F] [/A]
; WHERE
; [d:][path] - Path where the TREE command resides.
; [D:][path] - Display of subdirectories starts with this
; specified subdirectory. If this is not
; specified, the default is the drive root directory.
; [/F] - This requests the files in each subdirectory
; in addition to the subdirectories themselves
; are to be listed.
; [/A] - This requests use of alternate graphic chars
; EXIT-NORMAL: ERRORLEVEL 0 - Normal completion
; EXIT-ERROR: ERRORLEVEL 1 - I/O error
; ERRORLEVEL 2 - Incorrect DOS version
; ERRORLEVEL 3 - Control Break termination
; EFFECTS: The result is a display of the Tree of subdirectories.
; No changes are made to the system, to the current subdirectory,
; nor to the current DOS default drive.
; 1. NO FILES, JUST SUBDIRECTORIES
; D:\ROOT
; ����SUBDIR1
; ����SUBDIR2
; � ����SUBDIR21
; � ����SUBDIR22
; ����SUBDIR3
; ����SUBDIR31
; ����SUBDIR32
; 2. FILES AND SUBDIRECTORIES
; D:\ROOT
; � MAINFIL1
; � MAINFIL2
; �
; ����SUBDIR1
; � FILE1
; � FILE2
; �
; ����SUBDIR2
; � � FILE2A
; � � FILE2B
; � �
; � ����SUBDIR21
; � � FILEA
; � � FILEB
; � �
; � ����SUBDIR22
; � FILEC
; � FILED
; � FILEF
; �
; ����SUBDIR3
; ����SUBDIR31
; ����SUBDIR32
; FILE32A
; FILE32B
; INCLUDED FILES: TREEQU.INC - EQUATES
; PATHMAC.INC - PATHGEN MACRO
; INTERNAL REFERENCES:
; ROUTINES:
; BEGIN - VERSION CHECK, SYSMSG INIT, EXIT TO DOS
; DEFINE_GRAPHICS - GET GRAPHIC CHARS FROM MSG
; PARSE - TOKENIZE THE DOS COMMAND LINE PARMS
; VERIFY_DRIVE - CHECK IF USER DRIVE ID IS OK
; INIT_CONDITIONS - GET INITIAL SUBDIR, APPEND,CTL_BREAK
; GET_VOL_LABEL - GET VOLUME LABEL ON SPECIFIED DRIVE
; VOLSER - DISPLAY VOLUME SERIAL NUMBER, IF ANY AN001
; LEN_ASCIIZ - GET LENGTH OF ASCIIZ STRING
; EXECUTE - LOOK THRU DIRECTORY LIST FOR SUBDIRS
; ANY_MORE_SUBDIR - LOOK AHEAD,SEE IF MORE SUBDIR
; FIND_TYPE_NORMAL - PROCESS NORMAL, NON-DIR, FILES
; FIND_TYPE_DIR - PROCESS THE DIRECTORY
; NEXT_LEVEL - SET UP TO LOOK AT LOWER LEVEL SUBDIR
; BEGIN_FIND - DO FIND FIRST FILE
; FIND_NEXT - LOOK FOR NEXT ENTRY IN DIRECTORY
; SHOW_FN - DISPLAY THE FILENAME FOUND
; FLN_TO_BUF - MOVE FILENAME TO BUFFER
; GRAF_TO_BUF - SELECT LEADING GRAPHIC CHAR FOR BUF
; BLANK_DASH - PUT BLANKS OR DASHES BEFORE FILENAME
; FIX_GRAF - CHANGE CURRENT GRAPHIC FOR NEXT LINE
; ANY_SUBDIRS - DISPLAY MSG IF NO SUBDIRS PRINTED
; DO_WRITE - SEND STRING TO STDOUT
; IF_NOMOREFILES - ASK EXTENDED ERROR FOR WHY IS ERROR
; GET_EXTERR - CALL EXTENDED ERROR
; SENDMSG - PASS IN REGS DATA FROM MSG DESCRIPTOR TO DISP MSG
; BREAK_HANDLER - CONTROL BREAK VECTOR POINTS HERE
; RESTORE - RETURN TO INITIAL DOS DEFAULT DRIVE
; MYERRORHANDLER - SERVICE CRITICAL ERROR HANDLER
; CHK_DBCS -SEE IF SPECIFIED BYTE IS A DBCS LEAD BYTE
; DATA AREAS:
; PSP - Contains the DOS command line parameters.
; STACK - Dynamic allocation of workareas.
; EXTERNAL REFERENCES:
; ROUTINES:
; SYSDISPMSG (FAR) - MESSAGE DISPLAY ROUTINE
; SYSLOADMSG (FAR) - SYSTEM MESSAGE LOADER
; PARSER (NEAR) - INTERROGATE DOS COMMAND LINE PARMS
; DATA AREAS:
; DTA - defined by the DOS FINDFIRST function.
; NOTES:
; This module should be processed with the SALUT pre-processor
; with the re-alignment not requested, as:
; SALUT TREE,NUL
; To assemble these modules, the sequential or alphabetical
; ordering of segments may be used.
; Sample LINK command:
; LINK @TREE.ARF
; Where the TREE.ARF is defined as:
; TREE+
; TREEPAR+
; TREESYSP+
; TREESYSM
; TREE
; These modules should be linked in this order. The load module is
; a COM file. It should be converted via EXE2BIN to a .COM file.
; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
; Display graphically the subdirectories and their files.
; A001 DCR 27, display vol serial number, if present.
; A002 Add support for /A switch for alternate graphics.
; A003 PTM 471 Avoid duplicate switches
; A004 PTM 537 Display parm in error
; A005 PTM 692 Remove period from vol label field
; A006 PTR1044 Append interface change
; A007 PTM1082 Critical error handler
; A008 PTM1199 DEFAULT DIR OF TARGET ALTERED
; A009 PTM1416 INT24 CLOBBERED USER'S RESPONSE
; A010 PTM1406 GET MEDIA ID WITH 69H, NOT IOCTL
; A011 PTM1821 COPYRIGH.INC moved to within msgserv.asm
; A012 PTM2352 DBCS ENABLING, CHECKING FOR "\"
; A013 PTM3512 PATHGEN
; A014 PTM3560 INVALID PATH DOES NOT DISPLAY PATHNAME
;
; Label: The following notice is found in the OBJ code generated from
; the "TREESYSM.SAL" module:
; "Version 4.00 (C) Copyright 1988 Microsoft
; "Licensed Material - Program Property of Microsoft
;****************** END OF SPECIFICATIONS *****************************
IF1 ;AN000;
%OUT COMPONENT=TREE, MODULE=TREE.SAL... ;AN000;
ENDIF ;AN000;
HEADER <MACRO DEFINITIONS> ;AN000;
INCLUDE PATHMAC.INC ;AN013;
; = = = = = = = = = = = =
FIXLIST MACRO LP,DOIT ;;AN000;
IF LP ;;AN000;
DOIT ;;AN000;
ENDIF ;;AN000;
ENDM ;;AN000;
; = = = = = = = = = = = =
HEADER MACRO TEXT ;;AN000;
FIXLIST LISTPARM,.XLIST ;;AN000;
SUBTTL TEXT ;;AN000;
FIXLIST LISTPARM,.LIST ;;AN000;
PAGE ;;AN000;
ENDM ;;AN000;
; = = = = = = = = = = = =
; $SALUT (0,36,41,52) ;AN000;
DOSCALL MACRO FN,SF ;;AN000;
IFNB <FN> ;;AN000;ARE THERE ANY PARMS AT ALL?
IFNB <SF> ;;AN000;
MOV AX,(FN SHL 8)+SF ;;AN000;AH=FN;AH=SF
ELSE ;;AN000;SINCE THERE IS NO SUB FUNC
MOV AH,FN ;;AN000;
ENDIF ;;AN000;
ENDIF ;;AN000;
INT 21H ;;AN000;
ENDM ;;AN000;
; = = = = = = = = = = = =
; $SALUT (0,14,19,36) ;AN000;
HEADER <EQUATES - DOS FUNCTION CALLS> ;AN000;
INCLUDE TREEQU.INC ;AN000;EQUATES, CONTROL BLOCKS
; = = = = = = = = = = = =
LISTPARM = 1 ;AN000;PERMIT LISTING
.LIST ;AN000;
HEADER <STATIC DATA AREA> ;AN000;
CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000;
ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000;AS SET BY DOS LOADER
; $SALUT (4,3,8,36) ;AN000;
EXTRN SUBLIST_PARSE:WORD ;AN004;PARSE ERROR XX - %0
EXTRN MSGNUM_VOL:WORD ;AN000;"Directory PATH listing for Volume %1"
EXTRN SUBLIST_VOL:WORD ;AN000;SUBLIST TO VOL LABEL IN FIX_DTA_FILN
EXTRN MSGNUM_LIST:WORD ;AN000;"Directory PATH listing"
EXTRN MSGNUM_INVPATH:WORD ;AN000;"INVALID PATH"
EXTRN SUBLIST_INVPATH:WORD ;AN014;THE ASCIIZ PATH CONSIDERED INVALID
EXTRN MSGNUM_EXTERR:WORD ;AN000;ALL EXTENDED ERRORS
EXTRN MSGNUM_NOSUB:WORD ;AN000;"No subdirectories exists"
EXTRN MSGNUM_SERNO:WORD ;AN001;"Volume Serial Number is %1-%2"
EXTRN SUBLIST_6A:WORD ;AN001;FIRST PART OF SERIAL NUMBER
EXTRN SUBLIST_6B:WORD ;AN001;SECOND PART OF SERIAL NUMBER
EXTRN CURRENT_PARM:WORD ;AN000;POINT TO NEXT PARM TO PARSE
EXTRN ORDINAL:WORD ;AN000;NUMBER OF CURRENT PARM
EXTRN LAST_BYTE:BYTE ;AN000;TAG AT END OF USED MEMORY, BEFORE STACK
EXTRN SYSDISPMSG:NEAR ;AN000;MESSAGE DISPLAY ROUTINE
EXTRN SYSLOADMSG:NEAR ;AN000;SYSTEM MESSAGE LOADER
EXTRN SYSGETMSG:NEAR ;AN002;SYSTEM MESSAGE LOCATER ROUTINE
EXTRN PARSER:NEAR ;AN000;INTERROGATE DOS COMMAND LINE PARMS
; = = = = = = = = = = = =
; $SALUT (0,14,19,36) ;AN000;
ORG 80H ;AN000;
PUBLIC COMMAND ;AN000;
COMMAND DB 128 DUP (?) ;AN000;DOS INPUT COMMAND LINE
; = = = = = = = = = = = =
ORG 100H ;AN000;REQUIRED LOCATION OF ENTRY POINT
START: JMP BEGIN ;AN000;DOS ENTRY POINT
; = = = = = = = = = = = =
;THERE ARE TWO SETS OF DEFINITIONS OF THE GRAPHIC CHARACTERS USED IN THE DISPLAY.
;THE FIRST SET LOOKS THE BEST, BUT ON SOME PRINTERS IS A TEDIOUS, SLOW PROCESS.
;THERE ARE SOME CODEPAGES THAT DO NOT HAVE THESE SAME GRAPHIC CHARACTERS IN
;THESE CORRESPONDING CODE POINT POSITIONS. JAPAN HAS ITS KATAKANA CHARACTER
;SET WHERE THESE GRAPHICS ARE DEFINED, AND WOULD THUS NOT WANT TO USE THIS
;FIRST GRAPHIC CHARACTERS SET. THE SECOND SET OF EQUATES DEFINE ALTERNATE
;CHARACTERS THAT, ALTHOUGH THE OUTPUT DOES NOT LOOK AS GOOD, AT LEAST WILL
;PRINT NORMALLY, AND DOES USE THE TRADITIONAL ASCII LOWER 128 AS ITS CODE
;POINTS, THUS WOULD BE AVAILABLE FOR THOSE OTHER CODEPAGES, LIKE JAPAN'S.
;IF IT BECOMES DESIRABLE TO GENERATE YET ANOTHER DEFINITION OF THESE CHARACTERS,
;THE REQUIREMENTS ARE:
; 1. NONE OF THE FOUR CAN BE BLANK
; 2. EACH OF THE FOUR MUST BE UNIQUE
; 3. EACH CHAR MUST BE A SINGLE BYTE (NO DBCS)
; GRAPHIC CHARACTERS
;THIS SET OF GRAPHIC CHARACTERS ARE ACTUALLY DEFINED BY THE MESSAGE 7,
;WHERE TRANSLATORS HAVE PROVIDED THE CHARACTERS COMPATABLE WITH THEIR
;NATIONAL CHARACTER CODEPAGE SET.
GRAF_TABLE LABEL BYTE ;AN002;DEFINITION OF FOUR GRAPHIC CHARACTERS
PUBLIC GRAF_TABLE ;AN002;
GRAF_ELBO DB "�" ;AN000;192 DECIMAL ASCII VAL
GRAF_DASH DB "�" ;AN000;196 DECIMAL ASCII VALUE
GRAF_TEE DB "�" ;AN000;195 DECIMAL ASCII VALUE
GRAF_BAR DB "�" ;AN000;179 DECIMAL ASCII VALUE
; ALTERNATE SET OF GRAPHIC CHARACTERS
;IF THE "/A" SWITCH IS SPECIFIED, THIS SET OF FOUR CHARACTERS WILL
;OVERLAY THE ABOVE SET OF GRAPHIC CHARACTERS.
GRAF_TABLE_ALT LABEL BYTE ;AN002;ALTERNATE SET OF GRAPHIC CHARACTERS
PUBLIC GRAF_TABLE_ALT ;AN002;
A_GRAF_ELBO DB "\" ;AN000;
A_GRAF_DASH DB "-" ;AN000;
A_GRAF_TEE DB "+" ;AN000;
A_GRAF_BAR DB "|" ;AN000;
; = = = = = = = = = = = =
FLAGS DB 0 ;AN000;INITIALIZE ALL FLAGS TO "FALSE"
PUBLIC FLAGS,F_SWITCH ;AN000;ADD ENTRIES IN LINK MAP
F_DEF_PAT_TAR EQU 40H ;AN008;IF ON, DEFAULT SUBDIR OF TARGET DRIVE IS KNOWN
;IF OFF, DEF SUBDIR OF TARGET NOT KNOWN ;AN008;
F_SUBDIR EQU 20H ;AN000;IF ON, A SUBDIR HAS BEEN DISPLAYED
;IF OFF, A SUBDIR HAS NOT YET BEED DISPLAYED
F_FAILING EQU 10H ;AN000;IF ON, DO NOT RESTORE SUBDIR ON FAILING DRIVE
;IF OFF, DO RESTORE SUBDIR ON TARGET DRIVE ;AN000;
F_FLN EQU 08H ;AN000;IF ON, A FILENAME HAS BEEN DISPLAYED
;IF OFF, NO FILNAME FOR THIS SUBDIR YET
F_FIRSTIME EQU 04H ;AN000;IF ON, DISPLAY OF NAME ALREADY DONE
;IF OFF, DISPLAY OF NAME NEVER DONE
F_SWITCH EQU 02H ;AN000;IF ON, THE /F SPECIFIED
;IF OFF, THEN /F NOT SPECIFIED
F_APPEND EQU 01H ;AC006;IF ON, DOS APPEND IS IN THE MULTIPLEXOR
;IF OFF, DOS APPEND IS NOT THE MULTIPLEXOR
APPEND_FLAGS DW 0 ;AN006;RECORDS ORIGINAL STATE OF APPEND
;8000H = /X:1
;4000H = /E
;2000H = /PATH:1
;1000H = /DRIVE:1
;0001H = ENABLE APPEND
DBCSENV DD 0 ;AN000;POINTER TO DBCS RANGES
ORIG_AX DW 0 ;AN000;DRIVE VERIFICATION FROM DOS AT ENTRY
CURRENT_COL DW 1 ;AN000;IN BUF, WHERE IS ELBO/TEE?
; INITIALLY SET TO START IN COLUMN ONE
MEDIA_ID_BUF A_MEDIA_ID_INFO <> ;AN001;AREA TO READ VOL SERIAL NUMBER WITH GET_MEDIA_ID
BUF DB ((DASH_NUM+1)*LEVEL_LIMIT) DUP(0) ;AN000;HAS ELBO,TEE,DASH,NUL ENDED
JUSTIN_CASE DB 64 DUP(0) ;AN000;CATCHES THE OVERFLOW
CRLF DB CR,LF,NUL ;AN000;LINE TERMINATOR
LEN_CRLF EQU 2 ;AN000;LENGTH OF CR, LF FIELDS IN PREVIOUS MSG
EXITFL DB EXOK ;AN000;RETURN CODE, INITIALLY "NORMAL"
; (SEE INCLUDED FILE OF EQUATES FOR DEFINITIONS OF VALUES)
; REMEMBER THE DOS DEFAULT DRIVE AND SUBDIRECTORY
DEFAULT_DR DB ? ;AN000;ALPHA LETTER OF DOS DEFAULT DRIVE
START_DR_NUM DB ? ;AN000;NUMERIC VALUE OF DOS DEFAULT DRIVE
; WHERE 0=A:, 1=B:, ETC...
DEFAULT_PATH DB BACK_SLASH ;AN000;FIRST BYTE OF PATH IS BACKSLASH
DB MAX_PATH DUP(0) ;AN000;ORIGINAL DEFAULT PATH
JUSTIN_CASE2 DB 64 DUP(0) ;AN000;CATCHES THE OVERFLOW
OLDINT23 DD ? ;AN000;ORIGINAL CONTENTS OF CTRL-BREAK VECTOR
OLDINT24 DD ? ;AN000;ORIGINAL CONTENTS OF CRITICAL ERROR VECTOR
FIX_DTA_RES DB 21 DUP(?) ;AN000;RESERVED FOR FIND NEXT CALLS
FIX_DTA_ATTR DB ? ;AN000;ATTRIBUTE
FIX_DTA_TIME DW ? ;AN000;TIME
FIX_DTA_DATE DW ? ;AN000;DATE
FIX_DTA_LSIZ DW ? ;AN000;LOW WORD OF FILE SIZE
FIX_DTA_HSIZ DW ? ;AN000;HIGH WORD OF FILE SIZE
FIX_DTA_FILN DB 13 DUP(?) ;AN000;FILENAME, WITH PERIOD, +0 BYTE
PUBLIC FIX_DTA_FILN ;AN000;USED TO DISPLAY VOLUME LABEL
STAR_STAR DB "*.*",0 ;AN000;UNIVERSAL FILENAME, +0
STAR_STAR_L EQU $-STAR_STAR ;AN000;LENGTH OF UNIVERSAL FILENAME, INCL NUL
SAVEFILN DB 13 DUP(?) ;AN000;COPY OF FIX_DTA_FILN, ABOVE
; THIS NEXT SET OF WORKSPACE DEFINES THE PATH BEING PROCESSED.
; THESE ITEMS MUST REMAIN TOGETHER, IN THIS ORDER:
START_DRIVE DB 0,":" ;AN000;DRIVE LETTER NEEDS TO BE FILLED IN HERE
PUBLIC START_DRIVE,START_PATH ;AN000;
START_PATH DB PERIOD ;AN000;AREA TO RECEIVE STARTING PATH ASCIIZ
DB (MAX_PATH+SIZE FIX_DTA_FILN) DUP(0) ;AN000;
JUSTIN_CASE3 DB 64 DUP(0) ;AN000;CATCHES THE OVERFLOW
; END OF CONTIGUOUS WORKSPACE DEFINING PATH
; = = = = = = = = = = = =
PATHLABL TREE ;AN013;
HEADER <BEGIN - VERSION CHECK, SYSMSG INIT, EXIT TO DOS> ;AN000;
; $SALUT (4,3,8,36) ;AN000;
BEGIN PROC NEAR ;AN000;
PUBLIC BEGIN ;AN000;
;INPUT - DOS COMMAND LINE PARMS, AS DEFINED IN MODULE PROLOG.
; CONTROL IS PASSED HERE FROM "START" AT ORG 100H.
; AX IS SET BY DOS TO FLAG ANY INVALID DRIVE SPECIFIED ON PARMS.
;OUTPUT - "EXITFL" HAS ERRORLEVEL RETURN CODE
; = = = = = = = = = = = =
MOV ORIG_AX,AX ;AN000;SAVE ORIGINAL VALUE OF AX
;SINCE THIS IS A .COM STYLE UTILITY, THE SEG ID IN THE MSG SUBLIST
;CANNOT BE SET BY THE LOADER, BUT MUST BE SET HERE, AT RUN TIME.
MOV SUBLIST_VOL.SUB_VALUE_SEG,CS ;AN000;MAKE SUBLIST VARIABLE ADDRESSABLE
MOV SUBLIST_6A.SUB_VALUE_SEG,CS ;AN001;
MOV SUBLIST_6B.SUB_VALUE_SEG,CS ;AN001;
MOV SUBLIST_PARSE.SUB_VALUE_SEG,CS ;AN004;
MOV SUBLIST_INVPATH.SUB_VALUE_SEG,CS ;AN014;
CALL SYSLOADMSG ;AN000; INIT SYSMSG HANDLER
; $IF C ;AN000; IF THERE WAS A PROBLEM
JNC $$IF1
CALL SYSDISPMSG ;AN000; LET HIM SAY WHY HE HAD A PROBLEM
MOV EXITFL,EXVER ;AN000; TELL ERRORLEVEL BAD DOS VERSION
; $ELSE ;AN000; SINCE SYSDISPMSG IS HAPPY
JMP SHORT $$EN1
$$IF1:
CLD ;AN000;CLEAR DIRECTION FLAG TO AUTO-INCREMENT
; GET CURRENT DRIVE ID
DOSCALL CURRDISK ;AN000;(19H) SET AL=0 IF A:, 1 IF B:, ETC...
MOV START_DR_NUM,AL ;AN000;SAVE NUMERIC VALUE OF DOS DEFAULT DRIVE
ADD AL,DRIVEA ;AN000;CONVERT DRIVE NUMBER TO LETTER
MOV DEFAULT_DR,AL ;AN000;REMEMBER ALPHA OF DEFAULT DRIVE
; OF FILENAME TO BE SEARCHED FOR
; RECORD THE INITIAL SET UP
CALL INIT_CONDITIONS ;AC007;SET DTA,APPEND STATUS,CAPTURE CTL-BREAK VEC
CALL DEFINE_GRAPHICS ;AN002;GET PROPER GRAPHIC CHARS FROM MSG
CALL PARSE ;AN000;LOOK AT DOS COMMAND LINE PARAMETERS,
; AND DISPLAY ERR MSG IF BAD
; $IF NC ;AN000;PARMS ARE OK?
JC $$IF3
; CURIOUS ODDITY:
; "CURRDISK" AL=0 DRIVE A:, AL=1 DRIVE B: ETC...
; "GET_CUR_DIR" AL=0 DEFAULT DRIVE, AL=1 DRIVE A: ETC...
; "SELECT_DISK" AL=0 DRIVE A:, AL=1 DRIVE B: ETC...
; SO... THE NUMBER WE HAVE HERE AGREES WITH "SELECT_DISK", BUT
; WE MUST ADD ONE WHEN WE DO THE "GET_CUR_DIR".
; GET CURRENT DIRECTORY OF TARGET DRIVE
;DS:SI = POINTER TO 64 BYTE USER AREA
;DL = DRIVE NUM (0=DEF, 1=A, ETC)
;OUTPUT: DS:SI POINTS TO FULL PATH NAME
; "DEFAULT_PATH" WILL HAVE THE DOS DEFAULT SUBDIRECTORY PATH.
MOV SI,OFFSET DEFAULT_PATH+1 ;AN000;PASS 64 BYTE AREA
MOV DL,START_DRIVE ;AN000;PASS NUMERIC VALUE
SUB DL,DRIVEA ;AN000; OF DRIVE TO BE SCANNED
INC DL ;AN000;SEE "CURIOUS ODDITY" ABOVE...
DOSCALL GET_CUR_DIR ;AN000;(47H) GET THE CURRENT SDIR OF TARGET DRIVE
OR FLAGS,F_DEF_PAT_TAR ;AN008;INDICATE DEFAULT PATH OF TARGET IS KNOWN
; DISPLAY FUNCTION HEADER
CALL GET_VOL_LABEL ;AN000;GET VOLUME LABEL TO FIX_DTA_FILN
; DISPLAY VOLUME SERIAL ID
CALL EXECUTE ;AN000;DISPLAY THE SET OF SUBDIRS
CALL ANY_SUBDIRS ;AN000;DISPLAY FINAL MSG IN CASE NO SUBDIRS
; $ELSE ;AN000;SINCE PARMS HAD A PROBLEM,
JMP SHORT $$EN3
$$IF3:
MOV EXITFL,EXERR ;AN000;SET ERROR RETURN CODE
; $ENDIF ;AN000;PARMS OK?
$$EN3:
; RESTORE SYSTEM TO INITIAL CONDITIONS
CALL RESTORE ;AN007;RETURN TO INITIAL DOS DEFAULT DRIVE,
; THE INITIAL DEFAULT PATH,
; AND THE INITIAL "APPEND" STATE.
; $ENDIF ;AN000;OK WITH SYSDISPMSG?
$$EN1:
MOV AL,EXITFL ;AN000;PASS BACK ERRORLEVEL RET CODE
DOSCALL RET_CD_EXIT ;AN000;(4CH) RETURN TO DOS WITH RET CODE
INT 20H ;AN000; IF ABOVE NOT WORK, EXIT ANYWAY
;FOR CONTROL-BREAK, "TREE" WILL EXIT TO DOS AT "CTL_BREAK" PROC
; IN STEAD OF HERE.
BEGIN ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <DEFINE_GRAPHICS - GET GRAPHIC CHARS FROM MSG> ;AN002;
DEFINE_GRAPHICS PROC NEAR ;AN002;
PUBLIC DEFINE_GRAPHICS ;AN002;
;INPUT - MESSAGE 7 HAS THE FOUR GRAPIC CHARS, DEFINED BY THE TRANSLATORS
; TO BE ACCEPTABLE TO THIS NATIONAL CODEPAGE.
;OUTPUT- THE "GRAF_TABLE" AREA IS Revised TO HAVE THE 4 GRAPHIC CHARS
; AS DEFINED BY THE MESSAGE
; = = = = = = = = = = = =
; DEFINE THE GRAPHIC CHARACTERS
MOV AX,GRAPHIC_MSGNUM ;AN002;REQUEST THE MESSAGE WITH GRAPHIC CHAR DEFS
MOV DH,UTILITY_MSG_CLASS ;AN002;
CALL SYSGETMSG ;AN002;ASK WHERE THOSE GRAPHIC CHARS ARE
;IF ANY PROBLEM HERE, JUST LEAVE
; THE GRAPHICS AS DEFINED AT ASSEMBLY TIME.
; $IF NC ;AN002;IF ALL OK, DS:SI POINTS TO MESSAGE
JC $$IF7
LEA DI,GRAF_TABLE ;AN002;POINT TO WHERE GRAPHIC CHARS ARE TO GO
LODSW ;AN002;GET FIRST PAIR OF CHARS
STOSW ;AN002;SAVE THEM
LODSW ;AN002;GET SECOND PAIR OF CHARS
STOSW ;AN002;AND SAVE THEM ALSO
; $ENDIF ;AN002;
$$IF7:
RET ;AN002;
DEFINE_GRAPHICS ENDP ;AN002;
; = = = = = = = = = = = =
HEADER <PARSE - TOKENIZE THE DOS COMMAND LINE PARMS> ;AN000;
PARSE PROC NEAR ;AN000;
PUBLIC PARSE ;AN000;
;INPUT - PSP HAS DOS COMMAND LINE PARAMETERS
;OUTPUT- CARRY IS SET IF THERE IS A PROBLEM
; CARRY IS CLEAR IF PARMS ARE OK
; IF THERE WERE ANY PARMS, THEY ARE MOVED FROM THE PSP
; INTO THE STRING, "COMMAND", WHERE THE PARSER WILL LOOK AT THEM.
; IF THE SWITCH "/F" WAS SPECIFIED, "F_SWITCH" IS SET TO "ON"
; IF THE SWITCH IS NOT SPECIFIED, "F_SWITCH" IS LEFT "OFF".
; IF THERE ARE NO PARMS, THE DEFAULTS OF CURRENT DRIVE AND CURRENT
; SUBDIRECTORY ARE SET UP TO BE WHERE THE SUBDIR SEARCH WILL
; START, AND THE "/F" SWITCH IS ASSUMED NOT SPECIFIED, SO
; THE DEFAULT DISPLAY WILL SHOW SUBDIRS ONLY, NO FILES.
; "START_DRIVE" EITHER HAS THE SPECIFIED STARTING DRIVE, OR
; WILL HAVE THE CURRENT DOS DEFAULT DRIVE.
; "START_PATH" EITHER WILL HAVE THE SPECIFIED STARTING PATH, OR
; WILL HAVE THE CURRENT DEFAULT PATH
; = = = = = = = = = = = =
MOV CURRENT_PARM,OFFSET COMMAND+1 ;AN000;SET POINT TO BEGINNING OF STRING
MOV ORDINAL,ZERO ;AN000;START WITH FIRST PARM
CALL PARSER ;AN000;INTERROGATE THE DOS COMMAND LINE PARMS
;OUTPUT: SET CARRY IF PROBLEM
; CLEAR CARRY IF ALL OK
; $IF NC ;AN000;IF ALL OK SO FAR WITH PARSER,
JC $$IF9
CMP START_DRIVE,NUL ;AN000;SEE IF START_DRIVE FILLED IN YET
; $IF E ;AN000;NO, NOT FILLED IN YET
JNE $$IF10
MOV AL,DEFAULT_DR ;AN000;GET ALPHA LETTER OF DEFAULT DRIVE
MOV START_DRIVE,AL ;AN000;SET WHERE TO SEARCH FOR SUBDIRS
CLC ;AN000;NO ERROR SO FAR
; $ELSE ;AN000;SINCE START_DRIVE WAS SPECIFIED
JMP SHORT $$EN10
$$IF10:
CALL VERIFY_DRIVE ;AN000;SEE IF USER SPECIFIED DRIVE IS OK, AND
; IF SO, CHANGE DOS DEFAULT DRIVE TO IT
;CARRY WILL BE SET IF ERROR
;IF A NEW DRIVE WAS SPECIFIED,
; DEFAULT DRIVE HAS BEEN CHANGED TO
; NEW DEFAULT DRIVE, USER SPECIFIED
; $ENDIF ;AN000;FILLED IN START_DRIVE YET?
$$EN10:
; $IF NC ;AN000;IF ALL OK SO FAR,
JC $$IF13
CMP START_PATH,NUL ;AN000;SEE IF START_PATH FILLED IN YET
; $IF E ;AN000;NO, NOT FILLED IN YET,
JNE $$IF14
MOV DI,OFFSET START_PATH ;AN000;SET WHERE TO PUT STARTING PATH
MOV AL,BACK_SLASH ;AN000;START CURRENT SUBDIR AT ROOT
STOSB ;AN000; SO START WITH BACK SLASH
;DI POINTS TO BYTE AFTER BACK SLASH
; JUST ADDED TO "START_PATH"
MOV SI,DI ;AN000;DS:SI = POINTER TO 64 BYTE USER AREA
MOV DL,DEFDRIVE ;AN000;DL = DRIVE NUM (0=DEF, 1=A, ETC)
DOSCALL GET_CUR_DIR ;AN000;(47H) GET CURRENT DIRECTORY
;OUTPUT: DS:SI POINTS TO FULL PATH NAME
; $ENDIF ;AN000;START_PATH FILLED IN YET?
$$IF14:
CLC ;AN000;INDICATE NO PROBLEM WITH PARMS
; $ENDIF ;AN000;ALL OK SO FAR?
$$IF13:
; $ENDIF ;AN000;ALL OK WITH PARSER?
$$IF9:
RET ;AN000;RETURN TO CALLER
PARSE ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <VERIFY_DRIVE - CHECK IF USER DRIVE ID IS OK> ;AN000;
VERIFY_DRIVE PROC NEAR ;AN000;
PUBLIC VERIFY_DRIVE ;AN000;
;THE USER HAS SPECIFIED A DRIVE LETTER. VERIFY IT IS A PROPER DRIVE.
;IF THE DRIVE LETTER SPECIFIED IS THE SAME AS THE DEFAULT DRIVE, IT IS OK.
;IF DIFFERENT, ADDITIONAL VERIFICATION TESTS MUST BE MADE.
;THIS TEST IS DONE BY TRYING TO CHANGE THE CURRENT DRIVE TO THE SPECIFIED
; DRIVE, THEN BY ASKING WHAT IS THE CURRENT DRIVE. IF THE CURRENT DRIVE
; HAS CHANGED FROM WHAT IT WAS ORIGINALLY, THEN THE NEW DRIVE LETTER IS OK.
; IF IT DID NOT CHANGE, THEN IT WAS A BOGUS DRIVE LETTER AND WE QUIT.
;INPUT: "START_DRIVE" - USER SPECIFIED DRIVE LETTER TO BE TESTED
; "DEFAULT_DR" - ORIGINAL DOS DEFAULT DRIVE
; "START_DR_NUM" - NUMERIC EQUIVALENT OF THE ORIGINAL DOS DEFAULT DRIVE
; "ORIG_AX" - HAS FLAGS TO VERIFY DRIVE, SET BY DOS AT LOAD TIME.
;OUTPUT: CARRY SET IF BAD, CARRY CLEAR IF OK
; IF BAD, ERROR MESSAGE IS DISPLAYED: "INVALID DRIVE SPECIFICATION"
; = = = = = = = = = = = =
MOV DL,START_DRIVE ;AN000;USING THE DRIVE SPECIFIED IN PARMS,
CMP DL,DEFAULT_DR ;AN000;DID PARMS SPECIFY DRIVE SAME AS DEFAULT?
; $IF NE ;AN000;IF DRIVE SPECIFIED IS DIFFERENT
JE $$IF18
MOV AX,ORIG_AX ;AN000;GET DRIVE VERIFICATION FLAGS, SAVED FROM AX
OR AL,AH ;AN000;COMBINE FLAGS FOR BOTH DRIVE ID'S, IF GIVEN
; $IF NZ,OR ;AN000;IF THERE IS A PROBLEM, OR...
JNZ $$LL19
SUB DL,DRIVEA ;AN000;CONVERT DRIVE LETTER TO DRIVE NUMBER
; DL=DRIVE NUMBER (0=A,1=B)
DOSCALL SELECT_DISK ;AN000;(0EH) SET DEFAULT DRIVE
;OUTPUT: AL=NUM. OF DRIVES (MIN 5) (NOT USED);AN000;
; (NOT INTERESTED...)
DOSCALL CURRDISK ;AN000;(19H) GET CURRENT DEFAULT DRIVE
;OUTPUT: AL = CURRENT DRIVE
; 0=A,1=B,ETC.
CMP AL,START_DR_NUM ;AN000;HAS THE ORIGINAL DOS DEFAULT DRIVE CHANGED?
CLC ;AN000;NO ERROR
; $IF E ;AN000;IF NO CHANGE, THEN USER SPECIFIED
JNE $$IF19
$$LL19:
; INVALID DRIVE
MOV MSGNUM_EXTERR,INVDRSPEC ;AN000;"INVALID DRIVE SPECIFICATION"
MOV DI,OFFSET MSGNUM_EXTERR ;AN000;
CALL SENDMSG ;AN000;TELL USER HE SAID BAD DRIVE LETTER
STC ;AN000;RETURN AN ERROR
; $ENDIF ;AN000;NO CHANGE?
$$IF19:
; $ELSE ;AN000;SINCE DRIVE SPECIFIED IS THE SAME
JMP SHORT $$EN18
$$IF18:
CLC ;AN000;NO ERROR
; $ENDIF ;AN000;NEW DRIVE SPECIFIED?
$$EN18:
RET ;AN000;RETURN TO CALLER
VERIFY_DRIVE ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <INIT_CONDITIONS - GET INITIAL SUBDIR, APPEND,CTL_BREAK> ;AN000;
INIT_CONDITIONS PROC NEAR ;AN000;
PUBLIC INIT_CONDITIONS ;AN000; MAKE ENTRY IN LINK MAP
;INPUT - "START_DR_NUM" WILL HAVE THE NUMERIC VALUE OF DOS DEFAULT DRIVE.
; - "DEFAULT_DR" WILL HAVE THE LETTER DRIVE ID OF DOS DEFAULT DRIVE.
;OUTPUT - "APPEND_FLAGS" RECORDS ORIGINAL STATUS OF /X OF APPEND.
; APPEND IS COMMANDED TO HALT ITS /X PROCESSING.
; CONTROL BREAK VECTOR IS ALTERED TO POINT TO MY HANDLER.
; = = = = = = = = = = = =
; SET UP THE LOCAL DTA
MOV DX,OFFSET FIX_DTA_RES ;AN000;PASS POINTER TO DTA BUFFER
DOSCALL SET_DTA ;AN000;(1AH) SET DTA FOR FIND FIRST/NEXT
; GET CURRENT APPEND STATUS
MOV AX,APPEND_CHECK ;AN006;SEE IF APPEND IS ACTIVE
INT 2FH ;AN006;CALL THE MULTIPLEXOR FUNCTION
OR AL,AL ;AN006;TEST THE RESULTS
; $IF NZ,AND ;AN006;IF INSTALLED
JZ $$IF23
MOV AX,APPEND_VERSION ;AN006;ASK IF DOS VERSION OF APPEND
INT 2FH ;AN006;CALL THE MULTIPLEXOR FUNCTION
CMP AX,DOS_APPEND_VER ;AN006;IS THIS THE DOS VERSION OF APPEND
; $IF E ;AN006;YES, DEAL WITH THIS VERSION
JNE $$IF23
OR FLAGS,F_APPEND ;AN000;FLAG IT AS THE DOS VERSION
MOV AX,GET_APPEND ;AN000;
INT 2FH ;AN000;READ STATUS OF /X FROM APPEND
;OUTPUT-BX=(SEE "APPEND_FLAGS" FOR DEFINITION
MOV APPEND_FLAGS,BX ;AC006;REMEMBER APPEND STATUS
; $ENDIF ;AN000;APPEND INSTALLED?
$$IF23:
; CAPTURE THE CRITICAL ERROR VECTOR
PUSH ES ;AN000;SAVE SEGREG
;AL = INTERRUPT NUMBER
DOSCALL GET_VECTOR,VEC_CRITERR ;AN000;(3524H) GET INTERRUPT VECTOR
;OUTPUT: ES:BX = CONTENTS OF VECTOR
MOV WORD PTR OLDINT24,BX ;AN000;SAVE THE ORIGINAL
MOV WORD PTR OLDINT24+WORD,ES ;AN000; CRITICAL ERROR HANDLER VECTOR
POP ES ;AN000;RESTORE SEGREG
MOV DX,OFFSET MYERRORHANDLER ;AN000;DS:DX = VECTOR TO INT HANDLER
;AL = INTERRUPT NUMBER
DOSCALL SET_VECTOR,VEC_CRITERR ;AN000;(25H) SET INTERRUPT VECTOR
; CAPTURE THE CONTROL BREAK VECTOR
PUSH ES ;AN000;SAVE SEGREG
;AL = INTERRUPT NUMBER
DOSCALL GET_VECTOR,VEC_CTLBREAK ;AN000;(3523H) GET INTERRUPT VECTOR
;OUTPUT: ES:BX = CONTENTS OF VECTOR
MOV WORD PTR OLDINT23,BX ;AN000;SAVE THE ORIGINAL
MOV WORD PTR OLDINT23+WORD,ES ;AN000; CTRL-BREAK VECTOR
POP ES ;AN000;RESTORE SEGREG
MOV DX,OFFSET BREAK_HANDLER ;AN000;DS:DX = VECTOR TO INT HANDLER
;AL = INTERRUPT NUMBER
DOSCALL SET_VECTOR,VEC_CTLBREAK ;AN000;(25H) SET INTERRUPT VECTOR
; STOP THE APPEND FUNCTION.
MOV AX,SET_APPEND ;AN000;CHANGE APPEND /X STATUS
XOR BX,BX ;AN000;REQUEST TERMINATION OF /X SUPPORT OF APPEND
INT 2FH ;AN000;SET IT
RET ;AN000;RETURN TO CALLER
INIT_CONDITIONS ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <GET_VOL_LABEL - GET VOLUME LABEL ON SPECIFIED DRIVE> ;AN000;
GET_VOL_LABEL PROC NEAR ;AN000;
PUBLIC GET_VOL_LABEL ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - "START_PATH" IS ASCIIZ OF STARTING PATH
;OUTPUT - "FIX_DTA_FILN" WILL HAVE ASCIIZ STRING OF VOLUMN LABEL.
; STARTING DRIVE AND PATH TO SPECIFIED SUBDIR IS DISPLAYED.
; = = = = = = = = = = = =
MOV CX,ATTR_VOLID ;AN000;REQUEST THE VOLUME ID
MOV DX,OFFSET STAR_STAR ;AN000;PASS FILENAME TO BE LOOKED FOR
DOSCALL FINDFIRST ;AN000;LOOK FOR VOLUME LABEL
; $IF NC ;AN000;IF LABEL FOUND OK,
JC $$IF25
;FIX_DTA_FILN HAS VOLUME LABEL
MOV DI,OFFSET MSGNUM_VOL ;AN000; "Directory PATH listing for Volume %1"
MOV AX,WORD PTR FIX_DTA_FILN+9 ;AN005;CONVERT LABELNAME FROM
MOV WORD PTR FIX_DTA_FILN+8,AX ;AN005; 12345678.123 FORMAT
MOV AX,WORD PTR FIX_DTA_FILN+11 ;AN005; TO REMOVE PERIOD
MOV WORD PTR FIX_DTA_FILN+10,AX ;AN005; TO BECOME 12345678123 INSTEAD
; $ELSE ;AN000;SINCE LABEL NOT FOUND,
JMP SHORT $$EN25
$$IF25:
MOV DI,OFFSET MSGNUM_LIST ;AN000; "Directory PATH listing"
; $ENDIF ;AN000;LABEL FOUND?
$$EN25:
CALL SENDMSG ;AN000;DISPLAY STARTING MESSAGE
CALL VOLSER ;AN001;DISPLAY VOLUME SERIAL NUMBER, IF ANY
; DISPLAY THE STARTING DRIVE AND SUBDIRECTORY
MOV DX,OFFSET START_DRIVE ;AN000;PASS POINTER TO STRING TO BE DISPLAYED
CALL LEN_ASCIIZ ;AN000;SETS CX = NUMBER OF BYTES TO WRITE
;DS:DX = ADDRESS OF DATA TO WRITE
CALL DO_WRITE ;AN000;DISPLAY STARTING SUBDIR TO STDOUT
RET ;AN000;RETURN TO CALLER
GET_VOL_LABEL ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <VOLSER - DISPLAY VOLUME SERIAL NUMBER, IF ANY> ;AN001;
VOLSER PROC NEAR ;AN001;
PUBLIC VOLSER ;AN001;
;IF THE MEDIA SUPPORTS A VOL SERIAL NUMBER, DISPLAY IT
; = = = = = = = = = = = =
; ISSUE GET MEDIA ID
MOV BH,ZERO ;AN001;BH=0, RES
MOV BL,START_DRIVE ;AN001;GET LETTER OF DRIVE BEING LOOKED AT
SUB BL,DRIVEA-1 ;AN001;(BACK UP 40H) BL=DRIVE NUM (1=A:, 2=B:, ETC)
MOV DX,OFFSET MEDIA_ID_BUF ;AN001;DS:DX=BUFFER (see A_MEDIA_ID_INFO STRUC)
DOSCALL GSET_MEDIA_ID,GET_ID ;AC010;(6900H) GET MEDIA ID
;CARRY SET ON ERROR (OLD STYLE BOOT RECORD)
; $IF NC ;AN001;IF THE GET MEDIA ID WORKED OK,
JC $$IF28
; NOTE: IN THE FOLLOWING TWO SUBLISTS, WE ARE GOING TO DISPLAY, IN HEX,
; A CONSECUTIVE SET OF 4 BYTES, THE VOLUME SERIAL NUMBER. THE ORDER OF
; THESE TWO WORDS OF HEX IS, LEAST SIGNIFICANT WORD FIRST, THEN THE
; MOST SIGNIFICANT WORD. WHEN DISPLAYED, THE MOST SIGNIFICANT IS TO BE
; DISPLAYED FIRST, SO THE VALUE AT SERIAL+2 GOES TO THE 6A SUBLIST,
; AND THE LEAST SIGNIFICANT VALUE AT SERIAL+0 GOES TO THE SECOND POSITION,
; REPRESENTED BY THE 6B SUBLIST.
LEA AX,MEDIA_ID_BUF.MI_SERIAL ;AN001;GET POINTER TO DATA TO BE PRINTED
MOV SUBLIST_6B.SUB_VALUE,AX ;AN001; INTO THE SUBLIST FOR %2
LEA AX,MEDIA_ID_BUF.MI_SERIAL+WORD ;AN001;GET POINTER TO DATA TO BE PRINTED
MOV SUBLIST_6A.SUB_VALUE,AX ;AN001; INTO THE SUBLIST FOR %1
;"Volume Serial Number is %1-%2"
MOV DI,OFFSET MSGNUM_SERNO ;AN001;DISPLAY THE NEW SERIAL NUMBER
CALL SENDMSG ;AN001;DISPLAY THE MESSAGE
; $ENDIF ;AN001;IS VOL SERIAL NUM PRESENT?
$$IF28:
RET ;AN001;RETURN TO CALLER
VOLSER ENDP ;AN001;
; = = = = = = = = = = = =
HEADER <LEN_ASCIIZ - GET LENGTH OF ASCIIZ STRING> ;AN000;
LEN_ASCIIZ PROC NEAR ;AN000;
PUBLIC LEN_ASCIIZ ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - ES:DX = POINTS TO START OF ASCIIZ STRING
;OUTPUT - CX = LENGTH OF CHARACTERS, INCLUDING THE NUL AT THE END
; = = = = = = = = = = = =
PUSH AX ;AN000;SAVE THE CALLER'S
PUSH DI ;AN000; REGISTERS
MOV CX,FULL_SEG_SIZE ;AN000;BETTER FIND THAT NUL SOMEWHERE...
MOV DI,DX ;AN000;SET INDEX TO WALK THRU THE STRING
MOV AL,NUL ;AN000;THIS IS THE CHAR I AM LOOKING FOR
REPNE SCASB ;AN000;LOOK FOR IT
SUB DI,DX ;AN000;TAKE AWAY WHERE WE STARTED, FROM WHERE WE AT
MOV CX,DI ;AN000; TO FIND NOW FAR WE MOVED
POP DI ;AN000;RESTORE THE CALLER'S
POP AX ;AN000; REGISTERS
RET ;AN000;RETURN TO CALLER
LEN_ASCIIZ ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <EXECUTE - LOOK THRU DIRECTORY LIST FOR SUBDIRS> ;AN000;
EXECUTE PROC NEAR ;AN000;
PUBLIC EXECUTE ;AN000;MAKE ENTRY IN LINK MAP
;BECAUSE OF THE RECURSIVE NATURE OF THIS ROUTINE, ALL ITS LOCAL WORKAREA
;MUST BE DYNAMICALLY ALLOCATED BY USING A PORTION OF THE STACK. AS EACH
;LOWER LEVEL OF STACK IS PROCESSED, A NEW CALL IS MADE TO THIS SUBROUTINE
;WHICH THEN CREATES A NEW WORKAREA FOR THAT SUBDIRECTORY.
;THE CURRENT STACK SIZE IS CHECKED TO SEE IF THERE IS ENOUGH ROOM FOR
;THE NEW STACK WORKAREA.
;INPUT:START_PATH - STRING OF PATHNAME OF PATH TO BE PROCESSED
;OUTPUT: WHEN THIS PROC RETURNS, ALL FILES IN THIS SUBDIR AND LOWER
; LEVELS OF SUBDIRS HAVE BEEN PROCESSED.
; = = = = = = = = = = = =
PUSH BP ;AN000;SAVE CALLER'S BP REG
SUB SP,WA_SIZE ;AN000;ALLOCATE STACK SPACE AS WORKAREA
MOV BP,SP ;AN000;SET BASE FOR WORKAREA CALLED "FRAME"
MOV AX,BP ;AN000;
SUB AX,OFFSET LAST_BYTE ;AN000;WHERE MY CODE ENDS
CMP AX,MIN_STACK ;AN000;IS THE MINIMUM STACK REMAINING?
; $IF AE ;AN000;IF ENUF STILL THERE, CONTINUE,
JNAE $$IF30
CMP START_PATH,BACK_SLASH ;AN000;WAS A BACKSLASH SDIR SPECIFIED,
; $IF NE ;AN000;NO BACKSLASH USED
JE $$IF31
MOV DX,OFFSET START_PATH ;AN000;POINT TO SPECIFIED PATH
DOSCALL CHDIR ;AN000;(3BH) CHANGE CURRENT DIR
; $IF NC ;AN000;IF CHDIR WORKED OK,
JC $$IF32
MOV DL,START_DRIVE ;AN000;GET TARGET DRIVE
SUB DL,DRIVEA-1 ;AN000;CONVERT TO NUM (A=1,B=2,ETC.)
LEA SI,[BP].FRAM_CURR_PATH+1 ;AN000;WHERE TO PUT PATH
MOV [BP].FRAM_CURR_PATH,BACK_SLASH ;AN000;
DOSCALL GET_CUR_DIR ;AN000;FIND WHERE WE ARE NOW
LEA SI,[BP].FRAM_CURR_PATH ;AN000;WHERE PATH WENT, WITH BACKSLASH
MOV DI,OFFSET START_PATH ;AN000;WHERE TO PUT IT
MOV CX,MAX_PATH+1 ;AN000;MOVE FULL LENGTH PLUS BACKSLASH
REP MOVSB ;AN000; TO START_PATH
; $ENDIF ;AN000;CHDIR OK?
$$IF32:
; $ELSE ;AN000;SINCE SPECIFIED PATH STARTS WITH BACKSLASH
JMP SHORT $$EN31
$$IF31:
MOV SI,OFFSET START_PATH ;AN000;USING THE STARTING PATH,
LEA DI,[BP].FRAM_CURR_PATH ;AN000;SAVE IT IN THE STACK WORKAREA
;(at times like this, sure is nice to
; have ES=SS. .EXE would be a problem..)
MOV CX,MAX_PATH+1 ;AN000;MOVE THE ENTIRE STARTING PATH+LEADING "\"
REP MOVSB ;AN000;INTO THE WORKAREA
MOV DX,OFFSET START_PATH ;AN000;POINT TO SPECIFIED PATH
DOSCALL CHDIR ;AN000;(3BH) CHANGE CURRENT SDIR TO SPECIFIED SDIR
; $ENDIF ;AN000;PERIOD SDIR SPECIFIED?
$$EN31:
; $IF NC ;AN000;IF CHDIR WORKED OK,
JC $$IF36
CALL ANY_MORE_SUBDIR ;AN000;SEE IF MORE SUBDIRS BELOW THIS ONE
;SETS "FRAM_CHAR" TO:
; "ELBO" - NO MORE DIR BELOW THIS ONE
; "TEE" - THERE IS ANOTHER DIR BELOW HERE
TEST FLAGS,F_SWITCH ;AN000;ARE ALL FILES ASKED FOR?
; (TEST WILL CLEAR CARRY FLAG)
; $IF NZ ;AN000;IS /F SET?
JZ $$IF37
CALL FIND_TYPE_NORMAL ;AN000;DISPLAY ALL THE FILENAMES
; $ENDIF ;AN000;/F?
$$IF37:
CALL FIND_TYPE_DIR ;AN000;DISPLAY ALL THE DIRECTORIES
; $ELSE ;AN000;SINCE CHDIR FAILED
JMP SHORT $$EN36
$$IF36:
MOV DI,OFFSET MSGNUM_INVPATH ;AN000;"INVALID PATH"
CALL SENDMSG ;AN000;SAY WHY I QUIT
MOV EXITFL,EXERR ;AN000;SET ERROR FLAG TO QUIT
; $ENDIF ;AN000;CHDIR OK?
$$EN36:
;FINISHED WITH THIS SUBDIRECTORY, SO
; $ELSE ;AN000;SINCE STACK TOO SMALL
JMP SHORT $$EN30
$$IF30:
MOV DI,OFFSET MSGNUM_EXTERR ;AN000;DESCRIPTOR FOR EXTENDED ERRORS
MOV [DI].MSG_NUM,INSUF_MEM ;AN000;"INSUFFICIENT MEMORY"
CALL SENDMSG ;AN000;
MOV EXITFL,EXERR ;AN000;SET ERRORLEVEL RET CODE
; $ENDIF ;AN000;
$$EN30:
ADD SP,WA_SIZE ;AN000;DISCARD WORKAREA
POP BP ;AN000;RESTORE CALLER'S BP REG
RET ;AN000;RETURN TO CALLER
EXECUTE ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <ANY_MORE_SUBDIR - LOOK AHEAD,SEE IF MORE SUBDIR> ;AN000;
ANY_MORE_SUBDIR PROC ;AN000;
;HAVING JUST DONE A FIND FIRST/NEXT FOR A SUBDIRECTORY,LOOK FOR ANOTHER
;INPUT: BP=DYNAMIC WORKAREA
; "FLAGS" FIRST TIME SWITCH
; FOR FIRST TIME, "START_DRIVE" AND "START_PATH" SET WITH WHERE TO LOOK.
; FIX_DTA_FILN MAY HAVE LATEST FILE PROCESSED, OR NOTHING
;OUTPUT:"FRAM_CHAR"="ELBO" = NO MORE SUBDIRS AFTER THIS ONE.
; "FRAM_CHAR"="TEE" = ANOTHER SUBDIR AFTER THIS ONE
; "EXITFL" SET TO NON ZERO IF REAL ERROR OCCURRED.
; FIX_DTA_FILN IS RESTORED TO WHATEVER IT HAD.
; = = = = = = = = = = = =
MOV SI,OFFSET FIX_DTA_FILN ;AN000;FROM THE DTA, FILENAME AREA
MOV DI,OFFSET SAVEFILN ;AN000; TO A TEMPORARY LOCATION
MOV CX,LENGTH SAVEFILN ;AN000; SAVE THE ENTIRE FILENAME FIELD
REP MOVSB ;AN000; INTO THE TEMPORARY LOCATION
TEST FLAGS,F_FIRSTIME ;AN000;IS THIS THE FIRST TIME?
; $IF Z ;AN000;IF THE FIRST TIME
JNZ $$IF43
MOV CX,ATTR_DIR ;AN000;SET ATTRIBUTE TO SUBDIR
MOV DX,OFFSET STAR_STAR ;AN000;PASS FILENAME TO BE LOOKED FOR
DOSCALL FINDFIRST ;AN000;
; $ELSE ;AN000;SINCE NOT FIRST TIME
JMP SHORT $$EN43
$$IF43:
DOSCALL FINDNEXT ;AN000;LOOK FOR ANOTHER SUBDIR
; $ENDIF ;AN000;FIRSTIME?
$$EN43:
; $SEARCH COMPLEX ;AN000;
JMP SHORT $$SS46
$$DO46:
DOSCALL FINDNEXT ;AN000;LOOK FOR ANOTHER SUBDIR
; $STRTSRCH ;AN000;
$$SS46:
; $EXITIF C ;AN000;IF ERROR WITH FINDNEXT
JNC $$IF46
CALL IF_NOMOREFILES ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
;CY NOT SET = "NO MORE FILES"
;CY IS SET = OTHER PROBLEM, "EXITFL" SET
MOV AL,GRAF_ELBO ;AN002;CHANGE TO ELBO
MOV [BP].FRAM_CHAR,AL ;AC002;SAY NO MORE SUBDIR
; $ORELSE ;AN000;SINCE NO ERROR WITH FINDNEXT
JMP SHORT $$SR46
$$IF46:
CMP FIX_DTA_ATTR,ATTR_DIR ;AN000;DID I FIND A SUBDIR?
; $ENDLOOP E,AND ;AN000;FINDNEXT OK?
JNE $$DO46
CMP FIX_DTA_FILN,PERIOD ;AN000;IS THIS FILENAME STARTING WITH "PERIOD"?
; $ENDLOOP NE ;AN000;IF NOT, FOUND A REAL SUBDIR
JE $$DO46
MOV AL,GRAF_TEE ;AN002;CHANGE TO TEE
MOV [BP].FRAM_CHAR,AL ;AN002;SAY STILL MORE SUBDIR
; $ENDSRCH ;AN000;
$$SR46:
TEST FLAGS,F_FIRSTIME ;AN000;IS THIS THE FIRST TIME?
; $IF NZ ;AN000;IF NOT THE FIRST TIME
JZ $$IF52
MOV DI,OFFSET FIX_DTA_RES ;AN000;MOVE TO THE FIXED DTA AREA
LEA SI,[BP].FRAM_DTA_RES ;AN000; FROM DYNAMIC AREA IN STACK
MOV CX,LENGTH FIX_DTA_RES ;AN000;SET COUNT TO FIELD SIZE
REP MOVSB ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK
; $ENDIF ;AN000;
$$IF52:
MOV DI,OFFSET FIX_DTA_FILN ;AN000;FROM A TEMPORARY LOCATION
MOV SI,OFFSET SAVEFILN ;AN000; TO THE DTA, FILENAME AREA
MOV CX,LENGTH SAVEFILN ;AN000; RESTORE THE ENTIRE FILENAME FIELD
REP MOVSB ;AN000; FROM THE TEMPORARY LOCATION
RET ;AN000;RETURN TO CALLER
ANY_MORE_SUBDIR ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <FIND_TYPE_NORMAL - PROCESS NORMAL, NON-DIR, FILES> ;AN000;
FIND_TYPE_NORMAL PROC NEAR ;AN000;
PUBLIC FIND_TYPE_NORMAL ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - PB=BASE OF FRAME, DYNAMIC WORKAREA WITH DTA
;OUTPUT - CY SET IF A PROBLEM, AND "EXITFL" HAS ERROR CODE
; CY CLEAR IF NORMAL "NO MORE FILES" FROM FIND FIRST/NEXT.
; = = = = = = = = = = = =
AND FLAGS,0FFH-F_FLN ;AN000;CLEAR INDICATOR FOR THIS SUBDIR
; TO SAY NO FILES PRINTED YET FOR THIS SDIR ;AN000;
MOV CX,ATTR_NORMAL ;AN000;SET TO LOOK FOR ALL FILES
CALL BEGIN_FIND ;AN000;DO FIND FIRST
; $DO ;AN000;STEP THRU EACH ENTRY IN THIS SUBDIR
$$DO54:
; $LEAVE C ;AN000;QUIT IF ERROR
JC $$EN54
OR FLAGS,F_FLN ;AN000;REQUEST THIS PRINTOUT BE DONE
CALL SHOW_FN ;AN000;SHOW THIS FILE JUST FOUND
CALL FIND_NEXT ;AN000;LOOK FOR ANOTHER
; $ENDDO ;AN000;LEAVE WILL QUIT IF PROBLEM WITH FINDNEXT
JMP SHORT $$DO54
$$EN54:
CALL IF_NOMOREFILES ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
;CY NOT SET = "NO MORE FILES"
;CY IS SET = OTHER PROBLEM, "EXITFL" SET
; $IF NC ;AN000;IF NO MORE FILES,
JC $$IF57
MOV AL,BLANK ;AN000;
MOV DI,OFFSET FIX_DTA_FILN ;AN000;WHERE NAME IS TO GO
MOV CX,LENGTH FIX_DTA_FILN ;AN000;NO. BYTES IN FILENAME FIELD
REP STOSB ;AN000;FILL FILENAME FIELD WITH BLANKS
MOV AL,ATTR_NORMAL ;AN000;SAY IT IS JUST A FILENAME
CALL SHOW_FN ;AN000;OUTPUT A BLANK LINE
; $ENDIF ;AN000;NO MORE FILES?
$$IF57:
RET ;AN000;RETURN TO CALLER
FIND_TYPE_NORMAL ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <FIND_TYPE_DIR - PROCESS THE DIRECTORY> ;AN000;
FIND_TYPE_DIR PROC NEAR ;AN000;
PUBLIC FIND_TYPE_DIR ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - PB=BASE OF FRAME, DYNAMIC WORKAREA WITH DTA
;OUTPUT - CY SET IF A PROBLEM
; CY CLEAR IF NORMAL "NO MORE FILES" FROM FIND FIRST/NEXT.
; = = = = = = = = = = = =
OR FLAGS,F_FLN ;AN000;PERMIT DISPLAY OF BUFFER
MOV CX,ATTR_DIR ;AN000;LOOK FOR DIRECTORY ATTRIBUTE
CALL BEGIN_FIND ;AN000;DO FIND FIRST
; $SEARCH ;AN000;STEP THRU EACH ENTRY IN THIS SUBDIR
$$DO59:
; $LEAVE C ;AN000;QUIT IF ERROR
JC $$EN59
CMP FIX_DTA_FILN,PERIOD ;AN000;WAS THAT A "PERIOD" FILENAME?
; $IF NE ;AN000;IF NOT, GO CHECK IT OUT
JE $$IF61
MOV AL,FIX_DTA_ATTR ;AN000;LOOK AT ATTRIB OF THIS FILE
CMP AL,ATTR_DIR ;AN000;IS THIS A DIRECTORY?
; $IF E ;AN000;IF DIR,
JNE $$IF62
CALL SHOW_FN ;AN000;SHOW THIS FILE JUST FOUND
ADD CURRENT_COL,DASH_NUM+1 ;AN000;LOCATE SDIR NAME IN PRINTOUT LINE
MOV SI,CURRENT_COL ;AN000;
LEA SI,BUF-1[SI] ;AN000;POINT AT SUBDIR NAME JUST PRINTED
MOV DI,OFFSET FIX_DTA_FILN ;AN000;WHERE "NEXT_LEVEL" EXPECTS IT
MOV CX,LENGTH FIX_DTA_FILN ;AN000;
REP MOVSB ;AN000;SET UP SUBDIR NAME TO GO PROCESS
CALL NEXT_LEVEL ;AN000;SHIFT TO LOWER LEVEL SUBDIRECTORY
CALL EXECUTE ;AN000;RECURSIVE CALL, PROCESS NEW LEVEL OF SUBDIR
SUB CURRENT_COL,DASH_NUM+1 ;AN000;BACK TO ORIGINAL LEVEL
LEA DX,[BP].FRAM_CURR_PATH ;AN000;DS:DX = POINTER TO ASCIIZ STRING
DOSCALL CHDIR ;AN000;(3BH) CHANGE CURRENT DIRECTORY
;GO BACK TO THE DIRECTORY THIS LEVEL OF
; STACK WORKAREA HAS BEEN DEALING WITH,
; SINCE "EXECUTE" HAD CHANGED IT TO WORK ON
; A LOWER SUBDIRECTORY.
; $ENDIF ;AN000;DIR?
$$IF62:
; $ENDIF ;AN000;"PERIOD" FILENAME?
$$IF61:
CMP EXITFL,EXOK ;AN000;ANY ERRORS SO FAR?
; $EXITIF NE,NUL ;AN000;YES, QUIT THIS MESS; OTHERWISE KEEP LOOKING
JNE $$SR59
CALL FIND_NEXT ;AN000;LOOK FOR ANOTHER
; $ENDLOOP ;AN000;LEAVE WILL QUIT IF PROBLEM WITH FINDNEXT
JMP SHORT $$DO59
$$EN59:
CMP EXITFL,EXOK ;AN000;IF NO ERROR FOUND SO FAR
; $IF E ;AN000;
JNE $$IF67
CALL IF_NOMOREFILES ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
;CY NOT SET = "NO MORE FILES"
;CY IS SET = OTHER PROBLEM, "EXITFL" SET
; $ENDIF ;AN000;ANY ERRORS SO FAR?
$$IF67:
; $ENDSRCH ;AN000;
$$SR59:
RET ;AN000;RETURN TO CALLER
FIND_TYPE_DIR ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <NEXT_LEVEL - SET UP TO LOOK AT LOWER LEVEL SUBDIR> ;AN000;
NEXT_LEVEL PROC NEAR ;AN000;
PUBLIC NEXT_LEVEL ;AN000;
;INPUT: FIX_DTA_FILN - FILE NAME OF LOWER LEVEL SUBDIR
;OUTPUT: START_PATH - HAS COMPLETE PATH TO THE NEW LEVEL SUBDIR
; = = = = = = = = = = = =
MOV SI,OFFSET START_PATH+1 ;AN000;WHERE TO SAVE CURRENT PATH
MOV DL,DEFDRIVE ;AN000;DL = DRIVE NUM (0=DEF, 1=A, ETC)
DOSCALL GET_CUR_DIR ;AN000;(47H) GET CURRENT DIRECTORY
;OUTPUT: DS:SI POINTS TO FULL PATH NAME
DEC SI ;AN012;START SCAN AT START_PATH
CALL SCAN_DBCS ;AN012;GET LAST 2 CHARS IN DL,DH
; SI NOW AT END OF STRING
MOV DI,SI ;AN012;GET POINTER TO NUL
CMP DL,BACK_SLASH ;AN000;
; $IF NE ;AN012;IF PATH NOT ALREADY TERMINATED WITH A "\"
JE $$IF70
MOV BYTE PTR [DI],BACK_SLASH ;AN000;TERMINATE PREVIOUS PATH
INC DI ;AN000;DI POINTS TO NEXT NUL AT END OF STRING
; $ENDIF ;AN000;END IN "\"?
$$IF70:
MOV SI,OFFSET FIX_DTA_FILN ;AN000;GET NAME OF NEW SUBDIR
MOV CX,LENGTH FIX_DTA_FILN ;AN000;
REP MOVSB ;AN000;ADD THE NEW SUBDIR TO END
AND FLAGS,0FFH - F_FIRSTIME ;AN000;IN NEW SUBDIR, REQUEST FIND FIRST TO START
RET ;AN000;RETURN TO CALLER
NEXT_LEVEL ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <SCAN_DBCS - FIND LAST 2 SBCS CHARS IN ASCIIZ> ;AN000;
SCAN_DBCS PROC NEAR ;AN000;
PUBLIC SCAN_DBCS ;AN000;
;INPUT: DS:SI = ASCIIZ STRING TO BE SCANNED
;OUTPUT: DL=LAST SBCS CHAR BEFORE NUL
; DH=NEXT TO LAST SBCS CHAR BEFORE NUL
; IF NO SBCS CHAR FOUND, DL OR DH WILL BE NUL
; SI=OFFSET TO NUL DELIMITER
XOR DX,DX ;AN000;CLEAR CHAR ACCUMULATOR
; $DO ;AN000;
$$DO72:
LODSB ;AN000;GET NEXT CHAR FROM DS:SI TO AL
CMP AL,NUL ;AN000;IS THAT THE DELIMITER?
; $LEAVE E ;AN000;FOUND THE END, SO QUIT
JE $$EN72
CALL CHK_DBCS ;AN000;IS THIS THE FIRST OF A DBCS PAIR?
; $IF C ;AN000;IF SO, FOUND A DBCS PAIR
JNC $$IF74
INC SI ;AN000;SKIP ITS PARTNER
MOV AL,NUL ;AN000;PASS BACK A NUL, INSTEAD OF AN SBCS CHAR
; $ENDIF ;AN000;
$$IF74:
MOV DH,DL ;AN000;SAVE PREVIOUS CHAR
MOV DL,AL ;AN000;REMEMBER THE CHAR JUST FOUND
; $ENDDO ;AN000;
JMP SHORT $$DO72
$$EN72:
DEC SI ;AN000;LODSB SET SI ONE BEYOND NUL
; SO SET SI BACK TO POINT TO THE NUL
RET ;AN000;RETURN TO CALLER
SCAN_DBCS ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <BEGIN_FIND - DO FIND FIRST FILE> ;AN000;
BEGIN_FIND PROC NEAR ;AN000;
PUBLIC BEGIN_FIND ;AN000;MAKE ENTRY IN LINK MAP
;INPUT- CURRENT DOS DEFAULT DRIVE HAS TARGET DRIVE TO BE RESEARCHED.
; CURRENT DEFAULT SUBDIRECTORY HAS SUBDIR TO BE RESEARCHED.
; CX = ATTRIBUTE OF FILE TYPE TO LOOK FOR
; BP = OFFSET OF DYNAMIC WORKAREA
;OUTPUT - DTA IS SET UP WITH FIRST FILE FOUND, READY TO BE USED BY FIND NEXT.
; WORKAREA HAS SAVED THE RESULT OF FINDFIRST.
; = = = = = = = = = = = =
MOV DX,OFFSET STAR_STAR ;AN000;PASS FILENAME TO BE LOOKED FOR
DOSCALL FINDFIRST ;AN000;(4EH) LOOK FOR FIRST SUBDIRECTORY
MOV SI,OFFSET FIX_DTA_RES ;AN000;MOVE FROM THE FIXED DTA AREA
LEA DI,[BP].FRAM_DTA_RES ;AN000; TO THE DYNAMIC AREA IN STACK
MOV CX,LENGTH FIX_DTA_RES ;AN000;SET COUNT TO FIELD SIZE
REP MOVSB ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK
RET ;AN000;RETURN TO CALLER
BEGIN_FIND ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <FIND_NEXT - LOOK FOR NEXT ENTRY IN DIRECTORY> ;AN000;
FIND_NEXT PROC NEAR ;AN000;
PUBLIC FIND_NEXT ;AN000;
;INPUT: RESERVED FIELD, LEFT FROM PREVIOUS FIND FIRST/NEXT, IN [BP].FRAM_DTA_RES
;OUTPUT: [BP].FRAM_DTA_RES UPDATED WITH NEW RESERVED DATA, FROM CURRENT DTA
; FIX_DTA.? FIELDS ARE SET UP TO DEFINE NEW FILE JUST FOUND.
; CY SET IF NO MORE FILES FOUND, CY CLEAR IF A NEW FILE FOUND.
; = = = = = = = = = = = =
LEA SI,[BP].FRAM_DTA_RES ;AN000;GET WHAT WAS LEFT FROM LAST FIND
MOV DI,OFFSET FIX_DTA_RES ;AN000;INTO THE FIXED DTA AREA
MOV CX,LENGTH FIX_DTA_RES ;AN000;SET COUNT TO FIELD SIZE
REP MOVSB ;AN000;SET UP DTA FOR FIND
DOSCALL FINDNEXT ;AN000;(4FH) CARRY WILL BE SET TO REFLECT RESULT
MOV SI,OFFSET FIX_DTA_RES ;AN000;MOVE FROM THE FIXED DTA AREA
LEA DI,[BP].FRAM_DTA_RES ;AN000; TO THE DYNAMIC AREA IN STACK
MOV CX,LENGTH FIX_DTA_RES ;AN000;SET COUNT TO FIELD SIZE
REP MOVSB ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK
RET ;AN000;RETURN TO CALLER
FIND_NEXT ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <SHOW_FN - DISPLAY THE FILENAME FOUND> ;AN000;
SHOW_FN PROC NEAR ;AN000;
PUBLIC SHOW_FN ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - BP=OFFSET TO WORKAREA IN STACK
; AL=ATTRIBUTE OF FILENAME AS DEFINED IN DIR ENTRY
; FLAGS (F_FLN) INDICATOR OF FLN HAVING BEEN PRINTED
;OUTPUT - "BUF" IS SET UP TO CONTAIN THE DISPLAY LINE, AND IS SENT TO STDOUT.
; = = = = = = = = = = = =
;DESCRIPTION OF THE LINE TO BE DISPLAYED, IN "BUF":
;"CURRENT_COL" HAS COL NUMBER WHERE LEADING GRAPHIC IS TO GO.
;"DASH_NUM" IS THE NUM OF DASHES THAT IMMEDIATELY FOLLOWS THE LEADING
; GRAPHIC. (FOR SUBDIRECTORIES ONLY - FOR REGULAR FILENAMES, THIS
; FIELD WOULD HAVE SPACES INSTEAD OF DASHES.)
;"FLN_INDENT" IS THE NUMBER OF SPACES TO BE PUT RIGHT IN FRONT OF A
; FILENAME. FOR SUBDIRS, THERE IS NO SUCH FIELD
;EXAMPLE, FOR SUBDIRS
; ����DIR_FILN
; FOR ORDINARY FILES
; �xxxssssANY_FILN.EXT (WHERE x AND s ARE SPACES)
; = = = = = = = = = = = =
CMP FIX_DTA_FILN,PERIOD ;AN000;DOES FILENAME START WITH PERIOD?
; $IF NE ;AN000;IF NOT, CONTINUE...
JE $$IF77
MOV BL,AL ;AN000;SAVE FILE ATTRIBUTE IN AL INTO BL
CALL FLN_TO_BUF ;AN000; MOVE NAME OF FILE TO OUTPUT BUFFER
CALL GRAF_TO_BUF ;AN000;DETERMINE LEADING GRAPHIC FOR BUFFER
CALL BLANK_DASH ;AN000;PUT BLANKS OR DASHES INTO BUF BEFORE FILENAME
; BUFFER INITIALIZED, DISPLAY IT
MOV DX,OFFSET BUF ;AN000;DISPLAY FILENAME OF FILE FOUND
CALL LEN_ASCIIZ ;AN000;SET CX=LEN OF DX@ BUFFER, UP THRU NUL
DEC CX ;AN000;FORGET THE NUL
TEST FLAGS,F_FLN ;AN000;HAVE ANY FLN BEEN PRINTED YET?
; $IF NZ ;AN000;IF SO, PRINT THIS
JZ $$IF78
CALL DO_WRITE ;AN000;DISPLAY FILENAME IN DX TO STDOUT
; $ENDIF ;AN000;FILES PRINTED YET?
$$IF78:
; CLEAN UP BUFFER FOR NEXT TIME
CALL FIX_GRAF ;AN000;SET UP GRAPHIC FOR NEXT LINE
MOV AL,[BP].FRAM_CHAR ;AN000;GET ALTERED GRAPHIC CHAR
MOV DI,CURRENT_COL ;AN000;FIND WHERE IN "BUF"
LEA DI,BUF-1[DI] ;AN000; TO PUT ALTERED GRAPHIC
STOSB ;AN000;STORE ALTERED GRAPHIC INTO BUFFER
CMP BL,ATTR_DIR ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF E ;AN000;IF IS A SUBDIRECTORY
JNE $$IF80
OR FLAGS,F_SUBDIR ;AN000;SAY, "A SUBDIR HAS BEEN PRINTED"
MOV DI,CURRENT_COL ;AN000;GET COL NUM OF ELBO/TEE
LEA DI,BUF[DI] ;AN000;POINT TO JUST AFTER ELBO/TEE
MOV AL,BLANK ;AN000;BLANK OUT THE HORIZONTAL DASHES
MOV CX,DASH_NUM ;AN000;HOW MANY DASHES WERE PUT IT
REP STOSB ;AN000;WIPE OUT THOSE DASHES FOR NEXT GUY
; $ENDIF ;AN000;
$$IF80:
; $ENDIF ;AN000;PERIOD FILENAME?
$$IF77:
RET ;AN000;RETURN TO CALLER
SHOW_FN ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <FLN_TO_BUF - MOVE FILENAME TO BUFFER> ;AN000;
FLN_TO_BUF PROC NEAR ;AN000;
PUBLIC FLN_TO_BUF ;AN000;
;INPUT: CURRENT_COL - INDEX INTO "BUF" WHERE THIS DISPLAY STARTS
; FIX_DTA_FILN - NAME OF FILE TO BE DISPLAYED
;OUTPUT: "BUF" HAS LEADING GRAPHIC AND FILENAME READY FOR DISPLAY.
; = = = = = = = = = = = =
MOV DI,CURRENT_COL ;AN000;
CMP BL,ATTR_DIR ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF NE ;AN000;IF NOT A SUBDIRECTORY
JE $$IF83
LEA DI,BUF+DASH_NUM+FLN_INDENT[DI] ;AN000;SET DESTINATION TO "BUF"+
; $ELSE ;AN000;SINCE IT IS SUBDIRECTORY
JMP SHORT $$EN83
$$IF83:
LEA DI,BUF+DASH_NUM[DI] ;AN000;SET DESTINATION TO "BUF"+
; $ENDIF ;AN000;
$$EN83:
MOV CX,LENGTH FIX_DTA_FILN ;AN000;SET COUNT TO MOVE ENTIRE FILE NAME
MOV SI,OFFSET FIX_DTA_FILN ;AN000;FROM DTA OF FIND FIRST
; $DO ;AN000;
$$DO86:
LODSB ;AN000;GET FIRST\NEXT CHAR OF FILENAME
STOSB ;AN000;MOVE THAT BYTE TO OUTPUT MSG FIELD
CMP AL,NUL ;AN000;IS THIS THE NUL CHAR DELIMITER?
; $LEAVE E ;AN000;QUIT IF NUL FOUND
JE $$EN86
; $ENDDO LOOP ;AN000;
LOOP $$DO86
$$EN86:
RET ;AN000;RETURN TO CALLER
FLN_TO_BUF ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <GRAF_TO_BUF - SELECT LEADING GRAPHIC CHAR FOR BUF> ;AN000;
GRAF_TO_BUF PROC NEAR ;AN000;
PUBLIC GRAF_TO_BUF ;AN000;
;INPUT: BL = ATTRIBUTE OF FILENAME
; FLAGS (F_FIRSTIME BIT)
; FRAM_CHAR = LEADING CHAR, FOR FILENAME DISPLAY
; CURRENT_COL = WHERE IN BUF TO PUT CHARS
; BUF = TO RECEIVE LEADING CHAR
;OUTPUT: BUF HAS LEADING CHAR
; = = = = = = = = = = = =
TEST FLAGS,F_SWITCH ;AN000;ARE FILENAMES TO BE LISTED
; $IF Z ;AN000;NO, JUST SUBDIRS
JNZ $$IF89
OR FLAGS,F_FIRSTIME ;AN000;DO NOT DO FIND FIRST SUBDIR
; $ENDIF ;AN000;
$$IF89:
CMP BL,ATTR_DIR ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF E ;AN000;IF A SUBDIR
JNE $$IF91
CALL ANY_MORE_SUBDIR ;AN000;SEE IF ANOTHER SUBDIR AFTER THIS ONE
; $ELSE ;AN000;SINCE NOT A SUBDIR
JMP SHORT $$EN91
$$IF91:
TEST FLAGS,F_FIRSTIME ;AN000;IS THIS THE FIRST TIME HERE?
; $IF Z ;AN000;IF FIRST TIME,
JNZ $$IF93
CALL FIX_GRAF ;AN000;SET UP GRAPHIC FOR NEXT LINE
; $ENDIF ;AN000;FIRST TIME?
$$IF93:
; $ENDIF ;AN000;SUBDIR?
$$EN91:
OR FLAGS,F_FIRSTIME ;AN000;FLAG, THIS HAS BEEN DONE
MOV AL,[BP].FRAM_CHAR ;AN000;START BUF WITH CURRENT GRAPHIC CHAR
MOV DI,CURRENT_COL ;AN000;
LEA DI,BUF-1[DI] ;AN000;
STOSB ;AN000;
RET ;AN000;RETURN TO CALLER
GRAF_TO_BUF ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <BLANK_DASH - PUT BLANKS OR DASHES BEFORE FILENAME> ;AN000;
BLANK_DASH PROC NEAR ;AN000;
PUBLIC BLANK_DASH ;AN000;
;INPUT: BL - FILE ATTRIBUTE
; CURRENT_COL - WHERE THIS DISPLAY STARTS IN "BUF"
; BUF - PARTLY READY CHARS FOR DISPLAY
;OUTPUT: BUF HAS PROPER CHARS BETWEEN LEADING GRAPHIC AND FILENAME FIELDS.
; = = = = = = = = = = = =
CMP BL,ATTR_DIR ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF NE ;AN000;IF NOT A SUBDIRECTORY
JE $$IF96
MOV AL,BLANK ;AN000;PUT IN BLANKS
MOV CX,DASH_NUM + FLN_INDENT ;AN000;SPECIFY HOW MANY BLANKS TO PUT IN
; $ELSE ;AN000;SINCE IT IS A SUBDIR
JMP SHORT $$EN96
$$IF96:
MOV AL,GRAF_DASH ;AN000;PUT IN THE DASHES
MOV CX,DASH_NUM ;AN000;SPECIFY HOW MANY DASHES TO PUT IN
; $ENDIF ;AN000;
$$EN96:
MOV DI,CURRENT_COL ;AN000;GET COL NUM OF ELBO/TEE
LEA DI,BUF[DI] ;AN000;POINT TO JUST AFTER ELBO/TEE
REP STOSB ;AN000;ADD DASHES/BLANKS TO PRINT LINE IN "BUF"
RET ;AN000;RETURN TO CALLER
BLANK_DASH ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <FIX_GRAF - CHANGE CURRENT GRAPHIC FOR NEXT LINE> ;AN000;
PUBLIC FIX_GRAF ;AN000;MAKE ENTRY IN LINK MAP
FIX_GRAF PROC NEAR ;AN000;
;IN THE WORKAREA, IS A CHAR THAT SHOWS WHAT HAS BEEN FOUND REGARDING ANY
;LOWER LEVELS OF SUBDIRS.
;WHEN DISPLAYING A SUBDIR, THE PRINT LINE STARTS EITHER WITH "ELBO",
;MEANING, NO LOWER LEVELS AFTER THIS ONE, OR WITH "TEE" WHICH MEANS
;THERE IS ANOTHER LEVEL OF SUBDIR BELOW THIS ONE. AFTER THE DISPLAY,
;THE REST OF THE DISPLAY OF FILENAMES WITHIN THIS SUBDIR, WILL SHOW
;THIS CHARACTER, BUT IN A Revised FORMAT. THIS SUBROUTINE PERFORMS
;THE MODIFICATION, AS:
;CHANGE "ELBO" TO "BLANK, OR CHANGE "TEE" TO "VERTICAL BAR".
;INPUT: BP=POINTER TO STACK WORKAREA
; FRAM_CHAR=FIELD IN WORKAREA WITH CHAR TO BE Revised
; = = = = = = = = = = = =
PUSH AX ;AN002;SAVE WORK REG
MOV AL,GRAF_ELBO ;AN002;GET ELBO CHAR
CMP [BP].FRAM_CHAR,AL ;AN000;FOR NEXT DISPLAY LINE AFTER THIS ONE,
; $IF E ;AN000;IF CURRENT LINE STARTS WITH "ELBO"
JNE $$IF99
MOV [BP].FRAM_CHAR,BLANK ;AN000;CHANGE IT TO JUST A BLANK
; $ELSE ;AN000;SINCE NOT ELBO
JMP SHORT $$EN99
$$IF99:
MOV AL,GRAF_TEE ;AN002;GET THE TEE CHAR
CMP [BP].FRAM_CHAR,AL ;AC002;CHANGE A "TEE"
; $IF E ;AN000;
JNE $$IF101
MOV AL,GRAF_BAR ;AN002;GET BAR CHAR
MOV [BP].FRAM_CHAR,AL ;AC002; TO A VERTICAL "BAR"
; $ENDIF ;AN000;
$$IF101:
; $ENDIF ;AN000;ELBO?
$$EN99:
POP AX ;AN002;RESTORE REG
RET ;AN000;RETURN TO CALLER
FIX_GRAF ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <ANY_SUBDIRS - DISPLAY MSG IF NO SUBDIRS PRINTED> ;AN000;
ANY_SUBDIRS PROC NEAR ;AN000;
;INPUT:FLAGS (F_SUBDIR BIT) IS SET IF ANY SUBDIR HAD BEEN DISPLAYED. IF THIS
; BIT IS OFF, THEN DISPLAY THE MESSAGE
; = = = = = = = = = = = =
TEST FLAGS,F_SUBDIR ;AN000;HAVE ANY SUBDIRS BEEN PRINTED YET?
; $IF Z ;AN000;NO, NONE PRINTED SO FAR
JNZ $$IF104
MOV DI,OFFSET MSGNUM_NOSUB ;AN000;"No sub-directories exist"
CALL SENDMSG ;AN000;DISPLAY THE MESSAGE
; $ENDIF ;AN000;ANY SUBDIRS PRINTED?
$$IF104:
RET ;AN000;RETURN TO CALLER
ANY_SUBDIRS ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <DO_WRITE - SEND STRING TO STDOUT> ;AN000;
DO_WRITE PROC NEAR ;AN000;
PUBLIC DO_WRITE ;AN000;
;AFTER THE REQUESTED STRING IS SEND TO STDOUT, IT IS TERMINATED BY CR,LF
;INPUT: DX=OFFSET TO STRING TO BE WRITTEN
; CX=LENGTH
;OUTPUT: STRING IS SENT TO STDOUT, FOLLOWED BY CR,LF.
; BX = SAVED AND RESTORED.
; = = = = = = = = = = = =
PUSH BX ;AN000;SAVE CALLER'S REG
MOV BX,STDOUT ;AN000;BX = FILE HANDLE
DOSCALL WRITE ;AN000;(40H) WRITE FUNCTION
MOV DX,OFFSET CRLF ;AN000;CLOSE MSG WITH CRLF
MOV CX,LEN_CRLF ;AN000;
DOSCALL WRITE ;AN000;(40H) WRITE FUNCTION
POP BX ;AN000;RESTORE CALLER'S REG
RET ;AN000;RETURN TO CALLER
DO_WRITE ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <IF_NOMOREFILES - ASK EXTENDED ERROR FOR WHY IS ERROR> ;AN000;
IF_NOMOREFILES PROC NEAR ;AN000;
PUBLIC IF_NOMOREFILES ;AN000;
;INPUT - A DOS FUNCTION HAS JUST RETURNED WITH A CARRY INDICATING ERROR
;OUTPUT - AX=EXTENDED ERROR CODE
; IF THE ERROR IS JUST A NO MORE FILES, CARRY IS CLEAR
; IF ANY OTHER ERROR, THEN CARRY IS SET, AND "EXITFL" HAS RET CODE
; = = = = = = = = = = = =
CALL GET_EXTERR ;AN000;GET THE EXTENDED ERROR TO AX
CMP AX,NO_MORE_FILES ;AN000;SEE IF FILE WAS NOT FOUND
; $IF E ;AN000;IF NO MORE FILES,
JNE $$IF106
CLC ;AN000;INDICATE A NORMAL RETURN
; $ELSE ;AN000;SINCE ERROR IS SOMETHING ELSE
JMP SHORT $$EN106
$$IF106:
STC ;AN000;INDICATE AN ABNORMAL RETURN
MOV EXITFL,EXERR ;AN000;INDICATE A PROBLEM TO RETURN CODE
; $ENDIF ;AN000;NO MORE FILES?
$$EN106:
RET ;AN000;RETURN TO CALLER
IF_NOMOREFILES ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <GET_EXTERR - CALL EXTENDED ERROR> ;AN000;
GET_EXTERR PROC NEAR ;AN000;
PUBLIC GET_EXTERR ;AN000;
;INPUT - A DOS FUNCTION HAS JUST RETURNED WITH A CARRY INDICATING ERROR
;OUTPUT: AX HAS EXTENDED ERROR CODE
; NOTE: OTHER REGS, BX, CX, NORMALLY SET BY THE EXTERROR CALL
; ARE NOT KEPT. THESE CONTAIN "LOCUS" AND SECONDARY LEVEL CODES
; THAT ARE NOT USED.
; = = = = = = = = = = = =
PUSH BX ;AN000;SAVE THE
PUSH DS ;AN000; CALLER'S
PUSH ES ;AN000; REGISTERS
PUSH CX ;AN000;
MOV BX,LEVEL_0 ;AN000;BX=LEVEL NUMBER
DOSCALL EXTERROR ;AN000;(59H) SET REGS TO SAY WHY PROBLEM
POP CX ;AN000;RESTORE REGS
POP ES ;AN000; CLOBBERED BY
POP DS ;AN000; THE DOSCALL
POP BX ;AN000;
RET ;AN000;RETURN TO CALLER
GET_EXTERR ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <SENDMSG - PASS IN REGS DATA FROM MSG DESCRIPTOR TO DISP MSG> ;AN000;
SENDMSG PROC NEAR ;AN000;
PUBLIC SENDMSG ;AN000;
; INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE
; OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED
; IF CARRY CLEAR, ALL OK
; IN EITHER CASE, DI AND AX ALTERED, OTHERS OK
; = = = = = = = = = = = =
PUSH BX ;AN000; SAVE CALLER'S REGS
PUSH CX ;AN000;
PUSH DX ;AN000;
PUSH SI ;AN000;
; 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
CALL SYSDISPMSG ;AN000; DISPLAY THE MESSAGE
; $IF C ;AN000; IF THERE IS A PROBLEM,
JNC $$IF109
; AX=EXTENDED ERROR NUMBER
MOV DI,OFFSET MSGNUM_EXTERR ;AN000; GET REST OF ERROR DESCRIPTOR
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
CALL SYSDISPMSG ;AN000; TRY TO SAY WHAT HAPPENED
STC ;AN000; REPORT PROBLEM
; $ENDIF ;AN000; PROBLEM WITH DISPLAY?
$$IF109:
POP SI ;AN000; RESTORE CALLER'S REGISTERS
POP DX ;AN000;
POP CX ;AN000;
POP BX ;AN000;
RET ;AN000;RETURN TO CALLER
SENDMSG ENDP ;AN000;
; = = = = = = = = = = =
HEADER <BREAK_HANDLER - CONTROL BREAK VECTOR POINTS HERE> ;AN000;
BREAK_HANDLER PROC FAR ;AN000;"FAR" HERE IS REQUIRED FOR
PUBLIC BREAK_HANDLER ;AN000; BREAK INTERRUPT HANDLERS
;THE INT 23H VECTOR HAS BEEN SET TO POINT HERE.
;THIS ROUTINE GETS CONTROL IF CONTROL-BREAK IS PRESSED.
;OUTPUT: THE "STC" REQUESTS THAT DOS ABORT WHEN I RETURN.
; THERE IS NO ERRORLEVEL VALUE TO BE PASSED BACK TO DOS AT THIS POINT.
CALL RESTORE ;AN000;PUT THINGS BACK LIKE THEY WERE
DOSCALL RET_CD_EXIT,EXCTL ;AN000;RETURN TO DOS, WITH CTL-BREAK ERROR CODE
INT 20H ;AN000;IN CASE ABOVE FAILS
;NOTE: THIS IS NOT THE MAIN EXIT FROM "TREE".
; THE USUAL EXIT IS IN "BEGIN" PROC.
BREAK_HANDLER ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <RESTORE - RETURN TO INITIAL DOS DEFAULT DRIVE> ;AN000;
RESTORE PROC NEAR ;AN000;
PUBLIC RESTORE ;AN000;
;SET DOS DEFAULT DRIVE BACK TO THE INITIAL VALUE, AND
; RESTORE THE INITIAL DEFAULT PATH,
; AND THE INITIAL "APPEND" STATE,
; AND THE ORIGINAL CONTROL BREAK VECTOR.
;INPUT - "DEFAULT_DR" SET TO ALPHA LETTER OF ORIGINAL DOS DEFAULT DRIVE.
; "START_DR_NUM" SET TO NUMERIC VALUE OF ORIGINAL DOS DEFAULT DRIVE
; "DEFAULT_PATH" SET TO ORIGINAL CURRENT PATH OF DOS DEFAULT DRIVE
; "APPEND_FLAGS" HAS ORIGINAL STATUS OF /X OF APPEND
; "OLDINT23" HAS ORIGINAL OWNER OF CONTROL BREAK VECTOR 23H
; "OLDINT24" HAS ORIGINAL OWNER OF CRITICAL ERROR VECTOR 24H
; = = = = = = = = = = = =
TEST FLAGS,F_FAILING ;AN000;IS RESTORING SUBDIR PERMITTED?
; $IF Z,AND ;AN000;YES, DO IT
JNZ $$IF111
TEST FLAGS,F_DEF_PAT_TAR ;AN000;HAS ORIGINAL SUBDIR BE FOUND YET?
; $IF NZ ;AN000;YES, DO IT
JZ $$IF111
; RESTORE THE CURRENT SUBDIRECTORY TO ITS ORIGINAL PATH
MOV DX,OFFSET DEFAULT_PATH ;AN000;DS:DX = POINTER TO ASCIIZ STRING
DOSCALL CHDIR ;AN000;(3BH) CHANGE CURRENT DIRECTORY
; $ENDIF ;AN000;
$$IF111:
; RESTORE THE DOS DEFAULT DRIVE TO ITS ORIGINAL DRIVE
MOV DL,START_DR_NUM ;AN000; DL=DRIVE NUMBER (0=A,1=B)
DOSCALL SELECT_DISK ;AN000;(0EH) SETS DEFAULT DRIVE
; SET APPEND BACK TO ITS ORIGINAL STATUS
TEST FLAGS,F_APPEND ;AN006;IF DOS VERSION OF APPEND IS ACTIVE
; $IF NZ ;AN006;IT NEEDS TO BE FIXED BACK LIKE IT WAS
JZ $$IF113
MOV AX,SET_APPEND ;AN000;RESTORE APPEND TO PREVIOUS /X STATUS
MOV BX,APPEND_FLAGS ;AC006;GET PREVIOUS STATUS
INT 2FH ;AN000;SET IT BACK AS IT WAS
; $ENDIF ;AN006;DOS VERSION OF APPEND?
$$IF113:
; FIXUP THE CONTROL BREAK VECTOR TO ITS ORIGINAL CONTENTS
PUSH DS ;AN000;SAVE THE SEGREG
LDS DX,OLDINT23 ;AN000;USING THE ORIGINAL CONTENTS OF THE VECTOR
;DS:DX = DWORD POINTER TO BE PUT INTO VECTOR
DOSCALL SET_VECTOR,VEC_CTLBREAK ;AN000;(25H) RESTORE THE ORIG INT 23 HANDLER
POP DS ;AN000;RESTORE THE SEGREG
; FIXUP THE CRITICAL ERROR VECTOR TO ITS ORIGINAL CONTENTS
PUSH DS ;AN000;SAVE THE SEGREG
LDS DX,OLDINT24 ;AN000;USING THE ORIGINAL CONTENTS OF THE VECTOR
;DS:DX = DWORD POINTER TO BE PUT INTO VECTOR
DOSCALL SET_VECTOR,VEC_CRITERR ;AN000;(25H) RESTORE THE ORIG INT 24 HANDLER
POP DS ;AN000;RESTORE THE SEGREG
RET ;AN000;RETURN TO CALLER
RESTORE ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <MYERRORHANDLER - SERVICE CRITICAL ERROR HANDLER> ;AN000;
MYERRORHANDLER PROC NEAR ;AN000;
;INPUT: DOS HAS CALLED THE CRITICAL ERROR INTERRUPT, VECTOR 24
; AL=FAILING DRIVE NUMBER (A:=0; B:=1; ETC.)
;OUTPUT: EITHER TREE IS TERMINATED (ON ABORT OR FAIL), OR
; AL HAS OPERATOR RESPONSE, AND IRET BACK TO DOS TO HANDLE IT.
; = = = = = = = = = = = =
ASSUME CS:CSEG ;AN000;ONLY THE CS REG IS WORTH A HOOT
ASSUME DS:NOTHING ;AN000;
ASSUME ES:NOTHING ;AN000;
ASSUME SS:NOTHING ;AN000;
PUSH AX ;AN000;SAVE FAILING DRIVE NUMBER (A:=0, B:=1, ETC)
PUSHF ;AN000;SAVE THE FLAGS
;(THIS IS NEEDED BECAUSE THE OLD INT 24
; HANDLER WILL EXIT WITH AN "IRET")
CALL DWORD PTR OLDINT24 ;AN000;INVOKE THE DOS ERROR HANDLER
;RESPONSE WILL BE RETURNED IN AL
;AL=0=IGNORE
;AL=1=RETRY
;AL=2=ABORT
;AL=3=FAIL
CMP AL,ABORT ;AN000;DID USER SAY ABORT ?
; $IF GE ;AN000;YES, PROCESS "ABORT"
JNGE $$IF115
PUSH CS ;AN000;SET UP SEGREGS
PUSH CS ;AN000; SO "RESTORE" WILL LIKE THEM
POP ES ;AN000;
POP DS ;AN000;
ASSUME DS:CSEG,ES:CSEG ;AN000;TELL THE ASSEMBLER WHAT I JUST DID
POP AX ;AN007;GET AL=FAILING DRIVE NUMBER
MOV AH,START_DRIVE ;AN007;GET THE TARGET DRIVE BEING USED
SUB AH,DRIVEA ;AN007; A:=0, B:=1, ETC
CMP AH,AL ;AN007;IS START DRIVE SAME AS FAILING DRIVE?
; $IF E ;AN007;IF SAME DRIVE
JNE $$IF116
OR FLAGS,F_FAILING ;AN007;REQUEST CHDIR ON FAILING DRIVE NOT TO BE DONE
; $ENDIF ;AN007;
$$IF116:
CALL RESTORE ;AN000;RESTORE ORIGINAL CONDITIONS
DOSCALL RET_CD_EXIT,EXABORT ;AN000;QUIT, RETURN ERRORLEVEL CODE TO DOS
; = = = = = = = = = = = = = = = = =
; $ENDIF ;AN000;
$$IF115:
ADD SP,WORD ;AC009;UNDO THE PUSH AX ABOVE
IRET ;AN000;
MYERRORHANDLER ENDP ;AN000;
; = = = = = = = = = = = =
HEADER <CHK_DBCS -SEE IF SPECIFIED BYTE IS A DBCS LEAD BYTE> ;AN012;
;*****************************************************************************
; Check DBCS environment
;*****************************************************************************
; Function: Check if a specified byte is in ranges of the DBCS lead bytes
; Input: AL = Code to be examined
; Output: If CF is on then a lead byte of DBCS
; Register: FL is used for the output, others are unchanged.
PUBLIC CHK_DBCS ;AN012;
Chk_DBCS PROC ;AN012;
PUSH DS ;AN012;save these regs, about to be clobbered
PUSH SI ;AN012;
LDS SI,DBCSENV ;AN012;GET VECTOR OF DBCS RANGES
ASSUME DS:NOTHING ;AN012;that function clobbered old DS
OR SI,SI ;AN012;IS THIS VECTOR SET YET?
; $IF Z ;AN012;NO, GO GET THE VECTOR
JNZ $$IF119
PUSH AX ;AN012;
DOSCALL DBCS_ENV,GET_DBCS_ENV ;AN012;SET DS:SI TO POINT TO DBCS VECTOR
MOV WORD PTR DBCSENV,SI ;AN012;SAVE THE DBCS VECTOR OFFSET
MOV WORD PTR DBCSENV+WORD,DS ;AN012; AND ITS SEGID
POP AX ;AN012;REGAIN THE CHAR TO BE CHECKED
; $ENDIF ;AN000;
$$IF119:
; $SEARCH ;AN012;
$$DO121:
CMP WORD PTR [SI],NUL ;AN012;vector ends with a nul terminator entry
; $LEAVE E ;AN012;if that was the terminator entry, quit
JE $$EN121
CMP AL,[SI] ;AN012;look at LOW value of vector
; $EXITIF NB,AND ;AN012;if this byte is in range with respect to LOW
JB $$IF121
CMP AL,[SI+1] ;AN012;look at HIGH value of vector
; $EXITIF NA ;AN012;if this byte is still in range
JA $$IF121
STC ;AN012;set flag to say, found a DBCS char.
; $ORELSE ;AN012;since char not in this vector
JMP SHORT $$SR121
$$IF121:
ADD SI,WORD ;AN012;go look at next vector in dbcs table
; $ENDLOOP ;AN012;go back and check out new vector entry
JMP SHORT $$DO121
$$EN121:
CLC ;AN012;set flag to say this is not a DBCS character
; $ENDSRCH ;AN012;
$$SR121:
POP SI ;AN012;restore the regs
POP DS ;AN012;
ASSUME DS:CSEG ;AN012;tell masm, DS back to normal
RET ;AN012;
Chk_DBCS ENDP ;AN012;
; = = = = = = = = = = = =
PATHLABL TREE ;AN013;
CSEG ENDS ;AN000;
END START ;AN000;
|