home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_11 / 9.ddi / TAEXMPL1.ZIP / IWHEREIS.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-02-13  |  17.6 KB  |  533 lines

  1.  
  2. ;   FILENAME: IWHEREIS.ASM
  3. ;
  4. ;   Copyright (c) 1988, 1990 by Borland International, Inc.
  5. ;
  6. ;   DESCRIPTION:  This program does a search for the file(s) specified on the
  7. ;   command line. It can also perform a DOS command on each file that is
  8. ;   found.
  9. ;
  10. ; Syntax: WHEREIS [d:][path]filename filename filename... [dos_command]
  11. ;  dos_command is a command surrounded by "",'', or []. It will be called
  12. ;  for each file that is found. It should include at least one of these:
  13. ;     %1 - Insert full path, filename and extension
  14. ;     %2 - Filename and extension (no path)
  15. ;     %3 - Only the path.
  16. ;     %4 - Only the filename before the extension followed by a .
  17. ;     %5 - Only the extension, preceeded by a .
  18. ;  For example to delete all .BAK files on a drive:
  19. ;     WHEREIS  *.BAK [DEL %2]",13,10>
  20. ;
  21. ;   Note that dos_command may be any valid DOS command, including invoking
  22. ;   batch files or built-in DOS commands. Note that the RMDIR, (also RD),
  23. ;   command should not be used on the directory that WHEREIS is currently
  24. ;   executing in.
  25. ;
  26. ;
  27. ;   ASSEMBLY INSTRUCTIONS: To assemble this module use the following
  28. ;   TASM command line.
  29. ;
  30. ;       TASM /m /dMDL=memorymodel iwhereis
  31. ;
  32. ;   /m in the above command line allows TASM to use extra passes to resolve
  33. ;   jumps and other operations to their shortest form and get rid of extra NOPs.
  34. ;   'memorymodel' in the above command line may be replaced by TINY, SMALL,
  35. ;   MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
  36. ;   a 286/386 machine, turn on the P286 directive in order to take advantage of
  37. ;   286/386 specific instructions. For example:
  38. ;
  39. ;       TASM /m /dMDL=memorymodel /jP286 iwhereis
  40. ;
  41. ;   SYSTEM REQUIREMENTS:
  42. ;       TASM 2.0
  43. ;       256K
  44. ;       DOS 2.0 or later
  45.  
  46. ; TURBO ASSEMBLER NEW FEATURES:
  47. ; TASM 2.0 has many new features. The following is a list of a few of
  48. ; them that have been used to make this program easier and more readable.
  49. ; To find the examples in the code, just seach for "**n", where n is a
  50. ; number from the following table.
  51.  
  52. ; Special TASM 2.0 features:
  53. ;    **1  - TASM automatically pushes the immediate value in a way that
  54. ;           preserves all registers if the processor mode is 8086. If
  55. ;           186 or above, then TASM pushes the value directly.
  56. ;    **2  - Many lines of assembler are replaced by the use of the
  57. ;           extended call syntax.
  58. ;    **3  - Conditional jumps that go out of range are automatically
  59. ;           adjusted to a different code sequence that allows the
  60. ;           further jump. Other jumps, even if forward referenced, are
  61. ;           automatically changed to the shortest possible code sequence
  62. ;           without extra NOPs, because of multipass capability.
  63. ;    **4  - TASM handles forward referenced variables that occur
  64. ;           in a segment other than DS: by automatically inserting
  65. ;           the proper segment override, and without causing phase errors.
  66. ;    **5  - TASM's ability to handle multiple objects on a single
  67. ;           PUSH or POP command makes coding shorter.
  68. ;    **6  - TASM's new line continuation feature while in IDEAL mode
  69. ;           makes long argument lists very easy.
  70.  
  71.  
  72. jumps      ; Have TASM automatically resolve out of range jumps
  73.  
  74. %tabsize 4
  75.  
  76. ifndef  MDL
  77.     display "Error: This module requires that you provide a memory model"
  78.     display "    definition on the command line. I.E. /dMDL=SMALL."
  79.     err ; Force a fatal error
  80. else
  81.  
  82.     ideal                   ; Use TASM's Ideal mode
  83.     model   MDL,pascal      ; Define the memory model
  84.                             ; Set language to PASCAL so we can rely on TASM's
  85.                             ; new extended call features.
  86.  
  87.     Version EQU "2.0"
  88.  
  89.     include "iwhglobl.inc"  ; Public symbol declarations
  90.     include "imacros.mac"   ; Various macros
  91.     include "bios.inc"
  92.     include "ibios.mac"
  93.     include "kbd.inc"      ; Keyboard scan codes
  94.     include "dos.inc"      ; Equates representing DOS functions/services
  95.     include "idos.mac"
  96.  
  97.     stack   7FFFh           ; Allocate 32K stack
  98.  
  99.     dataseg
  100.  
  101.     PspAddress  dw  ?       ; Segment address of Program Segment Prefix(PSP)
  102.     DisplayPage db  0       ; Current display page
  103.     include "WHUSAGE.INC"   ; Usage screen declaration
  104.  
  105.     ; Pascal style strings to store the parsed file specification.
  106.  
  107.     Drive       db  0," :  "
  108.     Path        db  MAX_PATH_LENGTH  dup (0)
  109.  
  110.     ; Following is used as a scratchpad when parsing additional filespecs
  111.     ; from the command line.
  112.     tempDrive   db  0," :  "
  113.     tempPath    db  MAX_PATH_LENGTH  dup (0)
  114.  
  115.  
  116.     FileSpecCounter db 0    ; Count how many filespecs we parsed
  117.     NextFileSpec    dw 0    ; Location of where to put next filespec
  118.  
  119.     DrivePtr    dw   ?      ; Points to where the file parse routine should
  120.     PathPtr     dw   ?      ; place its results.
  121.  
  122.  
  123.     FileSpec    db  MAX_FILE_SPECS dup (FILE_SPEC_SIZE dup (0))
  124.                             ; Make room for the filenames, each with a
  125.                             ; preceeding length byte and terminating 0
  126.  
  127.     db  '\'
  128.     HomeDirectory   db  MAX_PATH_LENGTH dup (0)
  129.     OldDrive        db  ?
  130.  
  131.     ; When working through the arguments on the command line to setup
  132.     ; filespecs,
  133.     CurrentArgument db  MAX_PATH_LENGTH+FILE_SPEC_SIZE dup (0)
  134.  
  135.     codeseg
  136.  
  137.     proc    GetArgument
  138.     ;   This procedure gets an argument transfered into a temporary
  139.     ;   buffer where all leading spaces are removed from the string.
  140.     ;
  141.     ;   Input
  142.     ;       AL contains number of argument to get.
  143.     ;   Output
  144.     ;       If argument exists:
  145.     ;          AL number of argument
  146.     ;          ES:DI points to temporary argument buffer
  147.     ;       If argument does not exist:
  148.     ;          AL contains 0
  149.     ;   Calling conventions
  150.     ;       NA
  151.     ;   Registers modified
  152.     ;       all
  153.  
  154.         call    ParamString
  155.         or      al,al
  156.         jz      @@Finished      ; A zero return means no more arguments.
  157.         push    ax              ; Save it to restore return value from ParamString
  158.  
  159. ; **2
  160. ;   The following lines are neatly replaced by a single line CALL with
  161. ;   extended syntax. All the variables are automatically pushed on the
  162. ;   stack in the proper order, automatically.
  163. ;
  164. ;        push    es
  165. ;        push    di
  166. ;
  167. ;        if (@Cpu and 100b) eq 100b
  168. ;            push    seg CurrentArgument
  169. ;        else
  170. ;            mov     ax, seg CurrentArgument
  171. ;            push    ax
  172. ;        endif
  173. ;        if (@Cpu and 100b) eq 100b
  174. ;            push    offset CurrentArgument
  175. ;        else
  176. ;            mov     ax, offset CurrentArgument
  177. ;            push    ax
  178. ;        endif
  179.  
  180.         xor     ah,ah
  181.         mov     al,[byte es:di]
  182.         inc     ax
  183.  
  184.         call    ByteCopy,es,di,seg CurrentArgument,Offset CurrentArgument
  185.  
  186.     @@DeleteSpaces:
  187.         cmp     [CurrentArgument+1], SPACE
  188.         jne     @@NoMoreSpaces
  189.  
  190. ; **2
  191. ;        if (@Cpu and 100b) eq 100b
  192. ;            push    seg CurrentArgument
  193. ;        else
  194. ;            mov     ax, seg CurrentArgument
  195. ;            push    ax
  196. ;        endif
  197. ;        if (@Cpu and 100b) eq 100b
  198. ;            push    offset CurrentArgument
  199. ;        else
  200. ;            mov     ax, offset CurrentArgument
  201. ;            push    ax
  202. ;        endif
  203.  
  204.         mov     cx, 1           ; Remove the first character
  205.         mov     ax, 1           ; from the string
  206.         call    DeleteChar,seg CurrentArgument,offset CurrentArgument
  207.  
  208.         jmp     @@DeleteSpaces
  209.     @@NoMoreSpaces:
  210.         mov     ax,seg CurrentArgument
  211.         mov     es,ax
  212.         mov     di,offset CurrentArgument
  213.  
  214.         pop     ax
  215.     @@Finished:
  216.         ret
  217.     endp    GetArgument
  218.  
  219.  
  220.  
  221.     dataseg
  222.  
  223. MakePascalString  SearchMssg,<"WHEREIS parameters:",13,10>
  224.  
  225.     codeseg
  226.     proc    Show_Args
  227.     ;   This procedure displays all the command line parameters sent
  228.     ;   to the program.
  229.     ;
  230.     ;   Input
  231.     ;       none
  232.     ;   Output
  233.     ;       none
  234.     ;   Calling conventions
  235.     ;       NA
  236.     ;   Registers modified
  237.     ;       all
  238.  
  239.         push es di ax                 ;**5
  240.         call WritePascalString,ds,offset SearchMssg
  241.         mov  [argcount],1             ;**4
  242.  
  243.     @@Show_loop:
  244.         mov  al,[argcount]
  245.         call GetArgument
  246.         or   al,al         ; Check for zero return. Means no more arguments.
  247.         jz   @@Show_Exit
  248.  
  249.         call WritePascalString,es,di  ; Show the current argument
  250.  
  251.         push seg BlankLine            ;**1
  252.         push offset BlankLine
  253.         call WritePascalString
  254.  
  255.         inc  [argcount]               ;**4
  256.         jmp  @@Show_loop
  257.  
  258.     @@Show_Exit:
  259.         pop  ax di es                 ;**5
  260.         ret
  261.     argcount db 1                     ;**4
  262.     endp    Show_Args
  263.  
  264.  
  265.  
  266.     proc Main
  267.  
  268.     ;************************* Program Entry Point ***************************
  269.     ; Execution of the program begins here.
  270.  
  271.     EntryPoint:
  272.         mov     ax, @data       ; Initialize ds by moving segment address
  273.         mov     ds, ax          ; of data segment into ds register
  274.         push    bp              ; Setup a starting stack frame.
  275.         mov     bp, sp
  276.  
  277.         call    Initialize      ; Initialize data structures, etc.
  278.  
  279.         call    Show_Args
  280.  
  281.  
  282.         mov     [FileSpecCounter],0  ; FileSpecCounter has # files found so far
  283.         mov     [NextFileSpec],offset FileSpec
  284.         mov     [PathPtr],offset Path
  285.         mov     [DrivePtr],offset Drive
  286.  
  287.  
  288.         mov     al,[FileSpecCounter]
  289.     ProcessFileSpec:                 ; Jump to here if AL already loaded
  290.         cmp     al,MAX_FILE_SPECS
  291.         je      @@StartFileSearch    ;**3
  292.  
  293.         inc     al
  294.         call    GetArgument
  295.         or      al,al
  296.         jz      @@StartFileSearch    ; If al=0, we are at the end of arguments.
  297.  
  298.         mov     al,[byte es:di+1]
  299.         call    IsDelimiter
  300.         jc      HandleDosCommand
  301.  
  302. ; **2
  303. ;        push    es              ; Store the location of the unparsed file spec.
  304. ;        push    di
  305. ;
  306. ;        ; Pull apart the drive, path and filename so we can store the
  307. ;        ; filename specification.
  308. ;
  309. ;        push    ds              ; Push the address to store the drive spec. in
  310. ;        if (@Cpu and 100b) eq 100b
  311. ;            push    offset Drive
  312. ;        else
  313. ;            mov     ax, offset Drive
  314. ;            push    ax
  315. ;        endif
  316. ;        push    ds              ; Push the address to store the path spec. in
  317. ;        if (@Cpu and 100b) eq 100b
  318. ;            push    offset Path
  319. ;        else
  320. ;            mov     ax, offset Path
  321. ;            push    ax
  322. ;        endif
  323. ;        push    ds              ; Push address to store filename spec. in
  324. ;        if (@Cpu and 100b) eq 100b
  325. ;            push    offset FileSpec
  326. ;        else
  327. ;            mov     ax, offset FileSpec
  328. ;            push    ax
  329. ;        endif
  330.  
  331.         ; Parse the filename into it's components
  332.         call    ParseFilename,es,di, \             ;Filespec to be parsed
  333.                               ds,[DrivePtr],   \   ;**6
  334.                               ds,[PathPtr],    \
  335.                               ds,[NextFileSpec]
  336.  
  337.         mov     al,[FileSpecCounter]
  338.         or      al,al
  339.         jz      CheckFirstArg     ; If al is zero, we are checking first
  340.                                   ; argument, so we can allow drive and
  341.                                   ; path specification.
  342.  
  343.         mov     bx,[PathPtr]
  344.         cmp     [byte bx], 0      ; Check if the parsed path is empty
  345.         jne     @@IllegalPath
  346.         mov     bx,[DrivePtr]     ; Check if the parsed drive is empty
  347.         cmp     [byte bx],0
  348.         jne     @@IllegalPath
  349.  
  350.         jmp     @@GetAnotherFileSpec
  351.  
  352.     @@IllegalPath:                ; Give an error for path on parameter other
  353.                                   ; than the first.
  354.         call    PathAfterFirst
  355.  
  356.  
  357.     CheckFirstArg:
  358.        ; For the next arguments, set the pointers to dummy areas
  359.        ; since we don't pay attention to the path and drive for
  360.        ; arguments other than the first.
  361.         mov     [PathPtr],offset tempPath
  362.         mov     [DrivePtr],offset tempDrive
  363.  
  364.         cmp     [byte Path], 0          ; Check if the path is empty
  365.         jne     HaveAPath
  366.         mov     [byte Path], 1
  367.         mov     [byte Path+1], '\'
  368.     HaveAPath:
  369.         cmp     [byte Drive], 0         ; Check if a drive definition exists
  370.         je      DontChangeDrives
  371.         cmp     [byte Drive+1], 61h     ; Check if the drive letter is lower
  372.         jng     IsCapitalized           ; case
  373.         sub     [byte Drive+1], 20h     ; Capitalize the drive letter
  374.     IsCapitalized:
  375.         mov     al, [byte Drive+1]
  376.         sub     al, 'A'
  377.         ChangeDrive <al>                ; Change to the appropriate drive
  378.         jmp     DoneWithFirstArg
  379.     DontChangeDrives:
  380.         mov     [byte Drive], 2         ; Initialize the drive
  381.         mov     al, [byte OldDrive]
  382.         mov     [byte Drive+1], al      ; string with the
  383.         add     [byte Drive+1], 'A'     ; current drive.
  384.     DoneWithFirstArg:
  385.         jmp     @@GetAnotherFileSpec
  386.  
  387.  
  388.     HandleDosCommand:
  389.         ; If a DOS command is given, it is surrounded by quotes.
  390.         ; We need to strip the quotes, and store it in the module that
  391.         ; handles executing DOS commands.
  392.         call    ParseDosCommand
  393.         jnc     @@DoneWithArg           ; If no errors, we are done with this arg
  394.         call    OnlyOneDosCommand
  395.  
  396.     @@GetAnotherFileSpec:
  397.         add     [NextFileSpec],FILE_SPEC_SIZE
  398.  
  399.         ; Increment the FileSpecCounter
  400.         mov     al,[FileSpecCounter]
  401.         inc     al
  402.         mov     [FileSpecCounter],al  ; FileSpecCounter has # files found so far
  403.     @@DoneWithArg:
  404.         jmp     ProcessFileSpec
  405.  
  406.     @@StartFileSearch:
  407.         ; We are now done analyzing the command line parameters.
  408.         ; Copy the start path onto the stack
  409.  
  410.         sub     sp, MAX_PATH_LENGTH     ; Make room on the stack
  411.         mov     si, sp
  412.  
  413.         xor     ah, ah
  414.         mov     al, [byte Path]         ; Get the path length
  415.         inc     al                      ; We want to copy the length byte also
  416.         inc     al                      ; And the null terminator
  417.         call    ByteCopy,ds,offset Path,ss,si   ; Copy the path onto the stack
  418.  
  419.  
  420.         call    FindFiles               ; Do the search for the file(s)
  421.         call    Terminate               ; End the program
  422.     ;*************************************************************************
  423.     endp    main
  424.  
  425.     proc    Initialize
  426.  
  427.     ;   This procedure initializes all global variables and data structures
  428.     ;   used by the program.
  429.     ;
  430.     ;   Input
  431.     ;       none
  432.     ;   Output
  433.     ;       none
  434.     ;   Calling conventions
  435.     ;       NA
  436.     ;   Registers modified
  437.     ;       ax, flags
  438.  
  439.         ; Store the PSP address by storing es in the variable PspAddress.
  440.         ; Note that we do it this way instead of using DOS function 62h because
  441.         ; the function is only available on DOS 3.0 or later.
  442.  
  443.         mov     [PspAddress], es
  444.  
  445.         push    ds
  446.         GetCurrentDir   <0>, <seg HomeDirectory>, <offset HomeDirectory>
  447.         pop     ds
  448.         GetDrive                        ; Get the current disk drive
  449.         mov     [byte OldDrive], al     ; Save it
  450.  
  451.         ; Verify that the user provided command line parameters.
  452.  
  453.         call    ParamCount
  454.         or      al, al                  ; Were any parameters passed by user?
  455.         jnz     @@Exit
  456.         call    UsageScreen             ; If no, display usage screen
  457.  
  458.     @@Exit:
  459.         ret
  460.     endp    ; Initialize
  461.  
  462.  
  463.     proc    Terminate   ;   This routine terminates the WHEREIS program.
  464.         mov     al, [byte OldDrive]     ; Get the original disk drive
  465.         ChangeDrive <al>                ; Restore the original disk drive
  466.         ChangeDirectory <seg HomeDirectory>, <((offset HomeDirectory) - 1)>
  467.         mov     ah, DOS_TERMINATE_EXE
  468.         int     DOS_FUNCTION
  469.     endp    Terminate
  470.  
  471.  
  472.     proc    UsageScreen
  473.  
  474.     ;   This routine displays a 'usage' screen that describes the syntax for
  475.     ;   using WHEREIS. It then terminates the program.
  476.     ;
  477.     ;   Input
  478.     ;       ds - Points to data segment where usage screen text is located
  479.     ;   Output
  480.     ;       none
  481.     ;   Calling conventions
  482.     ;       NA
  483.     ;   Registers modified
  484.     ;       ax, cx, dx
  485.  
  486.         call    WriteAsciizString,ds,offset Syntax
  487.         call    Terminate               ; Terminate program
  488.     endp    ; UsageScreen
  489.  
  490.  
  491.     proc    PathAfterFirst
  492.  
  493.     ;   This routine displays a 'usage' screen that tells the user that
  494.     ;   drive and path info may only be given on the first argument.
  495.     ;   It then terminates the program.
  496.     ;
  497.     ;   Input
  498.     ;       ds - Points to data segment where usage screen text is located
  499.     ;   Output
  500.     ;       none
  501.     ;   Calling conventions
  502.     ;       NA
  503.     ;   Registers modified
  504.     ;       ax, cx, dx
  505.  
  506.         call    WritePascalString,ds,offset OnlyFirst    ;**2
  507.         call    Terminate               ; Terminate program
  508.     endp
  509.  
  510.     proc    OnlyOneDosCommand
  511.  
  512.     ;   This routine displays a 'usage' screen that tells the user that
  513.     ;   drive and path info may only be given on the first argument.
  514.     ;   It then terminates the program.
  515.     ;
  516.     ;   Input
  517.     ;       ds - Points to data segment where usage screen text is located
  518.     ;   Output
  519.     ;       none
  520.     ;   Calling conventions
  521.     ;       NA
  522.     ;   Registers modified
  523.     ;       ax, cx, dx
  524.  
  525.         call    WritePascalString,ds,offset OnlyOneCommand
  526.         call    Terminate               ; Terminate program
  527.     endp
  528.  
  529.  
  530. endif   ; ifndef MDL
  531.  
  532. end EntryPoint
  533.