home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
tasm
/
ifindfil.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-28
|
11KB
|
286 lines
; FILENAME: IFINDFIL.ASM
;
; Copyright (c) 1988 by Borland International
;
; DESCRIPTION: This module implement a routine that performs a recursive
; search through a hard disk of a specified file.
;
; ASSEMBLY INSTRUCTIONS: To assemble this module use the following
; TASM command line.
;
; TASM /dMDL=memorymodel ifindfil
;
; 'memorymodel' in the above command line may be replaced by TINY, SMALL,
; MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
; a 286/386 machine, turn on the P286 directive in order to take advantage of
; 286/386 specific instructions. For example:
;
; TASM /dMDL=memorymodel /jP286 ifindfil
%tabsize 4
ifndef MDL
display "Error: This module requires that you provide a memory model"
display " definition on the command line. I.E. /dMDL=SMALL."
err ; Force a fatal error
else
ideal ; Use TASM's Ideal mode
model MDL ; Define the memory model
include "iwhglobl.inc"
include "imacros.mac"
include "idos.inc"
include "dos.inc"
include "idos.mac"
include "kbd.inc"
include "bios.inc"
include "ibios.mac"
dataseg
AllFiles db "*.*",0 ; ASCIIZ string representing all files
SwitchChar db 1,'\' ; Directory seperating character
CurrentDir db MAX_PATH_LENGTH dup (0)
MakePascalString BlankLine, <13, 10>
codeseg
macro NewLine ; Force a new line
ifdef _286_
push seg BlankLine
push offset BlankLine
else
mov ax, seg BlankLine
push ax
mov ax, offset BlankLine
push ax
endif
call WritePascalString
endm
proc FindFiles
; This routine does a recursive search down through the directory
; structure of a disk looking for a file. If the routine finds a
; match it displays the complete drive\path\filename. The routine
; uses the following algorithm:
;
; make room for a local copy of the Dta
; change directories to the location of the file we're looking for
; find all matches in the current directory
; for each sub-directory in the current directory
; Do a recursive call to this routine
; restore the original directory
;
; The routine uses the global variable FileSpec as the specification
; of the file to search for.
;
; Input
; DS - points to the segment in which FileSpec resides
; Path - A pascal style string representing the path in which to
; search for the file
; Output
; none
; Calling convention
; Pascal
; Registers modified
; ax, bx, cx, dx, si, es, flags
arg Path:byte:MAX_PATH_LENGTH=PARM_SIZE
local DataTransferArea:byte:DTA_SIZE=LOCAL_SIZE
push bp
mov bp, sp
; make room for the Dta, Drive, Path and Filename on the stack
sub sp, LOCAL_SIZE
mov si, bp ; Get the address of the Dta buffer
sub si, DTA_SIZE
push ds ; Store ds before call to SetDTA
SetDTA <ss>, <si> ; Set the current Dta address
pop ds ; Restore ds after SetDTA
if @CodeSize eq 0 ; FindFiles is near
add si, DTA_SIZE + 5 ; Get the address of the Path
else
add si, DTA_SIZE + 7 ; Get the address of the Path
endif
xor bx, bx
mov bl, [byte ss:si-1] ; Get the length byte
cmp bl, 1 ; Check if the path is 1 letter. If it
jle short ChangeDirs ; is we don't want to remove it.
cmp [byte ss:si+bx-1], '\' ; Check if the path ends with a '\'. If
jne short ChangeDirs ; it does, remove it.
mov [byte ss:si+bx-1], 0
dec [byte ss:si-1]
ChangeDirs:
push ds
ChangeDirectory <ss>, <si> ; Change the directory
GetCurrentDir <0>, <seg CurrentDir>, <offset CurrentDir>
pop ds
if (@Cpu and 100b) eq 100b
push seg CurrentDir
push offset CurrentDir
else
mov ax, seg CurrentDir
push ax
mov ax, offset CurrentDir
push ax
endif
mov ax, 0020h ; Replace spaces with 0
mov cx, MAX_PATH_LENGTH
call FindAndReplace
FindFirst <0FFh>, <ds>, <offset FileSpec + 1>
NextFile: ; Find each of the matching files
cmp ax, 0
jne CheckDirectories
GetKbdStatus
jz short NoKey
call Terminate
NoKey:
if (@Cpu and 100b) eq 100b
push seg Drive ; Get the address of the drive
push offset Drive ; description
else
mov ax, seg Drive
push ax
mov ax, offset Drive
push ax
endif
mov al, [Drive]
xor ah, ah
call WritePascalString ; Display the drive description
mov ax, seg CurrentDir
mov es, ax
mov di, offset CurrentDir
cmp [byte es:di], 'A' ; Check if the string is empty
jl short DontNeedBackSlash
dec di ; Decrement the offset of the pointer
DontNeedBackSlash:
push es
push di
call WriteASCIIZString
if (@Cpu and 100b) eq 100b
push seg SwitchChar
push offset SwitchChar
else
mov ax, seg SwitchChar
push ax
mov ax, offset SwitchChar
push ax
endif
call WritePascalString
push ss ; Pass the address of the filename
mov si, bp
sub si, DTA_SIZE - (offset (Dta).Filename)
push si
call WriteASCIIZString
NewLine
FindNext
jmp NextFile
CheckDirectories:
push ds
FindFirst <010000b>, <(seg AllFiles)>, <(offset AllFiles)>
pop ds
NextDirectory:
cmp ax, 0 ; Check if we've found a sub-directory
je CheckAttributes
jmp Exit
CheckAttributes: ; Check if it's a directory
mov si, bp ; Get the address of the attribute
sub si, DTA_SIZE - (offset (Dta).FileAttribute)
mov al, [byte ss:si] ; Get the directory entries attributes
and al, 10000b
cmp al, 10000b
jne short GetNextDirectory
; Check if the directory is '.' or '..'
mov si, bp ; Get the address of the attribute
sub si, DTA_SIZE - (offset (Dta).Filename)
cmp [byte ss:si], '.' ; If it's '.' or '..' then skip
je GetNextDirectory ; it
; Copy the new path onto the stack
sub sp, MAX_PATH_LENGTH ; Make room on the stack
mov bx, sp
push ss ; Push segment address of Path
mov si, bp
if @CodeSize eq 0 ; FindFiles is near
add si, 4 ; get offset of current path string
else
add si, 6
endif
push si ; Push offset of path
push ss ; Push address to copy to
push bx
mov al, [byte Path] ; Get the path length
inc al ; Copy the length byte also
call ByteCopy ; Copy the path onto the stack
; Append the new directory to the path on the stack
push es ; Save es:di before call to
push di ; GetASCIIZStrLen
mov si, bp ; Get the address of the current Dta
; Get the address of the directory name from it's location in the Dta
sub si, DTA_SIZE - (offset (Dta).Filename)
push ss ; Push the address of the directory
push si ; name
call GetASCIIZStrLen ; Get the length of the directory name
pop di ; Restore es:di
pop es
cmp [byte es:di-1], '\' ; Check if the path on the stack ends
je short HasBackSlash ; with a '\'. If not append one.
mov [byte es:di], '\'
inc di
push si
mov si, sp ; Adjust the length byte of the string
inc [byte ss:si+2]
pop si
HasBackSlash:
push ss ; Push the address of the directory
push si ; name
push es ; Push the address to copy the directory name to
push di
call ByteCopy ; Copy the directory name
mov si, sp ; Adjust the length byte of the string
dec al ; we appended to. Don't include the
add [byte ss:si], al ; terminating 0 in the length
; Do recursive call
call FindFiles ; Do the search for the file(s)
push ds
mov ax, bp
if @CodeSize eq 0 ; Near code models
add ax, 5
else
add ax, 7
endif
ChangeDirectory <ss>, <ax> ; Change to the directory that was
pop ds ; active before the recursive call
add sp, MAX_PATH_LENGTH ; Remove space allocated on the stack
mov si, bp
sub si, DTA_SIZE
push ds
SetDTA <ss>, <si> ; Restore the Dta
pop ds
GetNextDirectory:
FindNext ; Find the next sub-directory
jmp NextDirectory
Exit:
add sp, LOCAL_SIZE
pop bp
ret ; Let the caller clean up the stack
endp FindFiles
endif ; ifndef MDL
end