?? checkpat.asm
字號:
mov ax,ds
mov es,ax
;
; find the end of the string
;
xor ax,ax
mov cx,-1
repne scasb
mov si,di
pop es
pop di
not cx
dec cx
jnz has_fnp ; continue if there's more in the string
add sp,2
stosb ; terminate path string
jmp check_fname ; exit if no path or filename
;
; search from the end for slash/backslash
;
has_fnp:
sub si,2 ; last char of string
mov bx,5c2fh ; the two slashes
std ; backwards scan
;
spath:
lodsb
cmp al,bl
je pfound
cmp al,bh
je pfound
loop spath
;
; no slash/backslash -> no path given
;
cld
pop si
xor cx,cx
jmp short cfname
;
longpath:
mov ax,ERR_PATHLEN
jmp error_exit
;
; copy the path (note: CX has length of path including slash)
;
pfound:
cld
pop si
cmp cx,MAXPATH
ja longpath
or flags,HAS_PATH ; we have a path
ldes di,path
IFDEF PASCAL
inc di
ENDIF
push cx
rep movsb
pop cx
;
; check for special filenames '.' and '..', and add them to
; the path if present.
; The special form that adds a '.' for every level further down
; the tree is recognized, and translated into the DOS-form '..\'
;
cfname:
cmp byte ptr [si],'.'
jne path_finished
cmp byte ptr [si+1],'.'
je is_special
cmp byte ptr [si+1],0
jne path_finished
;
is_special:
or flags,HAS_PATH ; we have a path
mov bx,MAXPATH
sub bx,cx
mov cx,2
lodsb
;
copy_special:
or bx,bx
jz longpath
dec bx
stosb
lodsb
or al,al
jz special_finished
cmp al,'.'
jne badname
loop copy_special
;
add_special:
sub bx,3
jle longpath
mov al,'\'
stosb
mov al,'.'
stosb
stosb
lodsb
or al,al
jz special_finished
cmp al,'.'
jne badname
jmp add_special
;
badname:
mov ax,ERR_FNAME
jmp error_exit
;
special_finished:
dec si
mov al,'\'
stosb
;
; now copy the filename and extension (limited to 8/3 chars)
;
path_finished:
xor al,al ; terminate path
stosb
;
mov bx,2a3fh ; the two wildcards '*' and '?'
ldes di,fname
IFDEF PASCAL
inc di
ENDIF
mov cx,8 ; max 8 for name
;
cfnloop:
lodsb
or al,al ; end of string?
jz cfndot
cmp al,'.'
je cfndot
jcxz cfnloop ; skip if 8 chars copied
stosb
dec cx
or flags,HAS_FNAME
cmp al,bl ; check for wildcards
je fnwild
cmp al,bh
jne cfnloop
;
fnwild:
or flags,HAS_WILD
jmp cfnloop
;
cfndot:
mov ah,al ; save terminator (0 or '.')
xor al,al
stosb ; terminate filename
or ah,ah
jz no_ext ; jump if at end of string
;
; extension present, copy it.
;
or flags,HAS_EXT
ldes di,ext
IFDEF PASCAL
inc di
ENDIF
mov cx,3
mov al,ah
stosb ; store '.' as first ext char
;
cextloop:
lodsb
or al,al
jz cextend
stosb
cmp al,bl ; check for wildcards
je extwild
cmp al,bh
jne cextcont
;
extwild:
or flags,HAS_WILD
;
cextcont:
loop cextloop
;
cextend:
xor al,al
stosb ; terminate extension
;
;
no_ext:
test flags,HAS_PATH
jz check_fname
;
; A path was specified, check it:
; Change the current directory to the one specified.
; If valid, read back the new directory string
; (which has '.' and '..' resolved).
; In any case, restore the current directory.
;
ldes di,fullpath ; make path string from drive and path
IFDEF PASCAL
inc di
ENDIF
ldds si,drive
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,path
IFDEF PASCAL
inc si
ENDIF
call @strcpy
cmp byte ptr es:[di-2],':' ; root dir ?
je no_slstrip ; then don't strip backslash
mov byte ptr es:[di-1],0 ; else remove trailing '\'
;
no_slstrip:
xor cx,cx ; cx is 'path ok' flag (init to not ok)
ldds dx,fullpath
IFDEF PASCAL
inc dx
ENDIF
ldes di,path
IFDEF PASCAL
inc di
ENDIF
mov ah,3bh ; change current directory
int 21h
mov ds,dseg
jc rest_path ; skip dir reading if invalid
cmp fail,0
jne rest_path
;
; read back path
;
ldds si,path
IFDEF PASCAL
inc si
ENDIF
inc si ; leave space for leading '\'
mov ah,47h ; get current directory
mov dx,drv ; drive number
int 21h
mov ds,dseg
jc rest_path ; shouldn't happen, but...
cmp fail,0
jne rest_path
;
mov byte ptr es:[di],'\' ; prefix with '\'
xor ax,ax
mov cx,-1
repne scasb ; find end of string
not cx
cmp cx,2
je rest_path ; don't append trailing '\' if root
mov byte ptr es:[di-1],'\'
stosb ; terminate
;
rest_path:
mov dx,offset dfltpath
mov ah,3bh
int 21h
;
; was the path ok?
;
or cx,cx
jnz check_fname
;
; exit if not
;
mov ax,ERR_PATH
jmp error_exit
;
; the path was ok, now check the filename if it doesn't contain
; wildcard chars.
;
check_fname:
test flags,HAS_WILD
jz checkfn1
jmp ready
;
checkfn1:
ldesf di,fullpath ; make full path string
IFDEF PASCAL
inc di
ENDIF
lddsf si,drive
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,path
IFDEF PASCAL
inc si
ENDIF
call @strcpy
test flags,HAS_FNAME OR HAS_EXT
jnz checkfn2
;
; No filename, get the attribute of the directory
;
or flags,IS_DIR
dec di
mov byte ptr es:[di],0 ; clear trailing '\'
dec di
cmp byte ptr es:[di],':' ; root dir?
je no_dirchk ; then don't get attribute
ldds dx,fullpath
IFDEF PASCAL
inc dx
ENDIF
mov ax,4300h ; get attribute
int 21h
mov ds,dseg
jc no_attrib ; shouldn't happen
cmp fail,0
jne no_attrib
mov ax,flags
mov ah,cl
and ah,7fh
mov flags,ax
no_dirchk:
jmp ready
;
no_attrib:
mov ax,ERR_PATH
jmp error_exit
;
checkfn2:
ldds si,fname
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,ext
IFDEF PASCAL
inc si
ENDIF
call @strcpy
;
mov ah,2fh ; get current DTA
int 21h ; ES:BX has current DTA
push bx
push es
;
mov ds,dseg
mov dx,offset dfltpath
mov ah,1ah ; set DTA
int 21h
;
ldds dx,fullpath
IFDEF PASCAL
inc dx
ENDIF
mov cx,10110B ; search all except label
mov ah,4eh ; search for first
int 21h
mov ds,dseg
jc no_file
cmp fail,0
jne no_file
;
mov ax,flags
mov ah,dfltpath+15h ; file attributes into upper byte of flags
test ah,10h ; subdirectory?
jz no_subdir
;
; The filename specifies a subdirectory. Append it to the path.
;
test inflags,INF_NODIR
jnz no_file
ldesf di,path
IFDEF PASCAL
inc di
ENDIF
mov cx,-1
xor ax,ax
repne scasb
dec di
mov si,offset dfltpath+1eh
call @strcpy
mov al,'\'
stosb
xor al,al
stosb
ldes di,fname
IFDEF PASCAL
inc di
ENDIF
stosb
ldes di,ext
IFDEF PASCAL
inc di
ENDIF
stosb
mov ax,flags
mov ah,dfltpath+15h ; file attributes into upper byte of flags
and ah,7fh ; make sure it's positive
and al,NOT (HAS_FNAME OR HAS_EXT)
or al,HAS_PATH
mov flags,ax
jmp short no_file
;
no_subdir:
or al,FILE_EXISTS
and ah,7fh ; make sure it's positive
mov flags,ax
;
no_file:
pop ds
pop dx
mov ah,1ah
int 21h ; restore DTA
;
ready:
ldesf di,fullpath ; make full path string
IFDEF PASCAL
inc di
ENDIF
lddsf si,drive
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,path
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,fname
IFDEF PASCAL
inc si
ENDIF
call @strcpy
ldds si,ext
IFDEF PASCAL
inc si
ENDIF
call @strcpy
mov ds,dseg
mov ax,flags
;
error_exit:
mov ds,dseg
cmp fail,0
je nofail
mov ax,ERR_CRITICAL
;
nofail:
push ax
cmp ax,0
jge no_error
ldesf di,fullpath
mov word ptr es:[di],0
;
no_error:
lds dx,save24
mov ax,2524h
int 21h
IFDEF PASCAL
ldesf di,drive
call @strlen
ldes di,path
call @strlen
ldes di,fname
call @strlen
ldes di,ext
call @strlen
ldes di,fullpath
call @strlen
ENDIF
pop ax
;
ret
;
checkpath endp
;
;
;e Returns TRUE if a file with name 'fname' exists.
;d Liefert TRUE wenn eine Datei mit dem Namen 'fname' existiert.
;
IFDEF PASCAL
IFDEF FARCALL
exists PROC far uses ds, fname: dword
ELSE
exists PROC near uses ds, fname: dword
ENDIF
ELSE
exists PROC uses ds, fname: ptr byte
ENDIF
;
IFDEF TC_HUGE
mov ax,SEG my_data
mov ds,ax
ENDIF
;
IFDEF PASCAL
ldds si,fname
; for pascal, zero-terminate input string
lodsb
mov bl,al
xor bh,bh
mov [si+bx],bh
mov dx,si
ELSE
ldds dx,fname
ENDIF
;
mov ax,4300h ; get file attributes
int 21h
mov ax,0
jc exists_end
test cx,10h ; directory?
jnz exists_end
inc ax
;
exists_end:
ret
;
exists endp
;
end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -