home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / tc20 / setargv.asm < prev    next >
Assembly Source File  |  1988-08-28  |  17KB  |  729 lines

  1.     NAME    SETARGV
  2.     PAGE    60,132
  3. ;[]------------------------------------------------------------[]
  4. ;|    SETARGV.ASM -- Parse Command Line            |
  5. ;|                                |
  6. ;|    Turbo-C Run Time Library    version 2.0        |
  7. ;|                                |
  8. ;|    Copyright (c) 1988 by Borland International Inc.    |
  9. ;|    All Rights Reserved.                    |
  10. ;[]------------------------------------------------------------[]
  11.  
  12.     INCLUDE RULES.ASI
  13.  
  14. ;    Segment and Group declarations
  15.  
  16. Header@
  17.  
  18. ;    External references
  19.  
  20. ExtSym@        _argc, WORD, __CDECL__
  21. dPtrExt@    _argv, __CDECL__
  22. ExtSym@        _psp, WORD, __CDECL__
  23. ExtSym@        _envseg, WORD, __CDECL__
  24. ExtSym@        _envLng, WORD, __CDECL__
  25. ExtSym@        _osmajor, BYTE, __CDECL__
  26. ExtProc@    abort, __CDECL__
  27.  
  28. ifdef    WILD
  29. ExtProc@    sbrk, __CDECL__
  30. endif
  31.  
  32.     SUBTTL    Parse Command Line
  33.     PAGE
  34. ;/*                            */
  35. ;/*-----------------------------------------------------*/
  36. ;/*                            */
  37. ;/*    Parse Command Line                */
  38. ;/*    ------------------                */
  39. ;/*                            */
  40. ;/*-----------------------------------------------------*/
  41. ;/*                            */
  42. PSPCmd        equ    00080h
  43.  
  44. CSeg@
  45.  
  46. IF    LPROG
  47. SavedReturn    dd    ?
  48. ELSE
  49. SavedReturn    dw    ?
  50. ENDIF
  51. SavedDS        dw    ?
  52. SavedBP        dw    ?
  53.  
  54.  
  55. ifdef    WILD
  56.  
  57. ;------------------------------------------------------------------------------
  58. ;
  59. ; Not enough space on stack for the program name.
  60. ;
  61. BadProgName    label    near
  62.         jmp    abort@
  63.  
  64. endif
  65.  
  66. ;==============================================================================
  67.  
  68. ifdef    WILD
  69. PubProc@    _wildargv, __CDECL__
  70. else
  71. PubProc@    _setargv, __CDECL__
  72. endif
  73.  
  74. ;    First, save caller context and Return Address
  75.  
  76.         pop    word ptr SavedReturn
  77. IF    LPROG
  78.         pop    word ptr SavedReturn+2
  79. ENDIF
  80.         mov    SavedDS, ds
  81.         cld
  82.  
  83. ;    Compute Command Line size
  84.  
  85.         mov    es, _psp@
  86.         mov    si, PSPCmd    ; ES: SI = Command Line address
  87.         xor    ah, ah
  88.         lods    byte ptr es:[si]
  89.         inc    ax        ; AX = Command Line size including \r
  90.         mov    bp, es
  91.         xchg    dx, si        ; BP:DX = Command Line address
  92.         xchg    bx, ax        ; BX    = Command line size
  93.  
  94. ;    Compute Program Name size
  95.  
  96.         mov    si, _envLng@
  97.         add    si, 2        ; SI = Program name offset
  98.         mov    cx, 1        ; CX = Filename size (includes \0)
  99.         cmp    _osmajor@, 3
  100.         jb    NoProgramName
  101.         mov    es, _envseg@
  102.         mov    di, si        ; SI = argv[0] address
  103.         mov    cl, 07fh
  104.         xor    al, al
  105.         repnz    scasb
  106.         jcxz    BadProgName
  107.         xor    cl, 07fh    ; CX = Filename size (includes \0)
  108. NoProgramName    label    near
  109.  
  110. ;    Reserve space for the arguments
  111.  
  112.         sub    sp, 2        ; To be sure nothing in SS:FFFF
  113.         mov    ax, 1
  114. ifndef    WILD
  115.         add    ax, bx
  116. endif
  117.         add    ax, cx
  118.         and    ax, not 1
  119.         mov    di, sp
  120.         sub    di, ax
  121.         jb    BadProgName
  122.         mov    sp, di        ; SS:DI = Command Line storage address
  123.  
  124. ;    Copy ProgName to the stack
  125.  
  126.         mov    ax, es
  127.         mov    ds, ax
  128.         mov    ax, ss
  129.         mov    es, ax
  130. ifndef    WILD
  131.         push    cx
  132. endif
  133.         dec    cx
  134.         rep    movsb
  135.         xor    al, al
  136.         stosb            ; ASCIIZ string
  137.  
  138. ;    Process Command Line.
  139.  
  140. ;==============================================================================
  141. ifdef WILD
  142. ;==============================================================================
  143.  
  144. ;
  145. ; The value of "wild_attr" is used in the "findfirst" call as the file
  146. ; attribute.
  147. ;
  148. ; The default value is 0, which will only include "regular" files.
  149. ;
  150. ; Adding 10H to this value will include directories, 04h will include system
  151. ; files, and 02h will include hidden files.
  152. ;
  153.  
  154. wild_attr    equ    0            ; include only regular files
  155.  
  156. ;------------------------------------------------------------------------------
  157.  
  158. ffblk        struc
  159.  
  160. ff_reserved    db    21 dup (?)
  161. ff_attrib    db    ?
  162. ff_ftime    dw    ?
  163. ff_fdate    dw    ?
  164. ff_fsize    dd    ?
  165. ff_name        db    14 dup (?)
  166.  
  167. ffblk        ends
  168.  
  169. wild_init_space    equ    128            ; initial buffer allocation
  170. wild_more_space    equ    256            ; buffer size increment
  171.  
  172. ;------------------------------------------------------------------------------
  173.  
  174. wild_buff_addr    equ    [bp]
  175. wild_buff_size    equ    [bp+4]
  176. wild_buff_max    equ    [bp+6]
  177. wild_arg_src    equ    [bp+8]
  178. wild_arg_dst    equ    [bp+10]
  179.  
  180. wild_argument    equ    [bp+12]
  181. wild_destin    equ    [bp+16]
  182. wild_path_len    equ    [bp+20]
  183. wild_argc    equ    [bp+22]
  184.  
  185. wild_DTA_save    equ    [bp+24]
  186. wild_ffblk    equ    [bp+28]
  187.  
  188. wild_frame_size    equ    28 + TYPE ffblk
  189.  
  190. ;------------------------------------------------------------------------------
  191.  
  192.         mov    cx, bp            ; save segment of command line
  193.         dec    bx            ; don't need trailing \0
  194.  
  195.         sub    sp, wild_frame_size
  196.         mov    bp, sp            ; bp points at local variables
  197.  
  198.         push    dx            ; save cmd line addr
  199.         push    cx            ; save cmd line seg
  200.         push    bx            ; save cmd line size
  201.         mov    ax, wild_init_space
  202.         mov    wild_buff_size, ax    ; save initial size
  203. ifndef    __HUGE__
  204.         mov    ds, savedDS
  205. endif
  206.         push    ax
  207.         call    sbrk@        
  208.         pop    cx            ; toss parameter
  209.         pop    cx            ; restore cmd line size
  210.         pop    ds            ; restore cmd line seg
  211.         pop    si            ; restore cmd line addr
  212.  
  213.         mov    wild_buff_addr, ax    ; save offset
  214. if    LDATA
  215.         mov    wild_buff_addr+2, dx    ; save segment
  216.         and    ax, dx
  217. else
  218.         mov    wild_buff_addr+2, ss    ; seg = SS
  219. endif
  220.         cmp    ax, -1
  221.         je    NoSbrkSpace        ; abort if not enough space
  222.         add    ax, wild_buff_size
  223.         mov    wild_buff_max, ax    ; save max offset
  224.  
  225.         mov    ah, 2fh
  226.         int    21h            ; get current DTA
  227.         mov    wild_DTA_save, bx
  228.         mov    wild_DTA_save+2, es
  229.         push    ds
  230.         push    ss            ; fflbk is on stack
  231.         pop    ds
  232.         lea    dx, wild_ffblk
  233.         mov    ah, 1ah
  234.         int    21h            ; switch DTA to ffblk
  235.         pop    ds
  236.  
  237.         les    di, dword ptr wild_buff_addr        
  238.         xor    dx, dx            ; dx = # of arguments
  239. ;
  240. ; Start new argument.
  241. ;
  242. NewArg:        mov    wild_arg_dst, di
  243.         xor    bh, bh            ; bh = wildcard flag
  244. ;
  245. ; Skip leading whitespace.
  246. ;
  247. ArgCopy:    mov    wild_arg_src, si    ; save address of argument
  248.         call    GetChar
  249.         jc    ArgCopyDone        ; jump if no more characters
  250.         jz    ArgCopyLoop
  251.         cmp    al, ' '
  252.         je    ArgCopy            ; skip whitespace
  253.         cmp    al, 9
  254.         je    ArgCopy
  255.         cmp    al, 13
  256.         je    ArgCopy
  257.         cmp    al, '"'
  258.         je    ArgQuote        ; jump if quoted string
  259. ;
  260. ; Loop to copy unquoted argument.
  261. ;
  262. ArgCopyLoop:    call    ArgPushChar        ; store character in destination
  263.         call    GetChar
  264.         jc    ArgComplete        ; jump if end of line
  265.         jz    ArgCopyLoop        ; jump if \"
  266.         cmp    al, ' '
  267.         je    ArgComplete        ; whitespace terminates
  268.         cmp    al, 9
  269.         je    ArgComplete
  270.         cmp    al, 13
  271.         je    ArgComplete        ; whitespace terminates
  272.         cmp    al, '"'
  273.         jne    ArgCopyLoop
  274. ArgComplete:    call    ProcessArg        ; copy or expand argument
  275.         jmp    SHORT NewArg
  276.  
  277. NoSbrkSpace:    jmp    abort@            ; error jump
  278.  
  279. ;
  280. ; Here if quoted argument.
  281. ;
  282. ArgQuote:    call    GetChar
  283.         jc    QuoteDone
  284.         jz    QuoteNext
  285.         cmp    al, '"'            ; terminating quote ?
  286.         je    QuoteDone
  287. QuoteNext:    call    ArgPushChar        ; store character in destination
  288.         jmp    SHORT ArgQuote
  289. ;
  290. ; End of a quoted argument. Push terminating null, do not expand.
  291. ;
  292. QuoteDone:    xor    al, al
  293.         call    ArgPushChar        ; push terminating null
  294.         inc    dx            ; bump arg count
  295.         jmp    SHORT NewArg        ; go get more
  296.  
  297. ;------------------------------------------------------------------------------
  298. ;
  299. ; Here when done expanding command line. Go build the argv array.
  300. ;
  301. ArgCopyDone:    mov    ax, di            ; ax = unused space
  302.         sub    ax, wild_buff_max
  303.         jz    ArgNoWaste        ; skip if all used
  304.         push    dx
  305.         push    di
  306. ifndef    __HUGE__
  307.         mov    ds, savedDS
  308. endif
  309.         push    ax
  310.         call    sbrk@            ; release unused memory
  311.         pop    cx            ; toss parameter
  312.         pop    di
  313.         pop    dx
  314. ArgNoWaste:    lds    si, dword ptr wild_buff_addr
  315.         mov    cx, di
  316.         sub    cx, si            ; cx = number of bytes in expanded line
  317.         inc    dx            ; count program name
  318.         jmp    BuildArgv
  319.  
  320. ;------------------------------------------------------------------------------
  321. ;
  322. ; Routine to retrieve the next character from the command line.
  323. ;    Sets CF when end of line reached.
  324. ;    Sets ZF when \ character found (i.e. \")
  325. ;
  326. ;    bh.bit0 set if wildcard chars found (* or ?)
  327. ;    bh.bit1 set if \ character found (\")
  328. ;
  329. GetChar        proc    near
  330.  
  331.         jcxz    GchEnd            ; jump if no more
  332.         lodsb
  333.         dec    cx
  334.         cmp    al, '\'            ; escape ?
  335.         je    GchEsc
  336.         cmp    al, '?'
  337.         je    GchWild
  338.         cmp    al, '*'
  339.         je    GchWild
  340. GchRet:        or    ah, 1            ; clear CF and ZF
  341.         ret
  342. GchWild:    test    bh, bh
  343.         jnz    GchRet            ; give up if \" has been found
  344.         or    bh, 1
  345.         ret
  346. GchEsc:        jcxz    GchRet            ; check for \ at end of line
  347.         cmp    byte ptr [si],'"'
  348.         jne    GchRet            ; only \" is special
  349.         lodsb
  350.         dec    cx
  351.         mov    bh, 2            ; set \ flag
  352.         xor    ah, ah            ; clear CF, set ZF
  353.         ret
  354. GchEnd:        stc
  355.         ret
  356.  
  357. GetChar        endp
  358.  
  359. ;------------------------------------------------------------------------------
  360. ;
  361. ; Routine to expand a wildcard parameter.
  362. ;
  363. ;    DS:SI    =    argument address
  364. ;    ES:DI    =    destination
  365. ; Returns:
  366. ;    CX    =    number of expanded arguments (0 = no match)
  367. ;
  368. WildExpand    proc    near
  369.  
  370.         push    ds
  371.         mov    wild_argument, si
  372.         mov    wild_argument+2, ds
  373.         mov    wild_destin, di
  374.         mov    wild_destin+2, es
  375.         mov    word ptr wild_argc, 0
  376. ;
  377. ; Find the length of the path prefix, if any.
  378. ;
  379.         mov    bx, si
  380. WildFindPath:    lodsb
  381.         and    al, al
  382.         jz    WildEndPath
  383.         cmp    al, '\'
  384.         je    WildDelimiter
  385.         cmp    al, ':'
  386.         je    WildDelimiter
  387.         cmp    al, '\'
  388.         jne    WildFindPath
  389. WildDelimiter:    mov    bx, si            ; save addr past last delimiter
  390.         jmp    SHORT WildFindPath
  391. WildEndPath:    sub    bx, wild_argument
  392.         mov    wild_path_len, bx
  393.  
  394.         mov    ah, 4eh
  395.         mov    cx, wild_attr        ; file attribute
  396.         lds    dx, dword ptr wild_argument
  397.         int    21h            ; find first matching file ...
  398.         jc    WildDone
  399. ;
  400. ; We have a matching file. Add it to the destination string (unless "." or "..")
  401. ;
  402. WildAddArg:    
  403. ;
  404. ; If directories are included (10h set in wild_attr), ignore "." and ".."
  405. ;
  406. if    wild_attr AND 10h
  407.         push    ss
  408.         pop    ds
  409.         lea    si,wild_ffblk.ff_name
  410.         cmp    byte ptr [si],'.'    ; skip if doesn't start with "."
  411.         jne    WildNoDir
  412.         cmp    byte ptr [si+1],0    ; check for "."
  413.         je    WildNameNext
  414.         cmp    word ptr [si+1],'.'    ; check for ".."
  415.         je    WildNameNext
  416. WildNoDir:
  417. endif
  418.  
  419.         inc    word ptr wild_argc
  420.         les    di, dword ptr wild_destin
  421.         mov    cx, wild_path_len    ; prefix filename with path
  422.         jcxz    WildCopyName
  423.         lds    si, dword ptr wild_argument
  424. WildCopyPath:    lodsb
  425.         call    ArgPushChar
  426.         loop    WildCopyPath
  427. WildCopyName:    lea    si,wild_ffblk.ff_name    ; copy filename from ffblk
  428. WildNameLoop:    lods    byte ptr ss:[si]
  429.         push    ax
  430.         call    ArgPushChar        ; store char in destination
  431.         pop    ax
  432.         and    al, al            ; continue until \0
  433.         jnz    WildNameLoop
  434.         mov    wild_destin, di
  435. WildNameNext:    mov    ah, 4fh
  436.         int    21h            ; find next matching file
  437.         jnc    WildAddArg
  438. ;
  439. ; Done with expansion. Restore ES:DI, set CX, and return.
  440. ;
  441. WildDone:    mov    cx, wild_argc
  442.         les    di, dword ptr wild_destin
  443.         pop    ds
  444.         ret
  445.  
  446. WildExpand    endp
  447.  
  448. ;------------------------------------------------------------------------------
  449. ;
  450. ; Routine to store a character in the destination string.
  451. ;
  452. ArgPushChar    proc    near
  453.  
  454.         cmp    di, wild_buff_max    ; space available ?
  455.         jae    ArgMoreSpace
  456.         stosb                ; yes --> store character
  457.         ret
  458. ;
  459. ; No more argument space. Grab some more memory through sbrk.
  460. ;
  461. ArgMoreSpace:    push    ds
  462.         push    es
  463.         push    si
  464.         push    di
  465.         push    ax
  466.         push    bx
  467.         push    cx
  468.         push    dx
  469.  
  470. ifndef    __HUGE__
  471.         mov    ds, savedDS
  472. endif
  473.         mov    ax, wild_more_space
  474.         add    wild_buff_size, ax    ; bump allocated size
  475.         add    wild_buff_max, ax    ; bump end pointer
  476.         push    ax
  477.         call    sbrk@        
  478.         pop    cx
  479. if    LDATA
  480.         and    ax, dx
  481. endif
  482.         cmp    ax, -1
  483.         je    NoArgSpace        ; abort if not enough space
  484.  
  485.         pop    dx
  486.         pop    cx
  487.         pop    bx
  488.         pop    ax
  489.         pop    di
  490.         pop    si
  491.         pop    es
  492.         pop    ds
  493.         stosb                ; store character
  494.         ret
  495.  
  496. ArgPushChar    endp
  497.  
  498. ;------------------------------------------------------------------------------
  499. ;
  500. ; Not enough space to process the command line .... abort.
  501. ;
  502. NoArgSpace:    jmp    abort@
  503.  
  504. ;------------------------------------------------------------------------------
  505. ;
  506. ; Routine to process an argument. 
  507. ;
  508. ProcessArg    proc    near
  509.  
  510.         push    bx
  511.         xor    al, al
  512.         call    ArgPushChar        ; null-terminate
  513.         pop    bx
  514.         test    bh, 1            ; wildcards present ?
  515.         jnz    ArgWild
  516.         inc    dx            ; bump arg count
  517.         ret
  518. ;
  519. ; We have a wildcard argument. Expand it.
  520. ;
  521. ArgWild:    push    cx
  522.         push    [si]            ; save word following argument
  523.         mov    byte ptr [si],0        ; null-terminate argument
  524.         xchg    si, wild_arg_src    ; si = argument address
  525.         push    di
  526.         mov    di, wild_arg_dst
  527.         push    dx
  528.         call    WildExpand
  529.         pop    dx
  530.         pop    bx
  531.         and    cx, cx            ; see if any matched
  532.         jnz    ArgWildSome
  533.         mov    di, bx            ; none ---> use unexpanded argument
  534.         mov    cx, 1            ; bump arg count by 1
  535. ArgWildSome:    add    dx, cx
  536.         mov    si, wild_arg_src
  537.         pop    [si]            ; restore word following argument
  538.         pop    cx
  539.         ret
  540.  
  541. ProcessArg    endp
  542.  
  543. ;------------------------------------------------------------------------------
  544. ;
  545. ; Build the argv array. [DS:SI] is the expanded command line, CX its length.
  546. ; DX has the number of arguments (including the program name).
  547. ;
  548. BuildArgv:    push    ds
  549.         push    dx
  550.         lds    dx, dword ptr wild_DTA_save
  551.         mov    ah, 1ah
  552.         int    21h            ; switch to original DTA
  553.         pop    dx
  554.         pop    ds
  555.  
  556.         add    sp, wild_frame_size    ; remove local variables
  557.  
  558.         mov    es,savedDS
  559.         mov    es:[_argc@], dx
  560.         inc    dx            ; argv ends with a NULL pointer
  561.         shl    dx, 1            ;   argc * 2    (LDATA = 0)
  562. IF    LDATA
  563.         shl    dx, 1            ;   argc * 4    (LDATA = 1)
  564. ENDIF
  565.         mov    bx, sp            ; point to program name
  566.         mov    bp, sp
  567.         sub    bp, dx
  568.         jb    NoArgSpace
  569.         mov    sp, bp            ; SS:BP = argv array address
  570.         mov    word ptr es:[_argv@], bp
  571. IF    LDATA
  572.         mov    word ptr es:[_argv@+2], ss
  573. ENDIF
  574.         mov    [bp], bx        ; set argv[0] to program name
  575. IF    LDATA
  576.         mov    [bp+2], ss        ; program name is on the stack
  577. ENDIF
  578.         add    bp, dPtrSize
  579.  
  580. SetArgvX    label    near
  581.         jcxz    SetLastArg
  582.         mov    [bp], si        ; Set argv[n]
  583. IF    LDATA
  584.         mov    [bp+2], ds
  585. ENDIF
  586.         add    bp, dPtrSize
  587. CopyArg        label    near
  588.         lodsb
  589.         or    al, al
  590.         loopnz    CopyArg
  591.         jz    SetArgvX
  592. SetLastArg    label    near
  593.         xor    ax, ax
  594.         mov    [bp], ax
  595. IF    LDATA
  596.         mov    [bp+2], ax
  597. ENDIF
  598.         mov    ds, savedDS
  599.  
  600. ;==============================================================================
  601. else
  602. ;==============================================================================
  603.  
  604.         mov    ds, bp
  605.         xchg    si, dx        ; DS: SI = Command Line address
  606.         xchg    bx, cx        ; CX = Command Line size including \r
  607.         mov    ax, bx
  608.         mov    dx, ax        ; AX = BX = DX = 0
  609.         inc    bx        ; BX = Nb of arguments (at least 1)
  610. Processing    label    near
  611.         call    NextChar
  612.         ja    NotQuote    ; Not a quote and there are more
  613. InString    label    near
  614.         jb    BuildArgv    ; Command line is empty now
  615.         call    NextChar
  616.         ja    InString    ; Not a quote and there are more
  617. NotQuote    label    near
  618.         cmp    al, ' '
  619.         je    EndArgument    ; Space is an argument separator
  620.         cmp    al, 13
  621.         je    EndArgument    ; \r    is an argument separator
  622.         cmp    al, 9
  623.         jne    Processing    ; \t    is an argument separator
  624. EndArgument    label    near
  625.         xor    al, al        ; Space and TAB are argument separators
  626.         jmp    short Processing
  627.  
  628. ;    Character test function used in SetArgs
  629. ;        On entry AL holds the previous character
  630. ;        On exit     AL holds the next character
  631. ;             ZF on if the next character is quote (") and AL = 0
  632. ;             CF on if end of command line and AL = 0
  633.  
  634. NextChar    PROC    NEAR
  635.         or    ax, ax
  636.         jz    NextChar0
  637.         inc    dx        ; DX = Actual length of CmdLine
  638.         stosb
  639.         or    al, al
  640.         jnz    NextChar0
  641.         inc    bx        ; BX = Number of parameters
  642. NextChar0    label    near
  643.         xchg    ah, al
  644.         xor    al, al
  645.         stc
  646.         jcxz    NextChar2    ; End of command line --> CF ON
  647.         lodsb
  648.         dec    cx
  649.         sub    al, '"'
  650.         jz    NextChar2    ; Quote found --> AL = 0 and ZF ON
  651.         add    al, '"'
  652.         cmp    al,'\'
  653.         jne    NextChar1    ; It is not a \
  654.         cmp    byte ptr ds:[si], '"'
  655.         jne    NextChar1    ; Only " is transparent after \
  656.         lodsb
  657.         dec    cx
  658. NextChar1    label    near
  659.         or    si, si        ; Be sure both CF & ZF are OFF
  660. NextChar2    label    near
  661.         ret
  662. NextChar    ENDP
  663.  
  664. ;    Invalid program name
  665.  
  666. BadProgName    label    near
  667.         jmp    abort@
  668.  
  669. ;    Now, build the argv array
  670.  
  671. BuildArgv    label    near
  672.         pop    cx
  673.         add    cx, dx        ; CX = Argument area size
  674.         mov    ds, SavedDS
  675.         mov    _argc@, bx
  676.         inc    bx        ; argv ends with a NULL pointer
  677.         add    bx, bx        ;     argc * 2    (LDATA = 0)
  678. IF    LDATA
  679.         add    bx, bx        ;     argc * 4    (LDATA = 1)
  680. ENDIF
  681.         mov    si, sp
  682.         mov    bp, sp
  683.         sub    bp, bx
  684.         jb    BadProgName
  685.         mov    sp, bp        ; SS:BP = argv array address
  686.         mov    word ptr _argv@, bp
  687. IF    LDATA
  688.         mov    word ptr _argv@+2, ss
  689. ENDIF
  690. SetArgvX    label    near
  691.         jcxz    SetLastArg
  692.         mov    [bp], si    ; Set argv[n]
  693. IF    LDATA
  694.         mov    [bp+2], ss
  695. ENDIF
  696.         add    bp, dPtrSize
  697. CopyArg        label    near
  698.         lods    byte ptr ss:[si]
  699.         or    al, al
  700.         loopnz    CopyArg
  701.         jz    SetArgvX
  702. SetLastArg    label    near
  703.         xor    ax, ax
  704.         mov    [bp], ax
  705. IF    LDATA
  706.         mov    [bp+2], ax
  707. ENDIF
  708.  
  709. ;==============================================================================
  710. endif        ;    ifdef WILD
  711. ;==============================================================================
  712.  
  713. ;    Restore caller context and exit
  714.  
  715. IF    LPROG
  716.         jmp    dword ptr SavedReturn
  717. ELSE
  718.         jmp    word ptr SavedReturn
  719. ENDIF
  720.  
  721. ifdef    WILD
  722. EndProc@    _wildargv, __CDECL__
  723. else
  724. EndProc@    _setargv, __CDECL__
  725. endif
  726.  
  727. CSegEnd@
  728.     END
  729.