home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK7 / SOURCE / STARTUP / DOS / STDARGV.AS$ / STDARGV
Encoding:
Text File  |  1991-11-06  |  16.2 KB  |  853 lines

  1.     page    ,132
  2.     title    stdargv - standard & wildcard _setargv routine
  3. ;***
  4. ;stdargv.asm - standard & wildcard _setargv routine
  5. ;
  6. ;    Copyright (c) 1985-1992, Microsoft Corporation.  All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;    processes program command line, with or without wildcard expansion
  10. ;
  11. ;*******************************************************************************
  12.  
  13.  
  14. ifdef    WILDCARD
  15.     name    _setargv    ; wildcard _setargv routine
  16. else
  17.     name    stdargv     ; standard _setargv routine
  18. endif
  19.  
  20. ifdef    WILDCARD
  21. ?DF    =    1        ; tell cmacros.inc we want to define our own segments
  22. endif
  23.  
  24.     .xlist
  25. include version.inc
  26. include cmacros.inc
  27. include msdos.inc
  28. include defsegs.inc
  29. include rterr.inc
  30.     .list
  31.  
  32. ifdef _WINDOWS
  33.  
  34. _MAX_PATH equ 260            ; max path (should match stdlib.h)
  35.  
  36. extrn    pascal    GETMODULEFILENAME:far    ; get argv[0]
  37. extrn    __myalloc:near            ; allocation routine for arguments
  38.  
  39. endif
  40.  
  41. ifdef FARSTACK
  42. ife sizeD
  43.     error <You cannot have a far stack in Small or Medium memory models.>
  44. endif
  45. endif
  46.  
  47. ifdef    WILDCARD        ; **********************************************
  48.  
  49. CrtDefSegs <code, data>
  50. CrtDefSegs <nmsg>
  51.  
  52. codeOFFSET equ    <offset _TEXT:>
  53. dataOFFSET equ    <offset DGROUP:>
  54.  
  55. ; Message used by ___setargv (wildcard version of __setargv)
  56.  
  57. sBegin    nmsg
  58. assumes ds,data
  59.  
  60.     _RTERR    _RT_SPACEARG, _RT_SPACEARG_TXT, _RT_STANDARD    ; 'not enough space for arguments'
  61.  
  62. sEnd
  63.  
  64. sBegin    npad
  65. assumes ds,data
  66.     dw    -1
  67. ; no padding for now;
  68. ; MAX padding would be
  69. ;    db    25 dup(0)
  70. sEnd
  71.  
  72. externP _cwild            ; Wildcard Expander
  73. externNP _amsg_exit        ; error handler (unable to allocate)
  74.  
  75. endif                ; WILDCARD    ; **********************************************
  76.  
  77.  
  78. sBegin    data
  79. assumes ds,data
  80.  
  81. C_CR    equ    0DH        ; ASCII carriage return
  82.  
  83. C_BLANK equ    ' '        ; ASCII space character
  84. C_TAB    equ    09h        ; ASCII horizontal tab character
  85.  
  86. C_QUOTE equ    '"'        ; ASCII (double) Quote Charater
  87. C_BACKSLASH equ '\'             ; ASCII backward slash character
  88.  
  89. externDP __argv         ; argument string array address
  90. externW __argc            ; count of argument strings
  91. externW _psp            ; address of Program Segment Prefix
  92. externD _pgmptr         ; far ptr to name of program
  93.  
  94. ifdef _WINDOWS
  95. ifdef _WINDLL
  96. externW _hModule        ; identifies module
  97. else
  98. externW _hInstance        ; identifies instance of module
  99. endif
  100. else    ;!_WINDOWS
  101. externW _osversion        ; address of OS version
  102. endif
  103.  
  104.  
  105. staticCP retadr,0        ; return address
  106.  
  107.  
  108. ifdef    WILDCARD        ; **********************************************
  109.  
  110. dta_flag db    0        ; Has DMA been set yet?
  111.  
  112. file_reserv db    21 dup (0)
  113. file_attrib db    0
  114. file_time dw    0
  115. file_date dw    0
  116. file_sizel dw    0
  117. file_sizeh dw    0
  118. file_name db    13 dup (0)
  119.  
  120. endif                ; WILDCARD    ; **********************************************
  121.  
  122. sEnd
  123.  
  124. ; ****************************************
  125.  
  126. jmps    MACRO    target
  127.     jmp    short target
  128.     ENDM
  129.  
  130. lje    MACRO    target
  131.     LOCAL    temp
  132.     jne    temp
  133.     jmp    target
  134. temp:
  135.     ENDM
  136.  
  137.  
  138. DELIM    MACRO    target
  139.     cmp    al,C_CR     ;; Test for end-of-line character
  140.     je    target
  141.     or    al,al        ;; Either Carriage Return or Null
  142.     je    target
  143.     ENDM
  144.  
  145. LDELIM    MACRO    target
  146.     cmp    al,C_CR     ;; Test for end-of-line character
  147.     lje    target
  148.     or    al,al        ;; Either Carriage Return or Null
  149.     lje    target
  150.     ENDM
  151.  
  152. ; ****************************************
  153.  
  154. sBegin    code
  155.  
  156. assumes ds,data
  157. ifdef FARSTACK
  158. assumes ss,nothing
  159. else
  160. assumes ss,data
  161. endif
  162. assumes cs,code
  163.  
  164. ifdef  _WINDOWS
  165.     if    sizeD
  166.     externP  _GetDGROUP
  167.     endif
  168. endif
  169.  
  170. page
  171. ;***
  172. ;_setargv, __setargv - set up "argc" and "argv" for C programs
  173. ;
  174. ;Purpose:
  175. ;    Gets the command line from the PSP and moves the information
  176. ;    to its place on the stack.
  177. ;
  178. ;    SIDE EFFECTS:
  179. ;        Allocates space on the stack for the argument strings
  180. ;        and a list of pointers to them.
  181. ;    ASSUMPTIONS:
  182. ;        Under DOS 2, there is no argv[0] string, so we store a null
  183. ;        char ('\0').
  184. ;
  185. ;        Under DOS 3 and later, the argv[0] string is found in the
  186. ;        environment segment, after the double null that terminates
  187. ;        that segment and after a word of value 1.  The rest of the
  188. ;        command line is found in the Program Segment Prefix at
  189. ;        offset 81H, and is terminated by a 0DH.  This command "tail"
  190. ;        cannot be greater than 126 bytes in length.
  191. ;
  192. ;        Quote marks and backslashes are treated specially.  A quoted
  193. ;        string is passed as a single argument, not including the
  194. ;        opening and closing quote characters.  A quote may be imbedded
  195. ;        in a string by placing an odd number of backslashes (`\')
  196. ;        before it.  Each pair of backslashes which precedes a quote
  197. ;        results in a single backslash in the resultant string.
  198. ;        An even number of backslashes followed by a quote results in
  199. ;        half that many backslashes, and the quote begins or ends the
  200. ;        quoted part of the string as is appropriate.  Backslashes not
  201. ;        followed by a quote are treated normally.
  202. ;
  203. ;        [""] ==> []
  204. ;        [\"] ==> ["]
  205. ;        [" \" "] == [ " ]
  206. ;        [" \\"] == [ \]
  207. ;        [" \\ "] == [ \\ ]
  208. ;        [" \\\" "] == [ \" ]
  209. ;        etc.
  210. ;        ["one two three"] ==> [one two three]
  211. ;        [one" two "three] ==> [one two three]
  212. ;        [o"ne two t"hree] ==> [one two three]
  213. ;        ["one \"two\" three"] ==> [one "two" three]
  214. ;        ["x\\\"x"] ==> [x\"x]
  215. ;
  216. ;Entry:
  217. ;
  218. ;Exit:
  219. ;    "argv" points to a null-terminated list of pointers to ASCIZ
  220. ;    strings, each of which is an argument from the command line.
  221. ;    "argc" is the number of arguments.  The strings are copied from
  222. ;    the Program Segment Prefix into space allocated on the stack.
  223. ;    The list of pointers is also located on the stack.
  224. ;
  225. ;Uses:
  226. ;    All registers except DS, SS, and BP are modified
  227. ;    Note especially that SI and DI are NOT preserved!
  228. ;
  229. ;Exceptions:
  230. ;
  231. ;*******************************************************************************
  232.  
  233. ifdef    WILDCARD        ; **********************************************
  234.  
  235. labelP    <PUBLIC,__setargv>
  236.  
  237. else                ; **********************************************
  238.  
  239. labelP    <PUBLIC,_setargv>
  240.  
  241. endif                ; WILDCARD    ; **********************************************
  242.  
  243.     pop    word ptr [retadr] ; get return address (offset)
  244. if    sizeC
  245.     pop    word ptr [retadr+2] ; get return address (segment)
  246. endif
  247.  
  248. ifdef    _WINDOWS
  249. ;
  250. ; In windows, get argv[0] from the system, not from the DOS segment
  251. ;
  252.     mov    ax,_MAX_PATH        ; maximum length of path
  253.     mov    cx,_RT_SPACEARG     ; Out of heap space
  254.     call    __myalloc        ; get argv[0] memory
  255.                     ; *** DIES ON ERROR ***
  256. ifdef    WILDCARD
  257.     inc    ax            ; room for wildcard flag
  258. endif
  259.     mov    word ptr [_pgmptr+2],dx ; set global variable "_pgmptr"
  260.     mov    word ptr [_pgmptr],ax
  261.  
  262.     push    dx            ; save ptr across call
  263.     push    ax
  264.  
  265. ifdef    _WINDLL
  266.     push    _hModule        ; module instance
  267. else
  268.     push    _hInstance        ; module instance
  269. endif
  270.     push    dx            ; address of name buffer
  271.     push    ax
  272.     mov    ax,_MAX_PATH        ; size of buffer
  273.     push    ax
  274.     call    GETMODULEFILENAME    ; ax = length of actual string
  275.     ; no error return defined
  276.  
  277.     pop    bx
  278.     pop    es            ; es:bx = pointer to string
  279.     add    bx,ax            ; es:bx = end of string
  280.     mov    byte ptr es:[bx],0    ; store a final null byte
  281.  
  282.     mov    dx,1            ; dx = number of bytes in argv[0]
  283.  
  284. else    ;!_WINDOWS
  285. ;
  286. ; Check DOS version.
  287. ;
  288.     mov    ax,[_osversion] ; ax = OS version number
  289.     mov    dx,1        ; dx = number of bytes in argv[0] if DOS 2.x
  290.     cmp    al,2
  291.     je    dos_two
  292.  
  293.     mov    es,_psp
  294.     mov    es,es:[DOS_envp] ; get environment segment
  295.     mov    word ptr [_pgmptr+2],es ; set global variable "_pgmptr"
  296.     xor    ax,ax
  297.     cwd            ; DX=0
  298.     mov    cx,8000H
  299.     xor    di,di        ; scan from beginning of environment
  300. find_env_end:
  301.     repne    scasb
  302.     scasb
  303.     jne    find_env_end
  304. ;
  305.     inc    di        ; skip count word (always 0x0001)
  306.     inc    di
  307.     mov    word ptr [_pgmptr],di ; set global variable "_pgmptr"
  308.     mov    cx,-1
  309.     repne    scasb
  310.     not    cx
  311.     mov    dx,cx        ; DX=number of bytes in argv[0]
  312.  
  313. endif    ;_WINDOWS
  314.  
  315. dos_two:
  316. ifdef FARSTACK
  317.     push    ds
  318.     pop    es
  319.     assumes es,data     ; set ES=DGROUP
  320. endif
  321.     mov    di,1        ; always start with one argument
  322.     mov    si,81H
  323.     mov    ds,_psp
  324.  
  325.  
  326.     assumes ds,nothing
  327. ;*
  328. ;*    Count the command tail arguments
  329. ;*
  330. ;
  331. ;    DI will count the number of arguments
  332. ;    DX will count the number of bytes needed for the arguments
  333. ;        (not including the null terminators)
  334. ;
  335. arg100:
  336. arg110:
  337.     lodsb
  338.     cmp    al,C_BLANK
  339.     je    arg110
  340.     cmp    al,C_TAB
  341.     je    arg110
  342.  
  343.     DELIM    arg400
  344.  
  345.     inc    di        ; Another argument
  346. ;
  347. ; Parse an argument
  348. ;
  349. arg200:
  350.     dec    si        ; back up to reload character
  351. arg210:
  352.     lodsb
  353.  
  354.     cmp    al,C_BLANK
  355.     je    arg100
  356.     cmp    al,C_TAB
  357.     je    arg100        ; white space terminates argument
  358.  
  359.  
  360.     DELIM    arg400
  361.  
  362.     cmp    al,C_QUOTE
  363.     je    arg310
  364.  
  365.     cmp    al,C_BACKSLASH
  366.     je    arg220
  367.  
  368.  
  369.  
  370.     inc    dx
  371.     jmps    arg210
  372. ;
  373. ; Count backslashes
  374. ;
  375. arg220:
  376.     xor    cx,cx
  377. arg221:
  378.     inc    cx        ; CX counts the backslashes
  379.     lodsb
  380.     cmp    al,C_BACKSLASH
  381.     je    arg221
  382. ;
  383.     cmp    al,C_QUOTE
  384.     je    arg230
  385.  
  386.     add    dx,cx        ; not followed by `"' -- treat `\'s normally
  387.     jmp    arg200
  388. ;
  389. arg230:
  390.     mov    ax,cx
  391.     shr    cx,1
  392.     adc    dx,cx        ; add 1 for every pair of backslashes
  393.     test    al,1        ; plus 1 for the " if odd number of \
  394.     jnz    arg210        ; " was escaped with a \
  395.     jmps    arg310        ; " opens a quoted substring
  396. ;
  397. ; Enter a quoted string
  398. ;
  399. arg300:
  400.     dec    si        ; back up to reload character
  401. arg310:
  402.     lodsb
  403.  
  404.     DELIM    arg400
  405.  
  406.     cmp    al,C_QUOTE
  407.     je    arg210        ; end of quoted portion of string
  408.  
  409.     cmp    al,C_BACKSLASH
  410.     je    arg320
  411.  
  412.  
  413.     inc    dx
  414.     jmp    arg310
  415. ;
  416. ; Count backslashes
  417. ;
  418. arg320:
  419.     xor    cx,cx
  420. arg321:
  421.     inc    cx        ; CX counts the backslashes
  422.     lodsb
  423.     cmp    al,C_BACKSLASH
  424.     je    arg321
  425. ;
  426.     cmp    al,C_QUOTE
  427.     je    arg330
  428.  
  429.     add    dx,cx        ; not followed by `"' -- treat `\'s normally
  430.     jmp    arg300
  431. ;
  432. arg330:
  433.     mov    ax,cx
  434.     shr    cx,1
  435.     adc    dx,cx        ; add 1 for every pair of backslashes
  436.     test    al,1        ; plus 1 for the " if odd number of \
  437.     jnz    arg310        ; " was escaped with a \
  438.     jmps    arg210        ; " closes a quoted substring
  439. ;
  440. ; Command line is fully parsed - compute number of bytes needed
  441. ;
  442. arg400:
  443. ;
  444. ;    Number of bytes needed =
  445. ;        Number of bytes used to make strings +
  446. ;        Number of bytes used to terminate strings +
  447. ;        sizeof(DATAPTR) * ( number of arguments + 1 )
  448. ;
  449. ifdef FARSTACK
  450.     push    es
  451. else
  452.     push    ss
  453. endif ;FARSTACK
  454.     pop    ds        ; Restore DS = DGROUP
  455.     assumes ds,data
  456.  
  457.     mov    __argc,di    ; Store number of arguments
  458.  
  459.     add    dx,di        ; add in terminator bytes
  460. ifdef    WILDCARD
  461.     add    dx,di        ; add in Wildcard flag bytes
  462. endif
  463.     inc    di        ; add one for NULL pointer
  464.     shl    di,1
  465. if    sizeD
  466.     shl    di,1
  467. endif
  468.     add    dx,di        ; add space for pointers to space for chars
  469.  
  470.     inc    dx
  471.     and    dl,not 1    ; Round up to an even number of bytes
  472. ;
  473. ;    Allocate space on the stack
  474. ;
  475. ;    DX is the total number of bytes needed for strings and pointers
  476. ;    DI is the number of bytes needed for the pointers
  477. ;
  478.     sub    sp,dx
  479.     mov    ax,sp
  480.  
  481.     mov    word ptr (__argv),ax
  482. if    sizeD
  483.     mov    word ptr (__argv+2),ss
  484. endif
  485. ;
  486. ;    Copy argument strings and addresses onto heap/stack
  487. ;        Address table is on the top, strings below that
  488. ;
  489.     mov    bx,ax
  490.     add    di,bx
  491.  
  492.     push    ss        ; ES=SS
  493.     pop    es        ; ES:DI is where the string copies will go
  494. ifndef FARSTACK
  495.     assumes es,data
  496. endif
  497.  
  498. ;
  499. ;    DS:SI    points to the argv[0]
  500. ;
  501. ;    ES:BX    points to where argv[0],argv[1],argv[2],... go
  502. ;    ES:DI    points to where *argv[0],*argv[1],*argv[2],... go
  503. ; For wildcard version only:
  504. ;    ES:DX    points to the wildcard flag character (prepended to argument)
  505. ;        during the creation of each argument
  506. ;
  507.  
  508. ifdef    _WINDOWS
  509.  
  510.     ; move the pointer, no need to move the string
  511.     lds    si,[_pgmptr]    ; copy argv[0], either fake or from env seg
  512.     assumes ds,nothing
  513.  
  514. ifdef    WILDCARD
  515.     dec    si        ; room for wildcard flag
  516. endif
  517.     mov    ss:[bx],si    ; argv[0] - offset part
  518. if    sizeD
  519.     mov    ss:[bx+2],ds    ; argv[0] - segment part
  520.     add    bx,4
  521. else
  522.     inc    bx
  523.     inc    bx
  524. endif
  525.  
  526. else    ;!_WINDOWS
  527.  
  528.     mov    ss:[bx],di    ; argv[i] - offset part
  529. if    sizeD
  530.     mov    ss:[bx+2],ss    ; argv[i] - segment part
  531.     add    bx,4
  532. else
  533.     inc    bx
  534.     inc    bx
  535. endif
  536.  
  537.     lds    si,[_pgmptr]    ; copy argv[0], either fake or from env seg
  538.     assumes ds,nothing
  539.  
  540. ifdef    WILDCARD
  541.     movsb
  542.     dec    si        ; copy first character as quote flag
  543. endif
  544.  
  545. copy_argv0:
  546.     lodsb
  547.     stosb
  548.     or    al,al
  549.     jnz    copy_argv0
  550.  
  551. endif    ;_WINDOWS
  552.  
  553.  
  554. ;
  555. ;    DS:SI    points to the raw command tail string
  556. ;
  557.  
  558. ifdef FARSTACK
  559.  
  560.     ifdef  _WINDOWS
  561.     push    ax
  562.     callcrt _GetDGROUP
  563.     mov    ds, ax        ; DS = DGROUP
  564.     pop    ax
  565.     else    ;not _WINDOWS
  566.     mov    si, DGROUP
  567.     mov    ds, si        ; DS = DGROUP
  568.     endif   ;not _WINDOWS
  569.  
  570.     assumes ds, data
  571.     mov    ds, [_psp]
  572.     assumes ds, nothing    ; let DS = psp
  573. else
  574.     mov    ds,ss:[_psp]    ; DS:SI is where the source strings are
  575. endif ;FARSTACK
  576.     mov    si,81H        ; address of strings
  577.  
  578.     assumes ds,nothing
  579.  
  580.     jmps    arg510
  581. ;
  582. ;    Skip blanks
  583. ;
  584. arg500:
  585.     xor    ax,ax
  586.     stosb
  587. arg510:
  588.     lodsb
  589.     cmp    al,C_BLANK
  590.     je    arg510
  591.     cmp    al,C_TAB
  592.     je    arg510
  593.  
  594. ifdef    WILDCARD
  595.     LDELIM    arg810
  596. else
  597. if    sizeD
  598.     LDELIM    arg810
  599. else
  600.     DELIM    arg810
  601. endif
  602. endif
  603.  
  604.     mov    ss:[bx],di
  605. if    sizeD
  606.     mov    ss:[bx+2],ss
  607.     add    bx,4
  608. else
  609.     inc    bx
  610.     inc    bx
  611. endif
  612.  
  613. ifdef    WILDCARD
  614.     mov    dx,di
  615.     stosb            ; initialize wildcard flag
  616. endif
  617. ;
  618. ;
  619. ; Parse an argument
  620. ;
  621. arg600:
  622.     dec    si        ; back up to reload character
  623. arg610:
  624.     lodsb
  625.  
  626.     cmp    al,C_BLANK
  627.     je    arg500
  628.     cmp    al,C_TAB
  629.     je    arg500        ; white space terminates argument
  630.  
  631.     DELIM    arg800
  632.  
  633.     cmp    al,C_QUOTE
  634.     je    arg710x
  635.  
  636.     cmp    al,C_BACKSLASH
  637.     je    arg620
  638.  
  639.  
  640.     stosb
  641.     jmps    arg610
  642. ;
  643. ; Count backslashes
  644. ;
  645. arg620:
  646.     xor    cx,cx
  647. arg621:
  648.     inc    cx        ; CX counts the backslashes
  649.     lodsb
  650.     cmp    al,C_BACKSLASH
  651.     je    arg621
  652. ;
  653.     cmp    al,C_QUOTE
  654.     je    arg630
  655.  
  656.     mov    al,C_BACKSLASH
  657.     rep    stosb        ; not followed by `"' -- treat `\'s normally
  658.     jmp    arg600
  659. ;
  660. arg630:
  661.     mov    al,C_BACKSLASH
  662.     shr    cx,1
  663.     rep    stosb
  664.     jnc    arg710x     ; " opens a quoted substring
  665.     mov    al,C_QUOTE
  666.     stosb
  667.     jmp    arg610        ; " was escaped with a \
  668. ;
  669. ; Enter a quoted string
  670. ;
  671. ifdef    WILDCARD
  672. arg710x:
  673.     inc    si        ; undoes the "DEC SI" between arg700 and arg710
  674. endif
  675.  
  676. arg700x:
  677.  
  678. ifdef    WILDCARD
  679.     xchg    dx,di        ; set the wildcard flag character to `"'
  680.     mov    al,C_QUOTE
  681.     stosb
  682.     dec    di
  683.     xchg    dx,di
  684. endif
  685.  
  686. arg700:
  687.     dec    si        ; back up to reload character
  688.  
  689. ifndef    WILDCARD
  690. arg710x:
  691. endif
  692.  
  693. arg710:
  694.     lodsb
  695.  
  696.     DELIM    arg800
  697.  
  698.     cmp    al,C_QUOTE
  699.     je    arg610        ; end of quoted portion of string
  700.  
  701.     cmp    al,C_BACKSLASH
  702.     je    arg720
  703.  
  704.  
  705.     stosb
  706.     jmp    arg710
  707. ;
  708. ; Count backslashes
  709. ;
  710. arg720:
  711.     xor    cx,cx
  712. arg721:
  713.     inc    cx        ; CX counts the backslashes
  714.     lodsb
  715.     cmp    al,C_BACKSLASH
  716.     je    arg721
  717. ;
  718.     cmp    al,C_QUOTE
  719.     je    arg730
  720.  
  721.     mov    al,C_BACKSLASH
  722.     rep    stosb        ; not followed by `"' -- treat `\'s normally
  723.     jmp    arg700x
  724. ;
  725. arg730:
  726.     mov    al,C_BACKSLASH
  727.     shr    cx,1
  728.     rep    stosb        ; store 1 for every pair of backslashes
  729.     jnc    arg610        ; " closes a quoted substring
  730.     mov    al,C_QUOTE    ; " was escaped with a \
  731.     stosb
  732.     jmps    arg710x
  733. ;
  734. ; Terminate last argument string, terminate list of argument pointers
  735. ;
  736. arg800:
  737.     xor    ax,ax
  738.     stosb            ; null-terminate final argument
  739. arg810:
  740.  
  741. ifdef FARSTACK
  742.     ifdef  _WINDOWS
  743.     callcrt _GetDGROUP
  744.     mov    ds, ax
  745.     else
  746.     mov    ax, DGROUP
  747.     mov    ds, ax
  748.     endif
  749. else
  750.     push    ss        ; default is SS == DGROUP
  751.     pop    ds
  752. endif
  753.     assumes ds,data
  754.  
  755. ifdef FARSTACK
  756.     mov    word ptr ss:[bx],0
  757.     mov    word ptr ss:[bx+2],0
  758. else
  759.     mov    word ptr [bx],0 ; add null pointer to __argv[]
  760. if    sizeD
  761.     mov    word ptr [bx+2],0
  762. endif
  763. endif ;FARSTACK
  764.  
  765. ifndef    WILDCARD
  766.     jmp    [retadr]    ; THE END
  767. else
  768.     call    _cwild
  769.     test    ax,ax
  770.     jz    no_arg_err
  771.  
  772.     mov    ax,_RT_SPACEARG ; 'not enough space for arguments'
  773.     jmp    _amsg_exit    ;
  774.  
  775. no_arg_err:
  776.     jmp    [retadr]
  777.  
  778. page
  779. ;***
  780. ;_find(dir) - find first matching file name against pattern "dir"
  781. ;
  782. ;Purpose:
  783. ;    _find(dir) - Find first matching file name against pattern "dir"
  784. ;    If dir == NULL, then get next match for current pattern.
  785. ;
  786. ;Entry:
  787. ;    dir    = DATA PTR of pattern to match
  788. ;
  789. ;Exit:
  790. ;    AX    = the address of a static area containing the file name if a
  791. ;          match was found.  Returns NULL if no match was found.
  792. ;
  793. ;Uses:
  794. ;    CX,DX, [dta_flag].
  795. ;
  796. ;Exceptions:
  797. ;
  798. ;*******************************************************************************
  799.  
  800. cProc    _find,<PUBLIC>
  801.     parmdp    dir
  802. cBegin
  803.     test    [dta_flag],-1
  804.     jnz    not_very_first
  805.  
  806.     mov    [dta_flag],-1
  807. ;
  808. ;    Set DTA, where the match structure is returned
  809. ;
  810.     mov    dx,dataOFFSET file_reserv
  811.     callos    setdma
  812. ;
  813. not_very_first:
  814.     mov    ah,DOS_findnext ; assume not first
  815.  
  816. if    sizeD
  817.     push    ds
  818.     lds    dx,dir
  819.     mov    cx,ds
  820.     jcxz    find_next
  821. else
  822.     mov    dx,dir
  823.     test    dx,dx
  824.     jz    find_next
  825. endif
  826.     mov    cx,A_D        ; match directories as well as files
  827.     mov    ah,DOS_findfirst
  828. find_next:
  829.     callos
  830. if    sizeD
  831.     pop    ds
  832. endif
  833.     mov    ax,dataOFFSET file_name
  834. if    sizeD
  835.     mov    dx,ds
  836. endif
  837.     jnc    retname
  838.  
  839.     xor    ax,ax        ; return 0 for no more matches
  840. if    sizeD
  841.     cwd
  842. endif
  843.  
  844. retname:
  845.  
  846. cEnd
  847.  
  848. endif                ;    WILDCARD    ; ***********************************************
  849.  
  850. sEnd    code
  851.  
  852.     end
  853.