home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_7 / 6.ddi / TAEXMPL1.ZIP / IFINDFIL.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-02-13  |  13.4 KB  |  373 lines

  1.  
  2. ;   FILENAME: IFINDFIL.ASM
  3. ;
  4. ;   Copyright (c) 1988, 1990 by Borland International, Inc.
  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. jumps
  22.  
  23. %tabsize 4
  24.  
  25. ifndef  MDL
  26.     display "Error: This module requires that you provide a memory model"
  27.     display "    definition on the command line. I.E. /dMDL=SMALL."
  28.     err ; Force a fatal error
  29. else
  30.     ideal                   ; Use TASM's Ideal mode
  31.     model   MDL,pascal      ; Define the memory model
  32.  
  33.     include "iwhglobl.inc"
  34.     include "imacros.mac"
  35.     include "idos.inc"
  36.     include "dos.inc"
  37.     include "idos.mac"
  38.     include "kbd.inc"
  39.     include "bios.inc"
  40.     include "ibios.mac"
  41.  
  42.     dataseg
  43.         AllFiles    db  "*.*",0     ; ASCIIZ string representing all files
  44.         SwitchChar  db  1,'\'       ; Directory seperating character
  45.         CurrentDir  db  MAX_PATH_LENGTH dup (0)
  46.         MakePascalString BlankLine, <13, 10>
  47.  
  48.         ; The following variable keep track of going through the
  49.         ; file specifications that were given on the command line.
  50.         FileSpecIndex db ?
  51.         FileSpecPtr   dw ?
  52.  
  53.  
  54.     codeseg
  55.  
  56.     macro   NewLine                 ; Force a new line
  57. ;;        ifdef  _286_
  58. ;;            push    seg BlankLine
  59. ;;            push    offset BlankLine
  60. ;;        else
  61. ;;            mov     ax, seg BlankLine
  62. ;;            push    ax
  63. ;;            mov     ax, offset BlankLine
  64. ;;            push    ax
  65. ;;        endif
  66.         call    WritePascalString,seg BlankLine,offset BlankLine
  67.     endm
  68.  
  69. TerminateKeyMssg db 13,10
  70.                  db '**ERROR** Whereis terminated due to keypress.'
  71.                  db 13,10,0
  72.  
  73.     ; The following messages should not include a line feed.
  74. PauseKeyMssg      db 'Press space to continue....',13,0
  75. PauseKeyEraseMssg db '                           ',13,0
  76.  
  77.     proc    FindFiles
  78.  
  79.     ;   This routine does a recursive search down through the directory
  80.     ;   structure of a disk looking for a file. If the routine finds a
  81.     ;   match it displays the complete drive\path\filename. The routine
  82.     ;   uses the following algorithm:
  83.     ;
  84.     ;       make room for a local copy of the Dta
  85.     ;       change directories to the location of the file we're looking for
  86.     ;       find all matches in the current directory
  87.     ;       for each sub-directory in the current directory
  88.     ;           Do a recursive call to this routine
  89.     ;       restore the original directory
  90.     ;
  91.     ;   The routine uses the global variable FileSpec as the specification
  92.     ;   of the file to search for.
  93.     ;   If any key is pressed, a message is printed and then this routine
  94.     ;   calls Terminate.
  95.     ;
  96.     ;   Input
  97.     ;       DS - points to the segment in which FileSpec resides
  98.     ;       Path - A pascal style string representing the path in which to
  99.     ;              search for the file
  100.     ;   Output
  101.     ;       none
  102.     ;   Calling convention
  103.     ;       Pascal
  104.     ;   Registers modified
  105.     ;       ax, bx, cx, dx, si, es, flags
  106.  
  107.     arg     Path:byte:MAX_PATH_LENGTH=PARM_SIZE
  108.     local   DataTransferArea:byte:DTA_SIZE=LOCAL_SIZE ;
  109.  
  110.     ; The PASCAL calling convention on the MODEL statement causes TASM
  111.     ; to do the following automatically.
  112. ;        push    bp
  113. ;        mov     bp, sp
  114. ;        ; make room for the Dta, Drive, Path and Filename on the stack
  115. ;        sub     sp, LOCAL_SIZE
  116.  
  117.         mov     [FileSpecIndex],1       ; Keep track which one we are searching
  118.         mov     [FileSpecPtr],offset FileSpec
  119.  
  120.  
  121.         mov     si, bp                  ; Get the address of the Dta buffer
  122.         sub     si, DTA_SIZE
  123.         push    ds                      ; Store ds before call to SetDTA
  124.         SetDTA  <ss>, <si>              ; Set the current Dta address
  125.         pop     ds                      ; Restore ds after SetDTA
  126.         if @CodeSize eq 0               ; FindFiles is near
  127.             add     si, DTA_SIZE + 5    ; Get the address of the Path
  128.         else
  129.             add     si, DTA_SIZE + 7    ; Get the address of the Path
  130.         endif
  131.  
  132.         xor     bx, bx
  133.         mov     bl, [byte ss:si-1]      ; Get the length byte
  134.         cmp     bl, 1                   ; Check if the path is 1 letter. If it
  135.         jle     ChangeDirs              ; is we don't want to remove it.
  136.         cmp     [byte ss:si+bx-1], '\'  ; Check if the path ends with a '\'. If
  137.         jne     ChangeDirs              ; it does, remove it.
  138.         mov     [byte ss:si+bx-1], 0
  139.         dec     [byte ss:si-1]
  140.     ChangeDirs:
  141.         push    ds
  142.         ChangeDirectory <ss>, <si>      ; Change the directory
  143.         GetCurrentDir   <0>, <seg CurrentDir>, <offset CurrentDir>
  144.         pop     ds
  145.         if (@Cpu and 100b) eq 100b
  146.             push    seg CurrentDir
  147.             push    offset CurrentDir
  148.         else
  149.             mov     ax, seg CurrentDir
  150.             push    ax
  151.             mov     ax, offset CurrentDir
  152.             push    ax
  153.         endif
  154.         mov     ax, 0020h               ; Replace spaces with 0
  155.         mov     cx, MAX_PATH_LENGTH
  156.         call    FindAndReplace
  157.  
  158.     FirstFile:
  159.         mov     ax,[FileSpecPtr]
  160.         inc     ax                      ; Get past length byte
  161.         FindFirst   <0FFh>, <ds>, <ax>
  162.     NextFile:                           ; Find each of the matching files
  163.         cmp     ax, 0
  164.         jne     CheckNextFileSpec
  165.  
  166.         ; Check if the user has pressed a key to interrupt WHEREIS.
  167.         GetKbdStatus
  168.         jz      NoKey
  169.  
  170.         ; Throw out the key(s) that were pressed.
  171.     DiscardKeys:
  172.         GetChar
  173.         cmp     al,' '          ; Check for space pressed to pause
  174.         je      JustPausing
  175.         cmp     al,'s'-'a'+1    ; Check for ^S pressed to pause
  176.         je      JustPausing
  177.  
  178.     FlushKeyboard:
  179.         GetKbdStatus
  180.         jz   GiveAbortMessage
  181.         GetChar
  182.         jmp  FlushKeyboard
  183.  
  184.     GiveAbortMessage:
  185.         ; Give a message to the user that WHEREIS is terminating.
  186.         call    WriteASCIIZString,seg TerminateKeyMssg,offset TerminateKeyMssg
  187.  
  188.         call    Terminate
  189.  
  190.     JustPausing:
  191.         ; Give a message to the user that WHEREIS is pausing
  192.         call    WriteASCIIZString,seg PauseKeyMssg,offset PauseKeyMssg
  193.  
  194.     WaitForSpace:
  195.         GetKbdStatus
  196.         jz   WaitForSpace
  197.         GetChar
  198.         cmp  al,' '
  199.         jne  FlushKeyboard
  200.  
  201.         ; Now get rid of the reminder
  202.         call    WriteASCIIZString,seg PauseKeyEraseMssg,offset PauseKeyEraseMssg
  203.  
  204.     NoKey:
  205.         if (@Cpu and 100b) eq 100b
  206.             push    seg Drive           ; Get the address of the drive
  207.             push    offset Drive        ; description
  208.         else
  209.             mov     ax, seg Drive
  210.             push    ax
  211.             mov     ax, offset Drive
  212.             push    ax
  213.         endif
  214.         mov     al, [Drive]
  215.         xor     ah, ah
  216.         call    WritePascalString       ; Display the drive description
  217.         mov     ax, seg CurrentDir
  218.         mov     es, ax
  219.         mov     di, offset CurrentDir
  220.         cmp     [byte es:di], 'A'       ; Check if the string is empty
  221.         jl      DontNeedBackSlash
  222.         dec     di                      ; Decrement the offset of the pointer
  223.     DontNeedBackSlash:
  224.         push    es
  225.         push    di
  226.         call    WriteASCIIZString
  227.         if (@Cpu and 100b) eq 100b
  228.             push    seg SwitchChar
  229.             push    offset SwitchChar
  230.         else
  231.             mov     ax, seg SwitchChar
  232.             push    ax
  233.             mov     ax, offset SwitchChar
  234.             push    ax
  235.         endif
  236.         call    WritePascalString
  237.  
  238.         mov     si, bp
  239.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  240.         push    ss  si  ; Push an extra copy of offset of filename
  241.  
  242.         ; Write the filename. Pass the address of the filename
  243.         call    WriteASCIIZString,ss,si
  244.         NewLine
  245.  
  246.         pop     si ax  ; Offset of filename   ax:si
  247.         mov     di,offset CurrentDir
  248.         push    ds                      ; Store ds before call to
  249.                                         ; ExecuteDosCommand and SetDTA
  250.         call    ExecuteDosCommand       ; Do the command for the file.
  251.  
  252.         mov     si, bp                  ; Get the address of the Dta buffer
  253.         sub     si, DTA_SIZE
  254.         SetDTA  <ss>, <si>              ; Set the current Dta address
  255.         pop     ds                      ; Restore ds after SetDTA
  256.  
  257.         FindNext
  258.         jmp     NextFile
  259.  
  260.     CheckNextFileSpec:
  261.         add     [FileSpecPtr],FILE_SPEC_SIZE    ; Point to next filespec
  262.         mov     al,[FileSpecIndex]              ; Bump up counter
  263.         inc     al
  264.         mov     [FileSpecIndex],al
  265.         cmp     al,[FileSpecCounter]
  266.         jle     FirstFile                       ; Go back to search another filespec
  267.  
  268.     CheckDirectories:
  269.         push    ds
  270.         FindFirst   <010000b>, <(seg AllFiles)>, <(offset AllFiles)>
  271.         pop     ds
  272.     NextDirectory:
  273.         cmp     ax, 0                   ; Check if we've found a sub-directory
  274.         je      CheckAttributes
  275.         jmp     Exit
  276.     CheckAttributes:                    ; Check if it's a directory
  277.         mov     si, bp                  ; Get the address of the attribute
  278.         sub     si, DTA_SIZE - (offset (Dta).FileAttribute)
  279.         mov     al, [byte ss:si]        ; Get the directory entries attributes
  280.         and     al, 10000b
  281.         cmp     al, 10000b
  282.         jne     GetNextDirectory
  283.  
  284.         ; Check if the directory is '.' or '..'
  285.  
  286.         mov     si, bp                  ; Get the address of the attribute
  287.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  288.         cmp     [byte ss:si], '.'       ; If it's '.' or '..' then skip
  289.         je      GetNextDirectory        ; it
  290.  
  291.         ; Copy the new path onto the stack
  292.  
  293.         sub     sp, MAX_PATH_LENGTH     ; Make room on the stack
  294.         mov     bx, sp
  295.         push    ss                      ; Push segment address of Path
  296.         mov     si, bp
  297.         if @CodeSize eq 0               ; FindFiles is near
  298.             add     si, 4               ; get offset of current path string
  299.         else
  300.             add     si, 6
  301.         endif
  302.         push    si                      ; Push offset of path
  303.         push    ss                      ; Push address to copy to
  304.         push    bx
  305.         mov     al, [byte Path]         ; Get the path length
  306.         inc     al                      ; Copy the length byte also
  307.         call    ByteCopy                ; Copy the path onto the stack
  308.  
  309.         ; Append the new directory to the path on the stack
  310.  
  311.         push    es di                   ; Save es:di before call to
  312.                                         ; GetASCIIZStrLen
  313.         mov     si, bp                  ; Get the address of the current Dta
  314.  
  315.         ; Get the address of the directory name from it's location in the Dta
  316.  
  317.         sub     si, DTA_SIZE - (offset (Dta).Filename)
  318.         call    GetASCIIZStrLen,ss,si   ; Get the length of the directory name
  319.         pop     di es                   ; Restore es:di
  320.  
  321.         cmp     [byte es:di-1], '\'     ; Check if the path on the stack ends
  322.         je      HasBackSlash            ; with a '\'. If not append one.
  323.         mov     [byte es:di], '\'
  324.         inc     di
  325.         push    si
  326.         mov     si, sp                  ; Adjust the length byte of the string
  327.         inc     [byte ss:si+2]
  328.         pop     si
  329.     HasBackSlash:
  330.         ; Copy the directory name
  331.         call    ByteCopy,ss,si, \       ; Address of the directory name.
  332.                          es,di          ; Address to copy directory name to
  333.  
  334.         mov     si, sp                  ; Adjust the length byte of the string
  335.         dec     al                      ; we appended to. Don't include the
  336.         add     [byte ss:si], al        ; terminating 0 in the length
  337.  
  338.         ; Do recursive call
  339.  
  340.         call    FindFiles               ; Do the search for the file(s)
  341.         push    ds
  342.         mov     ax, bp
  343.         if  @CodeSize eq 0              ; Near code models
  344.             add     ax, 5
  345.         else
  346.             add     ax, 7
  347.         endif
  348.         ChangeDirectory <ss>, <ax>      ; Change to the directory that was
  349.         pop     ds                      ; active before the recursive call
  350.  
  351. ;; Remember, the following cleanup is done automatically by Pascal Model.
  352. ;;        add     sp, MAX_PATH_LENGTH     ; Remove space allocated on the stack
  353.  
  354.         mov     si, bp
  355.         sub     si, DTA_SIZE
  356.         push    ds
  357.         SetDTA  <ss>, <si>              ; Restore the Dta
  358.         pop     ds
  359.     GetNextDirectory:
  360.         FindNext                        ; Find the next sub-directory
  361.         jmp     NextDirectory
  362.     Exit:
  363.  
  364.      ; Once again, the cleanup is done automatically because of PASCAL model.
  365. ;        add     sp, LOCAL_SIZE
  366. ;        pop     bp
  367.         ret
  368.     endp    FindFiles
  369.  
  370. endif   ; ifndef MDL
  371.  
  372. end
  373.