home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / APOG / ASM7.ZIP / WHEREIS.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-09-24  |  17.5 KB  |  520 lines

  1.         name    whereis
  2.         title   'WHEREIS -- find file'
  3.         page    55,132
  4. ;
  5. ; WHEREIS -- find file in directory structure
  6. ; by John Scotia, first published in Softalk/IBM
  7. ; modified by Ray Duncan
  8. ;
  9. ;     usage:   WHEREIS filename        (filename can use wildcards)
  10. ;
  11. lf      equ     0ah                     ;ASCII line feed
  12. cr      equ     0dh                     ;ASCII carriage return
  13. ff      equ     0ch                     ;ASCII form feed
  14. tab     equ     09h
  15. eom     equ     '$'                     ;end of message flag
  16. ;
  17.                                         ;Program Segment Prefix
  18. default_fcb equ 05ch
  19. command equ     80h
  20. default_dta equ 080h
  21. ;
  22. ;
  23.  
  24. ; This is the format for the DOS Data Transfer Area used when DOS 2.0
  25. ; searches for a file match in directories.
  26.  
  27. DTA     STRUC
  28.         RESERVED        DB      21 DUP (?)
  29.         ATTRIBUTE       DB      ?
  30.         TIME            DW      ?
  31.         DATE            DW      ?
  32.         SIZE            DD      ?
  33.         NAME_FOUND      DB      13 DUP (?)
  34. DTA     ENDS
  35.  
  36. cseg    segment para public 'CODE'
  37.  
  38.         assume  cs:cseg,ds:data,es:data,ss:stack
  39.  
  40.         page
  41.  
  42. ; This is the main program that sets up the initial conditions for
  43. ; SDIR which, in turn, does a recursive search.
  44. ;
  45. ; Reads:        PATH_NAME
  46. ; Writes:       FILE_NAME
  47. ; Calls:        SDIR
  48.  
  49. whereis proc    far
  50.  
  51.         push    ds                      ;save final return
  52.         xor     ax,ax
  53.         push    ax
  54.         mov     bp,sp                   ;save pointer to final return
  55.                                         ; in case we want to exit
  56.                                         ; inside recursive routine
  57.  
  58.         mov     ax,data                 ;make data segment addressable
  59.         mov     es,ax                   ;via ES
  60.  
  61.         call    infile                  ;get name of search target
  62.  
  63.         mov     ax,data                 ;make data segment addressable
  64.         mov     ds,ax                   ;via DS
  65.         jnc     whereis1                ;jump if filename was ok
  66.                                         ;filename was missing,
  67.         mov     dx,offset msg1          ;print error message and exit
  68.         mov     ah,9
  69.         int     21h
  70.         ret
  71. whereis1:
  72.         mov     ah,30h                  ;check DOS version
  73.         int     21h
  74.         cmp     al,2
  75.         jae     whereis2                ;proceed, DOS 2.0 or greater
  76.         mov     dx,offset msg3          ;DOS 1.1 --- print message
  77.         mov     ah,9                    ;and exit
  78.         int     21h
  79.         ret
  80. whereis2:
  81.         MOV     DI,OFFSET PATH_NAME
  82.         XOR     AL,AL                   ;Search for the zero at the end
  83.         CLD                             ; of PATH_NAME
  84.         MOV     CX,64                   ;Max. length of scan for 0
  85.         REPNZ   SCASB
  86.         MOV     BX,DI
  87.         DEC     BX                      ;DS:BX points to end of PATH_NAME
  88.         MOV     DX,0                    ;Tell SDIR this is first
  89.         CALL    SDIR                    ;Now do the recursive search
  90.         mov     ax,match_count          ;were any matches found?
  91.         or      ax,ax
  92.         jz      whereis8                ;no,jump
  93.         ret                             ;yes,just exit
  94. whereis8:
  95.         mov     dx,offset msg2          ;no,print "no match"
  96.         mov     ah,9
  97.         int     21h
  98.         ret
  99.                                         ;this is a special crash
  100.                                         ;exit, which may be taken
  101.                                         ;from inside recursed proc.
  102. whereis9:
  103.         mov     sp,bp
  104.         ret
  105.  
  106. whereis endp
  107.  
  108.         page
  109.  
  110. ;  This procedure searches all the files in the current directory
  111. ; looking for a match.  It also prints the full name for each match.
  112. ;
  113. ;       DS:BX           Pointer to end of current path name
  114. ;       DS:DX           Old disk transfer area (DTA)
  115. ;
  116. ; Reads:        Disk Transfer Area (DTA)
  117. ; Writes:       Disk Transfer Area (DTA)
  118. ; Calls:        BUILD_NAME, FMATCH, PNAME
  119. ;               NMATCH, BUILD_STAR_NAME, SSUB
  120.  
  121. SDIR    PROC    NEAR
  122.         PUSH    SI                      ;Need to restore on exit
  123.         PUSH    DX
  124.         CALL    BUILD_NAME              ;Build the absolute search name
  125.         CALL    FMATCH                  ;See if there is a match here
  126.         JC      sdir2                   ;No match, check subdirectories
  127.         CALL    PNAME                   ;Write name of match.
  128. sdir1:
  129.         CALL    NMATCH                  ;Find the next match
  130.         JC      sdir2                   ;No match, search sub-directories
  131.         CALL    PNAME                   ;Match, write absolute name
  132.         JMP     sdir1                   ;Look for the next matching name
  133. sdir2:                                  ;No match, so try sub-directories.
  134.         POP     DX                      ;Restore DTA
  135.         PUSH    DX
  136.         CALL    BUILD_STAR_NAME         ;Search for all directories
  137.         CALL    FMATCH                  ;Get first entry
  138.         JC      SDIR5                   ;There are no entries
  139.         MOV     SI,DX                   ;Put address of DTA into SI
  140.         TEST    [SI].ATTRIBUTE,10H      ;Is it a directory entry?
  141.         JNZ     SDIR4                   ;Yes, then search sub-directory
  142. SDIR3:
  143.         CALL    NMATCH                  ;No, then find the next match
  144.         JC      SDIR5                   ;There are no more entries
  145.         TEST    [SI].ATTRIBUTE,10H      ;Is this a directory?
  146.         JZ      SDIR3                   ;No, then try again
  147. SDIR4:
  148.         CMP     [SI].NAME_FOUND,'.'     ;Is this a . or .. directory?
  149.         JE      SDIR3                   ;Yes, skip to next directory
  150.         CALL    SSUB                    ;Search the sub-directory
  151.         PUSH    AX                      ;Now reset the DTA
  152.         MOV     AH,1AH
  153.         INT     21H
  154.         POP     AX
  155.         JMP     SDIR3
  156.  
  157. SDIR5:
  158.         POP     DX
  159.         POP     SI
  160.         RET
  161. SDIR    ENDP
  162.  
  163.         page
  164.  
  165. ; This procedure searches the subdirectory whos name is in the DTA
  166. ;
  167. ;       DS:BX           End of the current path name
  168. ;       DS:[DX].NAME_FOUND      Name of subdirectory for search
  169. ; Reads:        PATH_NAME
  170. ; Writes:       PATH_NAME
  171. ; Calls:        SDIR
  172.  
  173. SSUB    PROC    NEAR
  174.         PUSH    DI
  175.         PUSH    SI
  176.         PUSH    AX
  177.         PUSH    BX
  178.         CLD                             ;Set for increment
  179.         MOV     SI,DX                   ;Put address of DTA into SI
  180.         ADD     SI,OFFSET NAME_FOUND    ;Set to start of sub-directory name
  181.         MOV     DI,BX                   ;DS:DI -- 0 at end of path name
  182. ssub1:                                  ;Copy sub-directory to path name
  183.         LODSB                           ;Copy one character
  184.         STOSB
  185.         OR      AL,AL                   ;Was it a 0?
  186.         JNZ     ssub1                   ;No, keep copying
  187.         MOV     BX,DI                   ;Set BX to end of new path name
  188.         STD                             ;Set flag for decrement
  189.         STOSB                           ;Store a 0 at end of string
  190.         MOV     AL,'\'
  191.         STOSB                           ;Place '\' at end of path name
  192.         CALL    SDIR                    ;Search this new path
  193.         POP     BX                      ;Restore the old end-of-path
  194.         MOV     BYTE PTR [BX],0         ;And store a zero here
  195.         POP     AX
  196.         POP     SI
  197.         POP     DI
  198.         RET
  199. SSUB    ENDP
  200.  
  201.         page
  202.  
  203. ; This procedure prints the matched name after the path name
  204. ;
  205. ;       DS:DX           Pointer to current disk transfer area
  206. ;
  207. ; Reads:        PATH_NAME, NAME_FOUND (in DTA)
  208. ; Calls:        pasciiz, CRLF
  209.  
  210. PNAME   PROC    NEAR
  211.         PUSH    AX
  212.         PUSH    DX
  213.         MOV     DX,OFFSET PATH_NAME
  214.         MOV     AL,[BX]                 ;Save character at end of path
  215.         MOV     BYTE PTR [BX],0         ;Set for end of string
  216.         CALL    pasciiz
  217.         MOV     [BX],AL                 ;Restore character
  218.         POP     DX                      ;Recover old pointer
  219.         PUSH    DX
  220.         ADD     DX,OFFSET NAME_FOUND
  221.         CALL    pasciiz
  222.         cmp     byte ptr switch,'g'     ;global switch set?
  223.         je      pname2                  ;yes,keep searching
  224.                                         ;no, check if user wants
  225.                                         ;to keep looking.
  226.         push    dx                      ;save current DTA
  227.         mov     dx,offset msg4          ;print 'More? '
  228.         mov     ah,9
  229.         int     21h
  230.         mov     ah,7                    ;read console without echo
  231.         int     21h
  232.         or      al,20h                  ;fold to lower case
  233.         cmp     al,'y'                  ;must be y, anything else exits
  234.         je      pname1
  235.         jmp     whereis9                ;take crash exit
  236. pname1: mov     dl,al                   ;if Y,echo it
  237.         mov     ah,2
  238.         int     21h
  239.         pop     dx                      ;restore pointer to DTA
  240. pname2: CALL    CRLF
  241.         inc     match_count             ;count names displayed
  242.         POP     DX
  243.         POP     AX
  244.         RET
  245. PNAME   ENDP
  246.  
  247.         page
  248.  
  249. ;  This procedure builds an absolute search name from PATH_NAME
  250. ; followed by FILE_NAME.
  251. ;
  252. ; Reads:        FILE_NAME
  253. ; Calls:        BUILD           to build the name
  254.  
  255. BUILD_NAME      PROC    NEAR
  256.         PUSH    SI
  257.         MOV     SI,OFFSET FILE_NAME
  258.         CALL    BUILD
  259.         POP     SI
  260.         RET
  261. BUILD_NAME      ENDP
  262.  
  263. BUILD_STAR_NAME         PROC    NEAR
  264.         PUSH    SI
  265.         MOV     SI,OFFSET STAR_NAME
  266.         CALL    BUILD
  267.         POP     SI
  268.         RET
  269. BUILD_STAR_NAME         ENDP
  270.  
  271. ; This procedure appends the string at DS:SI to PATH_NAME in
  272. ; PATH_NAME.  It knows where the path name ends from knowing how
  273. ; long PATH_NAME is.
  274. ;
  275. ;       DS:SI           Name of file
  276. ;       DS:BX           End of PATH_NAME
  277. ;
  278. ; Reads:        DS:SI
  279. ; Writes:       PATH_NAME
  280.  
  281. BUILD   PROC    NEAR
  282.         PUSH    AX
  283.         PUSH    DI
  284.         MOV     DI,BX
  285.         CLD                             ;Set direction for increment
  286. build1:
  287.         LODSB                           ;Copy one character of name
  288.         STOSB
  289.         OR      AL,AL                   ;End of string yet?
  290.         JNZ     build1                  ;No, keep copying
  291.         POP     DI
  292.         POP     AX
  293.         RET
  294. BUILD   ENDP
  295.  
  296.         page
  297.  
  298. ;  This procedure finds the first match between the name given by
  299. ; DS:DX and the directory entries found in the directory PATH_NAME.
  300. ;
  301. ;       DS:DX           Pointer to current disk transfer area
  302. ; Returns:
  303. ;       CF      0       A match was found
  304. ;               1       No match found
  305. ;       AX              Error code returned:
  306. ;               2       File not found
  307. ;               18      No more files
  308. ;       DS:DX           Pointer to new disk transfer area
  309. ;
  310. ; Reads:        PATH_NAME
  311. ; Writes:       dbuff
  312.  
  313. FMATCH  PROC    NEAR
  314.         PUSH    CX
  315.         CMP     DX,0                    ;First one?
  316.         JA      ALLOCATE                ;No, then allocate space
  317.         MOV     DX,OFFSET dbuff-TYPE DTA
  318. allocate:
  319.         add     dx,type dta             ;no, then allocate room for new DTA
  320.         MOV     CX,10H                  ;Search attribute for files and dirs.
  321.         MOV     AH,1AH                  ;Set disk transfer address
  322.         INT     21H
  323.         PUSH    DX                      ;Need DX for address of search name
  324.         MOV     DX,OFFSET PATH_NAME
  325.         MOV     AH,4EH                  ;Call for "find first match"
  326.         INT     21H
  327.         POP     DX
  328.         POP     CX
  329.         RET                             ;Return with carry flag info
  330. FMATCH  ENDP
  331.  
  332.  
  333.         page
  334.  
  335. ; Get next match for filename
  336. ; (very similar to Get first match routine)
  337.  
  338. ; Returns:
  339. ;       CF      0       A match was found
  340. ;               1       No match found
  341. ;       AX              Error code returned:
  342. ;               2       File not found
  343. ;               18      No more files
  344. ;
  345. ; Reads:        PATH_NAME
  346. ; Writes:       dbuff
  347.  
  348. NMATCH  PROC    NEAR
  349.         PUSH    CX
  350.         PUSH    DX
  351.         MOV     DX,OFFSET PATH_NAME
  352.         MOV     CX,10H                  ;Attribute for files and directories
  353.         MOV     AH,4FH                  ;Call for "Find next match"
  354.         INT     21H
  355.         POP     DX
  356.         POP     CX
  357.         RET                             ;Return with carry flag intact
  358. NMATCH  ENDP
  359.  
  360.  
  361.         page
  362.  
  363. ;  Send CRLF sequence to the screen.
  364.  
  365. CRLF    PROC    NEAR
  366.         PUSH    AX
  367.         PUSH    DX
  368.         MOV     AH,02
  369.         MOV     DL,0AH
  370.         INT     21H
  371.         MOV     DL,0DH
  372.         INT     21H
  373.         POP     DX
  374.         POP     AX
  375.         RET
  376. CRLF    ENDP
  377.  
  378.         page
  379.  
  380. ;  Display ASCIIZ string
  381. ;  Call with DS:DX = string addr
  382.  
  383. pasciiz PROC    NEAR
  384.         PUSH    AX
  385.         PUSH    DX
  386.         PUSH    SI
  387.         CLD                             ;Set direction for increment
  388.         MOV     SI,DX                   ;Set up pointer to string
  389.         MOV     AH,2
  390. pasciiz1:
  391.         LODSB                           ;Get character
  392.         or      al,al                   ;if zero,all done
  393.         jz      pasciiz2
  394.         MOV     DL,AL
  395.         INT     21H                     ;Write one character
  396.         jmp     pasciiz1                ;loop till string exhausted
  397. pasciiz2:
  398.         POP     SI
  399.         POP     DX
  400.         POP     AX
  401.         RET
  402. pasciiz ENDP
  403.  
  404.         page
  405.  
  406.  
  407. infile  proc    near            ;process name of input file
  408.                                 ;DS:SI <- addr command line
  409.         mov     si,offset command
  410.                                 ;ES:DI <- addr filespec buffer
  411.         mov     di,offset file_name
  412.         cld
  413.         lodsb                   ;any command line present?
  414.         or      al,al           ;return error status if not.
  415.         jz      infile4
  416. infile1:                        ;scan over leading blanks
  417.         lodsb                   ;to file name
  418.         cmp     al,cr           ;if we hit carriage return
  419.         jz      infile4         ;filename is missing.
  420.         cmp     al,20h          ;is this a blank?
  421.         jz      infile1         ;if so keep scanning.
  422.         xor     ah,ah           ;reset "." found flag
  423.                                 ;found first char of name
  424. infile2:
  425.         cmp     al,'\'          ;if slash,reset "." flag
  426.         jne     infile22
  427.         xor     ah,ah
  428. infile22:                       ;check if extension specified
  429.         cmp     al,'.'
  430.         jne     infile24
  431.         inc     ah
  432. infile24:                       ;
  433.         stosb                   ;move last char. to output
  434.                                 ;file name buffer.
  435.         lodsb                   ;check next character, found
  436.         cmp     al,cr           ;carriage return yet?
  437.         je      infile3         ;yes,exit with success code
  438.         cmp     al,'/'          ;or if we hit a switch delimiter
  439.         jne     infile26
  440. infile25:
  441.         lodsb                   ;get the switch char and save it
  442.         or      al,20h          ;force to lower case
  443.         mov     byte ptr es:switch,al
  444.         jmp     infile3         ;then jump to finish up
  445. infile26:
  446.         cmp     al,20h          ;is this a blank?
  447.         jne     infile2         ;if not keep moving chars.
  448. infile27:
  449.         lodsb                   ;search up to end, in case of switch
  450.         cmp     al,'/'
  451.         je      infile25        ;found switch,go save it
  452.         cmp     al,cr
  453.         jne     infile27        ;otherwise, fscan until CR found
  454. infile3:                        ;found end of input name
  455.         or      ah,ah           ;was "." found?
  456.         jnz     infile35        ;yes,jump
  457.         mov     al,'.'          ;no,force ext to wildcard
  458.         stosb
  459.         mov     al,'*'
  460.         stosb
  461. infile35:
  462.         xor     al,al           ;store trailing null byte
  463.         stosb                   ;exit with CY=0 as success flag
  464.         clc
  465.         ret
  466.  
  467. infile4:                        ;exit with carry =1
  468.         stc                     ;for error flag
  469.         ret
  470. infile  endp
  471.  
  472. cseg    ends
  473.  
  474.         page
  475.  
  476. data            segment para public 'DATA'
  477.  
  478. STAR_NAME       DB      '*.*',0
  479.  
  480. PATH_NAME       DB      '\',0
  481.                 DB      80 DUP (0)      ;Space for 64 character path name
  482.                                         ; and 13 character file name
  483.  
  484. FILE_NAME       DB      13 DUP (0)      ;Save room for full DOS file name
  485.  
  486. msg1            db      cr,lf
  487.                 db      'Missing file name.'
  488.                 db      cr,lf,eom
  489.  
  490. msg2            db      cr,lf
  491.                 db      'No match found.'
  492.                 db      cr,lf,eom
  493.  
  494. msg3            db      cr,lf
  495.                 db      'Requires DOS version 2.0 or greater.'
  496.                 db      cr,lf,eom
  497.  
  498. msg4            db      tab,'  More (y/n) ? ',eom
  499.  
  500. match_count     dw      0               ;number of filenames matching
  501.                                         ;input filespec
  502.  
  503. switch          db      0               ;char following / saved here
  504.  
  505. dbuff           equ     $               ;this starts the scratch area
  506.                                         ;which will be used as search
  507.                                         ;buffers.  It is right under
  508.                                         ;the stack, which is made very
  509.                                         ;large to give it room.
  510.  
  511. data            ends
  512.  
  513.  
  514. stack   segment para stack 'STACK'
  515.         db      32768 dup (?)
  516. stack   ends
  517.  
  518.  
  519.         end     whereis
  520.