home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv2_4 / qbasic / dsearch.asm < prev    next >
Encoding:
Assembly Source File  |  1989-03-02  |  8.8 KB  |  226 lines

  1. ;;    Microsoft Systems Journal
  2. ;;    Volume 2; Issue 4; September, 1987
  3.  
  4. ;;    pp. 63-76
  5.  
  6. ;; Author(s): Dan Mick
  7. ;; Title:     Microsoft QuickBASIC: Everyone's First PC Language Gets Better
  8.  
  9.  
  10.  
  11. ;;    Figure 1
  12. ;;    ========
  13.  
  14.  
  15.  
  16. ;;    DSEARCH.ASM
  17. ;;    Written by Dan Mick
  18.  
  19.  
  20.         page    62,132
  21.  
  22. data    segment public 'data'
  23. dta_ofs dw      ?               ;save area for BASIC's DTA
  24. dta_seg dw      ?
  25. fill    db      ?               ;"fill array" flag
  26. selflg  db      ?               ;"selective search" flag
  27. search_attr     db      ?       ;files' search attribute
  28. filcnt  dw      ?               ;count of files found
  29. path    db      64 dup (0)      ;search path, passed from BASIC
  30.  
  31. ;DTA structure for findfirst, findnext calls (see DOS documentation)
  32.  
  33. dta     db      21 dup (0)      ;reserved area (used for findnext)
  34. attrib  db      ?               ;attribute of file found
  35. time    dw      ?               ;time of last write
  36. date    dw      ?               ;date
  37. fsize   dd      ?               ;filesize (32 bit integer)
  38. fname   db      13 dup (0)      ;ASCIIZ filename: name.ext,00
  39. data    ends
  40.  
  41. dgroup  group   data
  42.  
  43. code    segment byte public 'code'
  44.         assume  cs:code, ds:dgroup
  45.         .xlist
  46. ;
  47. ;CALL DSEARCH(path$, attr, count, selective, array ofs)
  48. ; path$ is a normal string variable with the path for the
  49. ; directory search.  It be a full pathname, including filename
  50. ; and extension fields.  To get all the files in the default
  51. ; directory on C:, for instance, path$="C:*.*", or all the files
  52. ; in subdir on the current drive, path$="subdir\*.*".
  53. ; attr is the MS-DOS file attribute for the search.  See below for
  54. ; a description.  Each bit represents a file attribute.
  55. ; count is an input and an output parameter.  On input, if it is
  56. ; zero, the files will not be put in the array, only counted.
  57. ; This is provided so that a dynamic array may be allocated after
  58. ; the size is determined by dsearch().  If count is non-zero on
  59. ; input, the filenames will be placed in the array.
  60. ; In either case, the count of filenames found is returned.
  61. ; selective is a flag indicating how to do the counting and
  62. ; searching process.  If the file attribute 10 is specified, for
  63. ; example, DOS will return all those filenames that have the
  64. ; subdir attribute as well as those that don't.  If selective is
  65. ; set nonzero, the non-subdir files will not be returned.  What
  66. ; this does, basically, is allow a "filter normal files" selection
  67. ; so that subdirs and volume labels may easily be found.
  68. ; array offset is a pointer (offset only for strings) to a string
  69. ; array big enough to hold all files found in path$.  The size
  70. ; required may be determined as described below.
  71. ;
  72. ; The attribute byte:
  73. ;
  74. ;           -------------------------------------
  75. ;           | X | X | X | A | D | V | S | H | R |
  76. ;           -------------------------------------
  77. ;
  78. ;  X is don't care, A = archive, D = subdirectory, V = volume label,
  79. ;  S = system, H = hidden, R = read-only.
  80. ;
  81.         .list
  82.  
  83. stk     struc
  84. bbp     dw      ?               ;BASIC's bp
  85. retadd  dd      ?               ;return address
  86. arrofs  dw      ?               ;param: array offset
  87. select  dw      ?               ;param: filter normal files flag
  88. count   dw      ?               ;param: count flag/count return
  89. attr    dw      ?               ;param: search attr
  90. path$   dw      ?               ;param: pathname to search
  91. stk     ends
  92.  
  93. ;calculate value to pop with RET n at end of proc (length of params)
  94. popval  =       (offset path$) + (size path$) - (offset arrofs)
  95.  
  96. strdes  struc                   ;BASIC string descriptor structure
  97. len     dw      ?               ;word length of string
  98. strptr  dw      ?               ;pointer to string space
  99. strdes  ends
  100.  
  101. dsearch proc    far             ;it's a far proc to BASIC
  102.         public  dsearch         ;let LINK know about this one
  103.  
  104.         push    bp              ;save BASIC's bp
  105.         mov     bp,sp           ;address stack as it exists now
  106.  
  107.         mov     [filcnt],0      ;initialize file count
  108.  
  109.         mov     si,path$[bp]    ;get pointer to string descriptor
  110.         mov     cx,len[si]      ;cx = path length
  111.         mov     si,strptr[si]   ;si -> path string data
  112.         lea     di,path         ;di -> place to fill
  113.         rep     movsb           ;move pathname to our data area
  114.         mov     byte ptr es:[di],0 ;make sure it's an ASCIIZ string
  115.  
  116.         mov     si,count[bp]    ;get pointer to fill flag in di
  117.         mov     cx,[si]         ;cx = fill flag
  118.         mov     byte ptr [fill],0 ;set flag to "no" first
  119.         or      cx,cx           ;nonzero?
  120.         jz      nofill          ;nope
  121.         mov     byte ptr [fill],0ffh ;yes, set flag
  122.  
  123. nofill: mov     di,select[bp]   ;get pointer to selective flag in di
  124.         mov     cx,[di]         ;cx = selective flag
  125.         mov     byte ptr [selflg],0 ;set flag to "no" first
  126.         or      cx,cx           ;nonzero?
  127.         jz      nosel           ;nope
  128.         mov     byte ptr [selflg],0ffh ;yes, set flag
  129.  
  130. nosel:  mov     di,attr[bp]     ;point at search attribute param
  131.         mov     cx,[di]         ;and get it
  132.  
  133.         mov     ah,2fh          ;get BASIC's DTA
  134.         int     21h
  135.         mov     [dta_ofs],bx
  136.         mov     [dta_seg],es    ;and save it
  137.         lea     dx,dta          ;set DTA to our area here
  138.         mov     ah,1ah
  139.         int     21h
  140.  
  141.         mov     di,arrofs[bp]   ;di -> first string descriptor
  142.         mov     di,[di]         ;di = first string descriptor offset
  143.         mov     bx,ds           ;set up es to string array segment
  144.         mov     es,bx           ; (BASIC's data segment)
  145.                                 ;now es:di -> first string descriptor
  146.  
  147.         mov     ah,4eh          ;find first matching file
  148.         xor     ch,ch           ;clear hi part of attribute
  149.         lea     dx,path         ;ds:dx points to search path
  150.         int     21h
  151.         jnc     ok              ;if error, cy set
  152.         cmp     ax,18           ;no files found?
  153.         jz      exit            ;yes, don't report error
  154.         mov     [filcnt],0ffffh ;set count to -1 to report path error
  155.         jmp     short exit      ;and leave
  156.  
  157. ok:     call    countit         ;rets cy if should save, incs filcnt
  158.         jz      findnext        ;no fill if zr set
  159.         call    move_filename   ;do the move
  160.  
  161. findnext:
  162.         mov     ah,4fh          ;find next function
  163.         int     21h             ;do it
  164.         jc      exit            ;if error, must be no more files
  165.         call    countit         ;count, return cy if should save
  166.         jz      findnext        ;if zr set, don't save name
  167.         call    move_filename   ;move it
  168.         jmp     short findnext  ;and keep hunting
  169.  
  170. exit:   push    ds
  171.         lds     dx,dword ptr [dta_ofs] ;get BASIC's DTA
  172.         mov     ah,1ah                 ;set DTA fn.
  173.         int     21h
  174.         pop     ds
  175.         mov     di,count[bp]    ;di -> fattr for count return
  176.         mov     ax,[filcnt]     ;get file count
  177.         mov     [di],ax         ;put file count in fattr
  178.         pop     bp              ;restore BASIC's BP
  179.         ret     popval          ;return and pop parameter pointers
  180. dsearch endp
  181.  
  182. countit         proc
  183. ;
  184.  
  185. ;Check file attribute if selective, and update count or not based on
  186. ;result. Return flag saying whether or not to move filename, too,
  187. ;based on updated count and the "fill" flag.
  188.  
  189. ;
  190.          cmp     [selflg],0ffh  ;are we selective?
  191.          jnz     bump           ;nope, count it
  192.          cmp     [attrib],cl    ;is the attr just what we want?
  193.          je      bump           ;yes, count this file
  194.          cmp     cl,cl          ;nope, set ZF
  195.          jmp     short dontfill ;and skip to exit
  196. bump:    inc     [filcnt]       ;update counter
  197.          cmp     [fill],0       ;now, are we filling?
  198. dontfill:                       ;get here from jne, so NZ
  199.          ret                    ; return with NZ if filling
  200. countit         endp
  201.  
  202. move_filename   proc    near
  203. ;
  204. ;es:di points to string descriptor to fill with filename from DTA
  205. ;
  206.         push    di              ;save pointer to descr. length part
  207.         mov     di,es:strptr[di] ;and point instead to string data
  208.         lea     si,fname        ;si -> filename (ASCIIZ)
  209. moveloop:
  210.         lodsb                   ;get filename character
  211.         or      al,al           ;is it 0? (end of string?)
  212.         jz      done            ;yes, quit moving data
  213.         stosb                   ;no, store
  214.         jmp     short moveloop  ;and continue
  215. done:   test    byte ptr [attrib],10h ;is this a subdir?
  216.         jz      notsub          ;no
  217.         mov     al,'\'          ;yes, store a trailing backslash
  218.         stosb
  219. notsub: pop     di              ;di -> length in s.d. again
  220.         add     di,4            ;move to next s.d. pointer
  221.         ret
  222. move_filename   endp
  223.  
  224. code    ends
  225.         end     dsearch
  226.