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