home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / SETARGV.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-06-07  |  18.1 KB  |  762 lines

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