mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 17:15:47 +00:00
513 lines
13 KiB
NASM
513 lines
13 KiB
NASM
;
|
|
; FCB management routines for MSDOS
|
|
;
|
|
|
|
INCLUDE DOSSEG.ASM
|
|
|
|
IFNDEF KANJI
|
|
KANJI EQU 0 ;FALSE
|
|
ENDIF
|
|
|
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
|
|
|
.xlist
|
|
.xcref
|
|
INCLUDE DOSSYM.ASM
|
|
INCLUDE DEVSYM.ASM
|
|
.cref
|
|
.list
|
|
|
|
i_need Name1,BYTE
|
|
i_need NumIO,BYTE
|
|
i_need DevFCB,BYTE
|
|
i_need Creating,BYTE
|
|
i_need ExtFCB,BYTE
|
|
i_need Attrib,BYTE
|
|
i_need SpaceFlag,BYTE
|
|
i_need Current_Country,WORD
|
|
|
|
procedure MakeFcb,NEAR
|
|
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,1 ; 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
|
|
CMP BYTE PTR[SI],":" ; Check for potential drive specifier
|
|
JNZ NODRV
|
|
INC SI ; Skip over colon
|
|
SUB AL,"@" ; Convert drive letter to binary drive number
|
|
JBE BADDRV ; Valid drive numbers are <= NUMIO
|
|
CMP AL,BYTE PTR [NUMIO]
|
|
JBE HAVDRV
|
|
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
|
|
NORMSCAN:
|
|
MOV CX,8
|
|
CALL GETWORD ; Get 8-letter file name
|
|
CMP BYTE PTR [SI],"."
|
|
JNZ NODOT
|
|
INC SI ; Skip over dot if present
|
|
MOV CX,3 ; Get 3-letter extension
|
|
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 KANJI
|
|
CALL TESTKANJ
|
|
JZ NOTDUAL3
|
|
JCXZ BNDERR ; Attempt to straddle boundry
|
|
MOVSB ; Transfer second byte
|
|
DEC CX
|
|
JMP SHORT NOTDUAL3
|
|
BNDERR:
|
|
MOV BYTE PTR ES:[DI-1]," " ; patch up that space
|
|
JMP MustGetWord ; go back and scan until delim
|
|
|
|
NOTDUAL3:
|
|
ENDIF
|
|
|
|
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
|
|
DEC SI
|
|
return
|
|
MakeFCB ENDP
|
|
|
|
;
|
|
; NameTrans is used by FindPath to scan off an element
|
|
; of a path. We must allow spaces in pathnames
|
|
; Inputs: SS - DOSGROUP
|
|
; DS:SI name
|
|
; Outputs: DS:SI advanced over spot
|
|
; ES:DI point to after Name1
|
|
; registers modified: AX, BX, CX, DX
|
|
procedure NameTrans,near
|
|
MOV BYTE PTR [SpaceFlag],1
|
|
PUSH SS
|
|
POP ES
|
|
MOV DI,OFFSET DOSGROUP:NAME1
|
|
PUSH DI
|
|
MOV AL,' '
|
|
MOV CX,11
|
|
REP STOSB
|
|
XOR AL,AL
|
|
MOV DL,AL
|
|
STOSB
|
|
POP DI
|
|
CMP BYTE PTR [SI],'.'
|
|
|
|
IF KANJI
|
|
JZ FOOBAR
|
|
CALL NORMSCAN
|
|
CMP [NAME1],0E5H
|
|
retnz
|
|
MOV [NAME1],5
|
|
return
|
|
FOOBAR:
|
|
ELSE
|
|
JNZ NORMSCAN
|
|
ENDIF
|
|
|
|
MOVSB
|
|
LODSB
|
|
CALL PATHCHRCMP
|
|
JZ GOTDOTNAME
|
|
OR AL,AL
|
|
JZ GOTDOTNAME
|
|
CMP AL,'.'
|
|
JNZ BADDOTS
|
|
STOSB
|
|
LODSB
|
|
CALL PATHCHRCMP
|
|
JZ GOTDOTNAME
|
|
OR AL,AL
|
|
JZ GOTDOTNAME
|
|
DEC SI
|
|
BADDOTS:
|
|
DEC SI
|
|
GOTDOTNAME:
|
|
DEC SI
|
|
XOR AL,AL
|
|
return
|
|
nametrans ENDP
|
|
|
|
SUBTTL BUILDFCB -- MAKE A BLANK FCB FOR A DEVICE
|
|
PAGE
|
|
procedure BuildFCB,near
|
|
ASSUME DS:DOSGROUP,ES:DOSGROUP
|
|
|
|
; Function:
|
|
; Build a blank FCB for I/O to a device
|
|
; Outputs:
|
|
; Same as GETNAME
|
|
|
|
MOV AX," "
|
|
MOV DI,OFFSET DOSGROUP:DEVFCB+8 ; Point to extent field
|
|
STOSW
|
|
STOSB ; Blank out extent field
|
|
XOR AX,AX
|
|
MOV CX,10
|
|
REP STOSW ; Fill FCB with zeros
|
|
STOSB
|
|
invoke DATE16
|
|
MOV DI,OFFSET DOSGROUP:DEVFCB+22
|
|
XCHG AX,DX
|
|
STOSW
|
|
XCHG AX,DX
|
|
STOSW
|
|
XCHG AX,BX ; But device number in AH
|
|
MOV BX,OFFSET DOSGROUP:DEVFCB
|
|
MOV SI,DI
|
|
XOR AL,AL ; Set zero, clear carry
|
|
return
|
|
BuildFCB ENDP
|
|
|
|
SUBTTL MOVENAME, LODNAME -- EXAMINE FCB AND SETUP
|
|
PAGE
|
|
procedure FCB_move,NEAR
|
|
|
|
entry MOVNAMENOSET
|
|
MOV DI,1
|
|
JMP SHORT MOVSTART
|
|
|
|
entry MOVNAME
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
|
|
; Inputs:
|
|
; DS, DX point to FCB or extended FCB
|
|
; Outputs:
|
|
; DS:DX point to normal FCB
|
|
; DS:SI point after end of NAME/EXT in FCB
|
|
; ES = DOSGROUP
|
|
; If file name OK:
|
|
; [NAME1] has name in upper case
|
|
; All registers destroyed
|
|
; Carry set if bad file name or drive
|
|
|
|
XOR DI,DI
|
|
MOVSTART:
|
|
MOV WORD PTR [CREATING],0E500H ; Not creating, not DEL *.*
|
|
MOV SI,DX
|
|
LODSB
|
|
MOV [EXTFCB],AL ; Set flag if extended FCB in use
|
|
XOR AH,AH ; Set default attributes
|
|
CMP AL,-1 ; Is it an extended FCB?
|
|
JNZ HAVATTRB
|
|
ADD DX,7 ; Adjust to point to normal FCB
|
|
ADD SI,6
|
|
MOV AH,[SI-1] ; Attribute byte
|
|
LODSB ; Get drive select byte
|
|
HAVATTRB:
|
|
invoke GETTHISDRV
|
|
retc
|
|
PUSH DS
|
|
PUSH DX
|
|
PUSH SI
|
|
PUSH AX
|
|
;
|
|
; DS:DX is pointer to good FCB
|
|
; DS:SI is same
|
|
;
|
|
; Move the file into Name1 and UCASE it
|
|
;
|
|
PUSH DI
|
|
context ES
|
|
MOV DI,OFFSET DOSGROUP:NAME1
|
|
CALL LodName
|
|
POP DI
|
|
JC DrvNoSet
|
|
|
|
;
|
|
; are we setting current dir info?
|
|
;
|
|
OR DI,DI
|
|
JNZ DrvNoSet ; do not set dir info
|
|
|
|
;
|
|
; check for device name first, eliminating drive hits on devices
|
|
;
|
|
context DS
|
|
invoke DEVNAME
|
|
JNC DrvNoSet ; we have a device
|
|
|
|
;
|
|
; make sure that everything is current
|
|
;
|
|
invoke FATREAD
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
MOV BYTE PTR [ATTRIB],attr_directory+attr_hidden+attr_system
|
|
invoke GETCURRDIR
|
|
DrvNoSet:
|
|
POP AX
|
|
MOV BYTE PTR [ATTRIB],AH
|
|
|
|
POP SI
|
|
POP DX
|
|
POP DS
|
|
context ES
|
|
MOV DI,OFFSET DOSGROUP:NAME1
|
|
|
|
entry LODNAME
|
|
; Inputs: DS:SI point to an FCB
|
|
; ES:DI point to an FCB
|
|
; Outputs: DS:SI point to after FCB
|
|
; ES:DI point to after FCB
|
|
; FCB from DS:SI copied and ucased to ES:DI
|
|
; Carry set if there was an error.
|
|
; Destroys AX,CX
|
|
CMP BYTE PTR [SI]," " ; Don't allow blank as first letter
|
|
STC ; In case of error
|
|
retz
|
|
|
|
IF KANJI
|
|
MOV CX,8
|
|
CMP BYTE PTR [SI],0E5H
|
|
JNZ MOVCHK
|
|
INC SI
|
|
MOV AL,5
|
|
STOSB
|
|
MOVSB
|
|
MOV CX,6
|
|
MOVCHK:
|
|
CALL GETLET
|
|
JB RET6
|
|
JNZ STOLET ; Is it a delimiter?
|
|
CMP AL," " ; This is the only delimiter allowed
|
|
STC ; In case of error
|
|
JNZ RET6
|
|
STOLET:
|
|
STOSB
|
|
CALL TESTKANJ
|
|
JZ MOVLP ;No
|
|
LODSB ;Get second byte
|
|
DEC CX
|
|
JZ BOUNDERR ;Attempt to cross boundry
|
|
STOSB
|
|
MOVLP:
|
|
LOOP MOVCHK
|
|
MOV CX,3
|
|
MOVCHK2:
|
|
CALL GETLET
|
|
JB RET6
|
|
JNZ STOLET2 ; Is it a delimiter?
|
|
CMP AL," " ; This is the only delimiter allowed
|
|
STC ; In case of error
|
|
retnz
|
|
STOLET2:
|
|
STOSB
|
|
CALL TESTKANJ
|
|
JZ MOVLP2 ;No
|
|
LODSB ;Get second byte
|
|
DEC CX
|
|
JNZ DOSTORE
|
|
BOUNDERR: ;Attempt to cross boundry
|
|
STC
|
|
return
|
|
|
|
DOSTORE:
|
|
STOSB
|
|
MOVLP2:
|
|
LOOP MOVCHK2
|
|
ELSE
|
|
MOV CX,11
|
|
MOVCHK:
|
|
CALL GETLET
|
|
JB RET6
|
|
JNZ STOLET ; Is it a delimiter?
|
|
CMP AL," " ; This is the only delimiter allowed
|
|
STC ; In case of error
|
|
retnz
|
|
STOLET:
|
|
STOSB
|
|
LOOP MOVCHK
|
|
ENDIF
|
|
|
|
CLC ; Got through whole name - no error
|
|
RET6: return
|
|
FCB_Move ENDP
|
|
|
|
SUBTTL GETLET, DELIM -- CHECK CHARACTERS AND CONVERT
|
|
PAGE
|
|
procedure GetLet,NEAR
|
|
; 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).
|
|
LODSB
|
|
|
|
CMP AL,"a"
|
|
JB CHK1
|
|
CMP AL,"z"
|
|
JA CHK1
|
|
SUB AL,20H ; Convert to upper case
|
|
CHK1:
|
|
PUSH SI
|
|
MOV SI,[Current_Country]
|
|
ADD SI,Map_call
|
|
PUSH CS ; CS for long return
|
|
CALL WORD PTR CS:[SI]
|
|
POP SI
|
|
entry CHK
|
|
CMP AL,"."
|
|
retz
|
|
CMP AL,'"'
|
|
retz
|
|
CALL PATHCHRCMP
|
|
retz
|
|
CMP AL,"["
|
|
retz
|
|
CMP AL,"]"
|
|
retz
|
|
|
|
DELIM:
|
|
CMP AL,":" ; Allow ":" as separator in IBM version
|
|
retz
|
|
|
|
CMP AL,"<"
|
|
retz
|
|
CMP AL,"|"
|
|
retz
|
|
CMP AL,">"
|
|
retz
|
|
|
|
CMP AL,"+"
|
|
retz
|
|
CMP AL,"="
|
|
retz
|
|
CMP AL,";"
|
|
retz
|
|
CMP AL,","
|
|
retz
|
|
SPCHK:
|
|
CMP AL,9 ; Filter out tabs too
|
|
retz
|
|
; WARNING! " " MUST be the last compare
|
|
CMP AL," "
|
|
return
|
|
GetLet ENDP
|
|
|
|
procedure PATHCHRCMP,NEAR
|
|
CMP AL,'/'
|
|
retz
|
|
CMP AL,'\'
|
|
return
|
|
PathChrCMP ENDP
|
|
|
|
IF KANJI
|
|
procedure TESTKANJ,NEAR
|
|
CMP AL,81H
|
|
JB NOTLEAD
|
|
CMP AL,9FH
|
|
JBE ISLEAD
|
|
CMP AL,0E0H
|
|
JB NOTLEAD
|
|
CMP AL,0FCH
|
|
JBE ISLEAD
|
|
NOTLEAD:
|
|
PUSH AX
|
|
XOR AX,AX ;Set zero
|
|
POP AX
|
|
return
|
|
|
|
ISLEAD:
|
|
PUSH AX
|
|
XOR AX,AX ;Set zero
|
|
INC AX ;Reset zero
|
|
POP AX
|
|
return
|
|
TESTKANJ ENDP
|
|
ENDIF
|
|
do_ext
|
|
|
|
CODE ENDS
|
|
END
|