home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / tasm / ifindfil.asm < prev    next >
Assembly Source File  |  1988-08-28  |  11KB  |  286 lines

  1.  
  2. ;   FILENAME: IFINDFIL.ASM
  3. ;
  4. ;   Copyright (c) 1988 by Borland International
  5. ;
  6. ;   DESCRIPTION:  This module implement a routine that performs a recursive
  7. ;   search through a hard disk of a specified file.
  8. ;
  9. ;   ASSEMBLY INSTRUCTIONS: To assemble this module use the following
  10. ;   TASM command line.
  11. ;
  12. ;       TASM /dMDL=memorymodel ifindfil
  13. ;
  14. ;   'memorymodel' in the above command line may be replaced by TINY, SMALL,
  15. ;   MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
  16. ;   a 286/386 machine, turn on the P286 directive in order to take advantage of
  17. ;   286/386 specific instructions. For example:
  18. ;
  19. ;       TASM /dMDL=memorymodel /jP286 ifindfil
  20.  
  21. %tabsize 4
  22.  
  23. ifndef  MDL
  24.     display "Error: This module requires that you provide a memory model"
  25.     display "    definition on the command line. I.E. /dMDL=SMALL."
  26.     err ; Force a fatal error
  27. else
  28.  
  29.     ideal                   ; Use TASM's Ideal mode
  30.     model   MDL             ; Define the memory model
  31.  
  32.     include "iwhglobl.inc"
  33.     include "imacros.mac"
  34.     include "idos.inc"
  35.     include "dos.inc"
  36.     include "idos.mac"
  37.     include "kbd.inc"
  38.     include "bios.inc"
  39.     include "ibios.mac"
  40.  
  41.     dataseg
  42.         AllFiles    db  "*.*",0     ; ASCIIZ string representing all files
  43.         SwitchChar  db  1,'\'       ; Directory seperating character
  44.         CurrentDir  db  MAX_PATH_LENGTH dup (0)
  45.         MakePascalString BlankLine, <13, 10>
  46.  
  47.     codeseg
  48.  
  49.     macro   NewLine                 ; Force a new line
  50.         ifdef  _286_
  51.             push    seg BlankLine
  52.             push    offset BlankLine
  53.         else
  54.             mov     ax, seg BlankLine
  55.             push    ax
  56.             mov     ax, offset BlankLine
  57.             push    ax
  58.         endif
  59.         call    WritePascalString
  60.     endm
  61.  
  62.  
  63.     proc    FindFiles
  64.  
  65.     ;   This routine does a recursive search down through the directory
  66.     ;   structure of a disk looking for a file. If the routine finds a
  67.     ;   match it displays the complete drive\path\filename. The routine
  68.     ;   uses the following algorithm:
  69.     ;
  70.     ;       make room for a local copy of the Dta
  71.     ;       change directories to the location of the file we're looking for
  72.     ;       find all matches in the current directory
  73.     ;       for each sub-directory in the current directory
  74.     ;           Do a recursive call to this routine
  75.     ;       restore the original directory
  76.     ;
  77.     ;   The routine uses the global variable FileSpec as the specification
  78.     ;   of the file to search for.
  79.     ;
  80.     ;   Input
  81.     ;       DS - points to the segment in which FileSpec resides
  82.     ;       Path - A pascal style string representing the path in which to
  83.     ;              search for the file
  84.     ;   Output
  85.     ;       none
  86.     ;   Calling convention
  87.     ;       Pascal
  88.     ;   Registers modified
  89.     ;       ax, bx, cx, dx, si, es, flags
  90.  
  91.     arg     Path:byte:MAX_PATH_LENGTH=PARM_SIZE
  92.     local   DataTransferArea:byte:DTA_SIZE=LOCAL_SIZE
  93.  
  94.         push    bp
  95.         mov     bp, sp
  96.  
  97.         ; make room for the Dta, Drive, Path and Filename on the stack
  98.  
  99.         sub     sp, LOCAL_SIZE
  100.         mov     si, bp                  ; Get the address of the Dta buffer
  101.         sub     si, DTA_SIZE
  102.         push    ds                      ; Store ds before call to SetDTA
  103.         SetDTA  <ss>, <si>              ; Set the current Dta address
  104.         pop     ds                      ; Restore ds after SetDTA
  105.         if @CodeSize eq 0               ; FindFiles is near
  106.             add     si, DTA_SIZE + 5    ; Get the address of the Path
  107.         else
  108.             add     si, DTA_SIZE + 7    ; Get the address of the Path
  109.         endif
  110.         xor     bx, bx
  111.         mov     bl, [byte ss:si-1]      ; Get the length byte
  112.         cmp     bl, 1                   ; Check if the path is 1 letter. If it
  113.         jle     short ChangeDirs        ; is we don't want to remove it.
  114.         cmp     [byte ss:si+bx-1], '\'  ; Check if the path ends with a '\'. If
  115.         jne     short ChangeDirs        ; it does, remove it.
  116.         mov     [byte ss:si+bx-1], 0
  117.         dec     [byte ss:si-1]
  118.     ChangeDirs:
  119.         push    ds
  120.         ChangeDirectory <ss>, <si>      ; Change the directory
  121.         GetCurrentDir   <0>, <seg CurrentDir>, <offset CurrentDir>
  122.         pop     ds
  123.         if (@Cpu and 100b) eq 100b
  124.             push    seg CurrentDir
  125.             push    offset CurrentDir
  126.         else
  127.             mov     ax, seg CurrentDir
  128.             push    ax
  129.             mov     ax, offset CurrentDir
  130.             push    ax
  131.         endif
  132.         mov     ax, 0020h               ; Replace spaces with 0
  133.         mov     cx, MAX_PATH_LENGTH
  134.         call    FindAndReplace
  135.         FindFirst   <0FFh>, <ds>, <offset FileSpec + 1>
  136.     NextFile:                           ; Find each of the matching files
  137.         cmp     ax, 0
  138.         jne     CheckDirectories
  139.         GetKbdStatus
  140.         jz      short NoKey
  141.         call    Terminate
  142.     NoKey:
  143.         if (@Cpu and 100b) eq 100b
  144.             push    seg Drive           ; Get the address of the drive
  145.             push    offset Drive        ; description
  146.         else
  147.             mov     ax, seg Drive
  148.             push    ax
  149.             mov     ax, offset Drive
  150.             push    ax
  151.         endif
  152.         mov     al, [Drive]
  153.         xor     ah, ah
  154.         call    WritePascalString       ; Display the drive description
  155.         mov     ax, seg CurrentDir
  156.         mov     es, ax
  157.         mov     di, offset CurrentDir
  158.         cmp     [byte es:di], 'A'       ; Check if the string is empty
  159.         jl      short DontNeedBackSlash
  160.         dec     di                      ; Decrement the offset of the pointer
  161.     DontNeedBackSlash:
  162.         push    es
  163.         push    di
  164.         call    WriteASCIIZString
  165.         if (@Cpu and 100b) eq 100b
  166.             push    seg SwitchChar
  167.             push    offset SwitchChar
  168.         else
  169.             mov     ax, seg SwitchChar
  170.             push    ax
  171.             mov     ax, offset SwitchChar
  172.             push    ax
  173.         endif
  174.         call    WritePascalString
  175.         push    ss                      ; Pass the address of the filename
  176.         mov     si, bp
  177.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  178.         push    si
  179.         call    WriteASCIIZString
  180.         NewLine
  181.         FindNext
  182.         jmp     NextFile
  183.     CheckDirectories:
  184.         push    ds
  185.         FindFirst   <010000b>, <(seg AllFiles)>, <(offset AllFiles)>
  186.         pop     ds
  187.     NextDirectory:
  188.         cmp     ax, 0                   ; Check if we've found a sub-directory
  189.         je      CheckAttributes
  190.         jmp     Exit
  191.     CheckAttributes:                    ; Check if it's a directory
  192.         mov     si, bp                  ; Get the address of the attribute
  193.         sub     si, DTA_SIZE - (offset (Dta).FileAttribute)
  194.         mov     al, [byte ss:si]        ; Get the directory entries attributes
  195.         and     al, 10000b
  196.         cmp     al, 10000b
  197.         jne     short GetNextDirectory
  198.  
  199.         ; Check if the directory is '.' or '..'
  200.  
  201.         mov     si, bp                  ; Get the address of the attribute
  202.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  203.         cmp     [byte ss:si], '.'       ; If it's '.' or '..' then skip
  204.         je      GetNextDirectory        ; it
  205.  
  206.         ; Copy the new path onto the stack
  207.  
  208.         sub     sp, MAX_PATH_LENGTH     ; Make room on the stack
  209.         mov     bx, sp
  210.         push    ss                      ; Push segment address of Path
  211.         mov     si, bp
  212.         if @CodeSize eq 0               ; FindFiles is near
  213.             add     si, 4               ; get offset of current path string
  214.         else
  215.             add     si, 6
  216.         endif
  217.         push    si                      ; Push offset of path
  218.         push    ss                      ; Push address to copy to
  219.         push    bx
  220.         mov     al, [byte Path]         ; Get the path length
  221.         inc     al                      ; Copy the length byte also
  222.         call    ByteCopy                ; Copy the path onto the stack
  223.  
  224.         ; Append the new directory to the path on the stack
  225.  
  226.         push    es                      ; Save es:di before call to
  227.         push    di                      ; GetASCIIZStrLen
  228.         mov     si, bp                  ; Get the address of the current Dta
  229.  
  230.         ; Get the address of the directory name from it's location in the Dta
  231.  
  232.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  233.         push    ss                      ; Push the address of the directory
  234.         push    si                      ; name
  235.         call    GetASCIIZStrLen         ; Get the length of the directory name
  236.         pop     di                      ; Restore es:di
  237.         pop     es
  238.         cmp     [byte es:di-1], '\'     ; Check if the path on the stack ends
  239.         je      short HasBackSlash      ; with a '\'. If not append one.
  240.         mov     [byte es:di], '\'
  241.         inc     di
  242.         push    si
  243.         mov     si, sp                  ; Adjust the length byte of the string
  244.         inc     [byte ss:si+2]
  245.         pop     si
  246.     HasBackSlash:
  247.         push    ss                      ; Push the address of the directory
  248.         push    si                      ; name
  249.         push    es          ; Push the address to copy the directory name to
  250.         push    di
  251.         call    ByteCopy                ; Copy the directory name
  252.         mov     si, sp                  ; Adjust the length byte of the string
  253.         dec     al                      ; we appended to. Don't include the
  254.         add     [byte ss:si], al        ; terminating 0 in the length
  255.  
  256.         ; Do recursive call
  257.  
  258.         call    FindFiles               ; Do the search for the file(s)
  259.         push    ds
  260.         mov     ax, bp
  261.         if  @CodeSize eq 0              ; Near code models
  262.             add     ax, 5
  263.         else
  264.             add     ax, 7
  265.         endif
  266.         ChangeDirectory <ss>, <ax>      ; Change to the directory that was
  267.         pop     ds                      ; active before the recursive call
  268.         add     sp, MAX_PATH_LENGTH     ; Remove space allocated on the stack
  269.         mov     si, bp
  270.         sub     si, DTA_SIZE
  271.         push    ds
  272.         SetDTA  <ss>, <si>              ; Restore the Dta
  273.         pop     ds
  274.     GetNextDirectory:
  275.         FindNext                        ; Find the next sub-directory
  276.         jmp     NextDirectory
  277.     Exit:
  278.         add     sp, LOCAL_SIZE
  279.         pop     bp
  280.         ret                             ; Let the caller clean up the stack
  281.     endp    FindFiles
  282.  
  283. endif   ; ifndef MDL
  284.  
  285. end
  286.