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
|
; SCCSID = @(#)fcb.asm 1.2 85/07/23
; SCCSID = @(#)fcb.asm 1.2 85/07/23
TITLE FCB - FCB parse calls for MSDOS
NAME FCB
; Low level routines for parsing names into FCBs and analyzing
; filename characters
;
; MakeFcb
; NameTrans
; PATHCHRCMP
; GetLet
; TESTKANJ
; NORMSCAN
; DELIM
;
; Revision history:
;
; A000 version 4.00 Jan. 1988
;
;
; get the appropriate segment definitions
;
.xlist
include dosseg.asm
TableLook equ -1
Table Segment
Zero label byte
Table ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
include dossym.inc
include devsym.inc
include doscntry.inc ;AN000; 2/12/KK
.cref
.list
i_need Name1,BYTE
i_need Creating,BYTE
i_need Attrib,BYTE
i_need SpaceFlag,BYTE
i_need FILE_UCASE_TAB,byte ;DOS 3.3
i_need COUNTRY_CDPG,byte ;AN000; 2/12/KK
i_need DrvErr,BYTE ;AN000; 2/12/KK
i_need DOS34_FLAG,WORD ;AN000; 2/12/KK
procedure MakeFcb,NEAR
ScanSeparator = 1
DRVBIT EQU 2
NAMBIT EQU 4
EXTBIT EQU 8
MOV BYTE PTR [SpaceFlag],0
XOR DL,DL ; Flag--not ambiguous file name
TEST AL,DRVBIT ; Use current drive field if default?
JNZ DEFDRV
MOV BYTE PTR ES:[DI],0 ; No - use default drive
DEFDRV:
INC DI
MOV CX,8
TEST AL,NAMBIT ; Use current name fields as defualt?
XCHG AX,BX ; Save bits in BX
MOV AL," "
JZ FILLB ; If not, go fill with blanks
ADD DI,CX
XOR CX,CX ; Don't fill any
FILLB:
REP STOSB
MOV CL,3
TEST BL,EXTBIT ; Use current extension as default
JZ FILLB2
ADD DI,CX
XOR CX,CX
FILLB2:
REP STOSB
XCHG AX,CX ; Put zero in AX
STOSW
STOSW ; Initialize two words after to zero
SUB DI,16 ; Point back at start
TEST BL,ScanSeparator; Scan off separators if not zero
JZ SKPSPC
CALL SCANB ; Peel off blanks and tabs
CALL DELIM ; Is it a one-time-only delimiter?
JNZ NOSCAN
INC SI ; Skip over the delimiter
SKPSPC:
CALL SCANB ; Always kill preceding blanks and tabs
NOSCAN:
CALL GETLET
JBE NODRV ; Quit if termination character
IF DBCS ;AN000;
CALL TESTKANJ ;AN000;; 2/18/KK
JNE NODRV ;AN000;; 2/18/KK
ENDIF ;AN000;
CMP BYTE PTR[SI],":" ; Check for potential drive specifier
JNZ NODRV
INC SI ; Skip over colon
SUB AL,"@" ; Convert drive letter to drive number (A=1)
JBE BADDRV ; Drive letter out of range
PUSH AX
Invoke GetVisDrv
POP AX
JNC HavDrv
CMP [DrvErr],error_not_DOS_disk ; if not FAt drive ;AN000;
JZ HavDrv ; assume ok ;AN000;
BADDRV:
MOV DL,-1
HAVDRV:
STOSB ; Put drive specifier in first byte
INC SI
DEC DI ; Counteract next two instructions
NODRV:
DEC SI ; Back up
INC DI ; Skip drive byte
entry NORMSCAN
MOV CX,8
CALL GETWORD ; Get 8-letter file name
CMP BYTE PTR [SI],"."
JNZ NODOT
INC SI ; Skip over dot if present
TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000;
JZ VOLOK ;AN000;
MOVSB ; 2nd byte of DBCS ;AN000;
MOV CX,2 ;AN000;
JMP SHORT contvol ;AN000;
VOLOK:
MOV CX,3 ; Get 3-letter extension
contvol:
CALL MUSTGETWORD
NODOT:
MOV AL,DL
return
NONAM:
ADD DI,CX
DEC SI
return
GETWORD:
CALL GETLET
JBE NONAM ; Exit if invalid character
DEC SI
;
; UGH!!! Horrible bug here that should be fixed at some point:
; If the name we are scanning is longer than CX, we keep on reading!
;
MUSTGETWORD:
CALL GETLET
;
; If spaceFlag is set then we allow spaces in a pathname
;
JB FILLNAM
JNZ MustCheckCX
TEST BYTE PTR [SpaceFlag],0FFh
JZ FILLNAM
CMP AL," "
JNZ FILLNAM
MustCheckCX:
JCXZ MUSTGETWORD
DEC CX
CMP AL,"*" ; Check for ambiguous file specifier
JNZ NOSTAR
MOV AL,"?"
REP STOSB
NOSTAR:
STOSB
IF DBCS ;AN000;
CALL TESTKANJ ;AN000;
JZ NOTDUAL3 ;AN000;
JCXZ BNDERR ; Attempt to straddle boundry ;AN000;
MOVSB ; Transfer second byte ;AN000;
DEC CX ;AN000;
JMP MUSTGETWORD ;AN000;
BNDERR: ;AN000;
TEST [DOS34_FLAG],DBCS_VOLID ;AN000;
JZ notvolumeid ;AN000;
TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000;
JNZ notvolumeid ;AN000;
OR [DOS34_FLAG],DBCS_VOLID2 ;AN000;
JMP MUSTGETWORD ;AN000;
notvolumeid:
;; INC CX ; Undo the store of the first byte
DEC DI
MOV AL," " ;PTM. ;AN000;
STOSB ;PTM. ;AN000;
INC SI ;PTM. ;AN000;
JMP MUSTGETWORD ;PTM. ;AN000;
NOTDUAL3: ;AN000;
ENDIF ;AN000;
CMP AL,"?"
JNZ MUSTGETWORD
OR DL,1 ; Flag ambiguous file name
JMP MUSTGETWORD
FILLNAM:
MOV AL," "
REP STOSB
DEC SI
return
SCANB:
LODSB
CALL SPCHK
JZ SCANB
IF DBCS ;AN000; ;AN000;
CMP AL,81H ;AN000;; 1ST BYTE OF DBCS BLANK 2/18/KK ;AN000;
JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
CALL TESTKANJ ;AN000;; 2/23/KK 3/31/KK revoved ;AN000;
JE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
CMP BYTE PTR [SI],40H;AN000;H ; 2ND BYTE OF DBCS BLANK 2/18/KK 3/31/KK revove;AN000;
JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
INC SI ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
JMP SCANB ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
SCANB_EXIT: ;AN000;; 2/18/KK 3/31/KK revoved ;AN000;
ENDIF ;AN000;
DEC SI
return
EndProc MakeFCB
;
; NameTrans is used by FindPath to scan off an element of a path. We must
; allow spaces in pathnames
;
; Inputs: DS:SI points to start of path element
; Outputs: Name1 has unpacked name, uppercased
; ES = DOSGroup
; DS:SI advanced after name
; Registers modified: DI,AX,DX,CX
procedure NameTrans,near
ASSUME DS:NOTHING,ES:NOTHING
MOV BYTE PTR [SpaceFlag],1
context ES
MOV DI,OFFSET DOSGROUP:NAME1
PUSH DI
MOV AX,' '
MOV CX,5
STOSB
REP STOSW ; Fill "FCB" at NAME1 with spaces
XOR AL,AL ; Set stuff for NORMSCAN
MOV DL,AL
STOSB
POP DI
CALL NORMSCAN
IF DBCS ;AN000;;KK.
MOV AL,[NAME1] ;AN000;;KK. check 1st char
invoke testkanj ;AN000;;KK. dbcs ?
JZ notdbcs ;AN000;;KK. no
return ;AN000;;KK. yes
notdbcs: ;AN000;
ENDIF ;AN000;
CMP [NAME1],0E5H
retnz
MOV [NAME1],5 ; Magic name translation
return
EndProc nametrans
Break <GETLET, DELIM -- CHECK CHARACTERS AND CONVERT>
If TableLook
ChType Macro ch,bits
ORG CharType-Zero+ch
db bits
ENDM
Table SEGMENT
PUBLIC CharType
Public FCB001S,FCB001E
FCB001S label byte
CharType DB 256 dup (-1)
ChType ".", <LOW (NOT ( fChk))>
ChType '"', <LOW (NOT (fFCB+fChk))>
ChType "/", <LOW (NOT (fFCB+fChk))>
ChType "\", <LOW (NOT (fFCB+fChk))>
ChType "[", <LOW (NOT (fFCB+fChk))>
ChType "]", <LOW (NOT (fFCB+fChk))>
ChType ":", <LOW (NOT (fFCB+fChk+fDelim))>
ChType "<", <LOW (NOT (fFCB+fChk+fDelim))>
ChType "|", <LOW (NOT (fFCB+fChk+fDelim))>
ChType ">", <LOW (NOT (fFCB+fChk+fDelim))>
ChType "+", <LOW (NOT (fFCB+fChk+fDelim))>
ChType "=", <LOW (NOT (fFCB+fChk+fDelim))>
ChType ";", <LOW (NOT (fFCB+fChk+fDelim))>
ChType ",", <LOW (NOT (fFCB+fChk+fDelim))>
ChType 0, <LOW (NOT (fFCB+fChk))> ; NUL
ChType 1, <LOW (NOT (fFCB+fChk))> ; ^A
ChType 2, <LOW (NOT (fFCB+fChk))> ; ^b
ChType 3, <LOW (NOT (fFCB+fChk))> ; ^c
ChType 4, <LOW (NOT (fFCB+fChk))> ; ^d
ChType 5, <LOW (NOT (fFCB+fChk))> ; ^e
ChType 6, <LOW (NOT (fFCB+fChk))> ; ^f
ChType 7, <LOW (NOT (fFCB+fChk))> ; ^g
ChType 8, <LOW (NOT (fFCB+fChk))> ; ^h
ChType 9, <LOW (NOT (fFCB+fChk+fDelim+fSpChk))> ; Tab
ChType 10, <LOW (NOT (fFCB+fChk))> ; ^j
ChType 11, <LOW (NOT (fFCB+fChk))> ; ^k
ChType 12, <LOW (NOT (fFCB+fChk))> ; ^l
ChType 13, <LOW (NOT (fFCB+fChk))> ; ^m
ChType 14, <LOW (NOT (fFCB+fChk))> ; ^n
ChType 15, <LOW (NOT (fFCB+fChk))> ; ^o
ChType 16, <LOW (NOT (fFCB+fChk))> ; ^p
ChType 17, <LOW (NOT (fFCB+fChk))> ; ^q
ChType 18, <LOW (NOT (fFCB+fChk))> ; ^r
ChType 19, <LOW (NOT (fFCB+fChk))> ; ^s
ChType 20, <LOW (NOT (fFCB+fChk))> ; ^t
ChType 21, <LOW (NOT (fFCB+fChk))> ; ^u
ChType 22, <LOW (NOT (fFCB+fChk))> ; ^v
ChType 23, <LOW (NOT (fFCB+fChk))> ; ^w
ChType 24, <LOW (NOT (fFCB+fChk))> ; ^x
ChType 25, <LOW (NOT (fFCB+fChk))> ; ^y
ChType 26, <LOW (NOT (fFCB+fChk))> ; ^z
ChType 27, <LOW (NOT (fFCB+fChk))> ; ^[
ChType 28, <LOW (NOT (fFCB+fChk))> ; ^\
ChType 29, <LOW (NOT (fFCB+fChk))> ; ^]
ChType 30, <LOW (NOT (fFCB+fChk))> ; ^^
ChType 31, <LOW (NOT (fFCB+fChk))> ; ^_
ChType " ", <LOW (NOT ( fChk+fDelim+fSpChk))>
ChType 255, -1
FCB001E label byte
Table ENDS
ENDIF
;
; Get a byte from [SI], convert it to upper case, and compare for delimiter.
; ZF set if a delimiter, CY set if a control character (other than TAB).
;
; DOS 3.3 modification for file char upper case. F.C. 5/29/86
procedure GetLet,NEAR
LODSB
entry GetLet2 ;AN000;; called by uCase
PUSH BX
MOV BX,OFFSET DOSGROUP:FILE_UCASE_TAB+2
getget:
CMP AL,"a"
JB CHK1
CMP AL,"z"
JA CHK1
SUB AL,20H ; Convert to upper case
CHK1:
CMP AL,80H ; DOS 3.3
JB GOTIT ; DOS 3.3
SUB AL,80H ;translate to upper case with this index
;
XLAT BYTE PTR CS:[BX]
If TableLook
GOTIT:
PUSH AX
MOV BX,OFFSET DOSGROUP:CharType
XLAT BYTE PTR CS:[BX]
TEST AL,fChk
POP AX
POP BX
RET
entry GetLet3 ;AN000; called by uCase
PUSH BX ;AN000;
JMP getget ;AN000;
ELSE
GOTIT:
POP BX
CMP AL,"."
retz
CMP AL,'"'
retz
CALL PATHCHRCMP
retz
CMP AL,"["
retz
CMP AL,"]"
retz
ENDIF
entry DELIM
IF TableLook
PUSH AX
PUSH BX
MOV BX,OFFSET DOSGroup:CharType
XLAT BYTE PTR CS:[BX]
TEST AL,fDelim
POP BX
POP AX
RET
ELSE
CMP AL,":"
retz
CMP AL,"<"
retz
CMP AL,"|"
retz
CMP AL,">"
retz
CMP AL,"+"
retz
CMP AL,"="
retz
CMP AL,";"
retz
CMP AL,","
retz
ENDIF
entry SPCHK
IF TableLook
PUSH AX
PUSH BX
MOV BX,OFFSET DOSGroup:CharType
XLAT BYTE PTR CS:[BX]
TEST AL,fSpChk
POP BX
POP AX
RET
ELSE
CMP AL,9 ; Filter out tabs too
retz
; WARNING! " " MUST be the last compare
CMP AL," "
return
ENDIF
EndProc GetLet
Procedure PATHCHRCMP,NEAR
CMP AL,'/'
JBE PathRet
CMP AL,'\'
return
GotFor:
MOV AL,'\'
return
PathRet:
JZ GotFor
return
EndProc PathChrCMP
IF DBCS
;--------------------- 2/12/KK
; Function: Check if an input byte is in the ranges of DBCS vectors.
;
; Input: AL ; Code to be examined
;
; Output: ZF = 1 : AL is SBCS ZF = 0 : AL is a DBCS leading byte
;
; Register: All registers are unchanged except FL
;
procedure TESTKANJ,NEAR ;AN000;
call Chk_DBCS ;AN000;
jc TK_DBCS ;AN000;
cmp AL,AL ; set ZF ;AN000;
return ;AN000;
TK_DBCS:
PUSH AX ;AN000;
XOR AX,AX ;Set ZF ;AN000;
INC AX ;Reset ZF ;AN000;
POP AX ;AN000;
return ;AN000;
EndProc TESTKANJ ;AN000;
;
Chk_DBCS PROC ;AN000;
PUSH DS ;AN000;
PUSH SI ;AN000;
PUSH BX ;AN000;
Context DS ;AN000;
MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccSetDBCS ;AN000;
LDS SI,[BX+1] ; set EV address to DS:SI ;AN000;
ADD SI,2 ; Skip length ;AN000;
DBCS_LOOP:
CMP WORD PTR [SI],0 ; terminator ? ;AN000;
JE NON_DBCS ; if yes, no DBCS ;AN000;
CMP AL,[SI] ; else ;AN000;
JB DBCS01 ; check if AL is ;AN000;
CMP AL,[SI+1] ; in a range of Ev ;AN000;
JA DBCS01 ; if yes, DBCS ;AN000;
STC ; else ;AN000;
JMP DBCS_EXIT ; try next DBCS Ev ;AN000;
DBCS01:
ADD SI,2 ;AN000;
JMP DBCS_LOOP ;AN000;
NON_DBCS:
CLC ;AN000;
DBCS_EXIT:
POP BX ;AN000;
POP SI ;AN000;
POP DS ;AN000;
RET ;AN000;
Chk_DBCS ENDP ;AN000;
ENDIF ;AN000;
CODE ENDS
END
;AN000;
|