729 lines
16 KiB
NASM
729 lines
16 KiB
NASM
|
NAME SETARGV
|
|||
|
PAGE 60,132
|
|||
|
;[]------------------------------------------------------------[]
|
|||
|
;| SETARGV.ASM -- Parse Command Line |
|
|||
|
;| |
|
|||
|
;| Turbo-C Run Time Library version 2.0 |
|
|||
|
;| |
|
|||
|
;| Copyright (c) 1988 by Borland International Inc. |
|
|||
|
;| All Rights Reserved. |
|
|||
|
;[]------------------------------------------------------------[]
|
|||
|
|
|||
|
INCLUDE RULES.ASI
|
|||
|
|
|||
|
; Segment and Group declarations
|
|||
|
|
|||
|
Header@
|
|||
|
|
|||
|
; External references
|
|||
|
|
|||
|
ExtSym@ _argc, WORD, __CDECL__
|
|||
|
dPtrExt@ _argv, __CDECL__
|
|||
|
ExtSym@ _psp, WORD, __CDECL__
|
|||
|
ExtSym@ _envseg, WORD, __CDECL__
|
|||
|
ExtSym@ _envLng, WORD, __CDECL__
|
|||
|
ExtSym@ _osmajor, BYTE, __CDECL__
|
|||
|
ExtProc@ abort, __CDECL__
|
|||
|
|
|||
|
ifdef WILD
|
|||
|
ExtProc@ sbrk, __CDECL__
|
|||
|
endif
|
|||
|
|
|||
|
SUBTTL Parse Command Line
|
|||
|
PAGE
|
|||
|
;/* */
|
|||
|
;/*-----------------------------------------------------*/
|
|||
|
;/* */
|
|||
|
;/* Parse Command Line */
|
|||
|
;/* ------------------ */
|
|||
|
;/* */
|
|||
|
;/*-----------------------------------------------------*/
|
|||
|
;/* */
|
|||
|
PSPCmd equ 00080h
|
|||
|
|
|||
|
CSeg@
|
|||
|
|
|||
|
IF LPROG
|
|||
|
SavedReturn dd ?
|
|||
|
ELSE
|
|||
|
SavedReturn dw ?
|
|||
|
ENDIF
|
|||
|
SavedDS dw ?
|
|||
|
SavedBP dw ?
|
|||
|
|
|||
|
|
|||
|
ifdef WILD
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Not enough space on stack for the program name.
|
|||
|
;
|
|||
|
BadProgName label near
|
|||
|
jmp abort@
|
|||
|
|
|||
|
endif
|
|||
|
|
|||
|
;==============================================================================
|
|||
|
|
|||
|
ifdef WILD
|
|||
|
PubProc@ _wildargv, __CDECL__
|
|||
|
else
|
|||
|
PubProc@ _setargv, __CDECL__
|
|||
|
endif
|
|||
|
|
|||
|
; First, save caller context and Return Address
|
|||
|
|
|||
|
pop word ptr SavedReturn
|
|||
|
IF LPROG
|
|||
|
pop word ptr SavedReturn+2
|
|||
|
ENDIF
|
|||
|
mov SavedDS, ds
|
|||
|
cld
|
|||
|
|
|||
|
; Compute Command Line size
|
|||
|
|
|||
|
mov es, _psp@
|
|||
|
mov si, PSPCmd ; ES: SI = Command Line address
|
|||
|
xor ah, ah
|
|||
|
lods byte ptr es:[si]
|
|||
|
inc ax ; AX = Command Line size including \r
|
|||
|
mov bp, es
|
|||
|
xchg dx, si ; BP:DX = Command Line address
|
|||
|
xchg bx, ax ; BX = Command line size
|
|||
|
|
|||
|
; Compute Program Name size
|
|||
|
|
|||
|
mov si, _envLng@
|
|||
|
add si, 2 ; SI = Program name offset
|
|||
|
mov cx, 1 ; CX = Filename size (includes \0)
|
|||
|
cmp _osmajor@, 3
|
|||
|
jb NoProgramName
|
|||
|
mov es, _envseg@
|
|||
|
mov di, si ; SI = argv[0] address
|
|||
|
mov cl, 07fh
|
|||
|
xor al, al
|
|||
|
repnz scasb
|
|||
|
jcxz BadProgName
|
|||
|
xor cl, 07fh ; CX = Filename size (includes \0)
|
|||
|
NoProgramName label near
|
|||
|
|
|||
|
; Reserve space for the arguments
|
|||
|
|
|||
|
sub sp, 2 ; To be sure nothing in SS:FFFF
|
|||
|
mov ax, 1
|
|||
|
ifndef WILD
|
|||
|
add ax, bx
|
|||
|
endif
|
|||
|
add ax, cx
|
|||
|
and ax, not 1
|
|||
|
mov di, sp
|
|||
|
sub di, ax
|
|||
|
jb BadProgName
|
|||
|
mov sp, di ; SS:DI = Command Line storage address
|
|||
|
|
|||
|
; Copy ProgName to the stack
|
|||
|
|
|||
|
mov ax, es
|
|||
|
mov ds, ax
|
|||
|
mov ax, ss
|
|||
|
mov es, ax
|
|||
|
ifndef WILD
|
|||
|
push cx
|
|||
|
endif
|
|||
|
dec cx
|
|||
|
rep movsb
|
|||
|
xor al, al
|
|||
|
stosb ; ASCIIZ string
|
|||
|
|
|||
|
; Process Command Line.
|
|||
|
|
|||
|
;==============================================================================
|
|||
|
ifdef WILD
|
|||
|
;==============================================================================
|
|||
|
|
|||
|
;
|
|||
|
; The value of "wild_attr" is used in the "findfirst" call as the file
|
|||
|
; attribute.
|
|||
|
;
|
|||
|
; The default value is 0, which will only include "regular" files.
|
|||
|
;
|
|||
|
; Adding 10H to this value will include directories, 04h will include system
|
|||
|
; files, and 02h will include hidden files.
|
|||
|
;
|
|||
|
|
|||
|
wild_attr equ 0 ; include only regular files
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
ffblk struc
|
|||
|
|
|||
|
ff_reserved db 21 dup (?)
|
|||
|
ff_attrib db ?
|
|||
|
ff_ftime dw ?
|
|||
|
ff_fdate dw ?
|
|||
|
ff_fsize dd ?
|
|||
|
ff_name db 14 dup (?)
|
|||
|
|
|||
|
ffblk ends
|
|||
|
|
|||
|
wild_init_space equ 128 ; initial buffer allocation
|
|||
|
wild_more_space equ 256 ; buffer size increment
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
wild_buff_addr equ [bp]
|
|||
|
wild_buff_size equ [bp+4]
|
|||
|
wild_buff_max equ [bp+6]
|
|||
|
wild_arg_src equ [bp+8]
|
|||
|
wild_arg_dst equ [bp+10]
|
|||
|
|
|||
|
wild_argument equ [bp+12]
|
|||
|
wild_destin equ [bp+16]
|
|||
|
wild_path_len equ [bp+20]
|
|||
|
wild_argc equ [bp+22]
|
|||
|
|
|||
|
wild_DTA_save equ [bp+24]
|
|||
|
wild_ffblk equ [bp+28]
|
|||
|
|
|||
|
wild_frame_size equ 28 + TYPE ffblk
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
mov cx, bp ; save segment of command line
|
|||
|
dec bx ; don't need trailing \0
|
|||
|
|
|||
|
sub sp, wild_frame_size
|
|||
|
mov bp, sp ; bp points at local variables
|
|||
|
|
|||
|
push dx ; save cmd line addr
|
|||
|
push cx ; save cmd line seg
|
|||
|
push bx ; save cmd line size
|
|||
|
mov ax, wild_init_space
|
|||
|
mov wild_buff_size, ax ; save initial size
|
|||
|
ifndef __HUGE__
|
|||
|
mov ds, savedDS
|
|||
|
endif
|
|||
|
push ax
|
|||
|
call sbrk@
|
|||
|
pop cx ; toss parameter
|
|||
|
pop cx ; restore cmd line size
|
|||
|
pop ds ; restore cmd line seg
|
|||
|
pop si ; restore cmd line addr
|
|||
|
|
|||
|
mov wild_buff_addr, ax ; save offset
|
|||
|
if LDATA
|
|||
|
mov wild_buff_addr+2, dx ; save segment
|
|||
|
and ax, dx
|
|||
|
else
|
|||
|
mov wild_buff_addr+2, ss ; seg = SS
|
|||
|
endif
|
|||
|
cmp ax, -1
|
|||
|
je NoSbrkSpace ; abort if not enough space
|
|||
|
add ax, wild_buff_size
|
|||
|
mov wild_buff_max, ax ; save max offset
|
|||
|
|
|||
|
mov ah, 2fh
|
|||
|
int 21h ; get current DTA
|
|||
|
mov wild_DTA_save, bx
|
|||
|
mov wild_DTA_save+2, es
|
|||
|
push ds
|
|||
|
push ss ; fflbk is on stack
|
|||
|
pop ds
|
|||
|
lea dx, wild_ffblk
|
|||
|
mov ah, 1ah
|
|||
|
int 21h ; switch DTA to ffblk
|
|||
|
pop ds
|
|||
|
|
|||
|
les di, dword ptr wild_buff_addr
|
|||
|
xor dx, dx ; dx = # of arguments
|
|||
|
;
|
|||
|
; Start new argument.
|
|||
|
;
|
|||
|
NewArg: mov wild_arg_dst, di
|
|||
|
xor bh, bh ; bh = wildcard flag
|
|||
|
;
|
|||
|
; Skip leading whitespace.
|
|||
|
;
|
|||
|
ArgCopy: mov wild_arg_src, si ; save address of argument
|
|||
|
call GetChar
|
|||
|
jc ArgCopyDone ; jump if no more characters
|
|||
|
jz ArgCopyLoop
|
|||
|
cmp al, ' '
|
|||
|
je ArgCopy ; skip whitespace
|
|||
|
cmp al, 9
|
|||
|
je ArgCopy
|
|||
|
cmp al, 13
|
|||
|
je ArgCopy
|
|||
|
cmp al, '"'
|
|||
|
je ArgQuote ; jump if quoted string
|
|||
|
;
|
|||
|
; Loop to copy unquoted argument.
|
|||
|
;
|
|||
|
ArgCopyLoop: call ArgPushChar ; store character in destination
|
|||
|
call GetChar
|
|||
|
jc ArgComplete ; jump if end of line
|
|||
|
jz ArgCopyLoop ; jump if \"
|
|||
|
cmp al, ' '
|
|||
|
je ArgComplete ; whitespace terminates
|
|||
|
cmp al, 9
|
|||
|
je ArgComplete
|
|||
|
cmp al, 13
|
|||
|
je ArgComplete ; whitespace terminates
|
|||
|
cmp al, '"'
|
|||
|
jne ArgCopyLoop
|
|||
|
ArgComplete: call ProcessArg ; copy or expand argument
|
|||
|
jmp SHORT NewArg
|
|||
|
|
|||
|
NoSbrkSpace: jmp abort@ ; error jump
|
|||
|
|
|||
|
;
|
|||
|
; Here if quoted argument.
|
|||
|
;
|
|||
|
ArgQuote: call GetChar
|
|||
|
jc QuoteDone
|
|||
|
jz QuoteNext
|
|||
|
cmp al, '"' ; terminating quote ?
|
|||
|
je QuoteDone
|
|||
|
QuoteNext: call ArgPushChar ; store character in destination
|
|||
|
jmp SHORT ArgQuote
|
|||
|
;
|
|||
|
; End of a quoted argument. Push terminating null, do not expand.
|
|||
|
;
|
|||
|
QuoteDone: xor al, al
|
|||
|
call ArgPushChar ; push terminating null
|
|||
|
inc dx ; bump arg count
|
|||
|
jmp SHORT NewArg ; go get more
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Here when done expanding command line. Go build the argv array.
|
|||
|
;
|
|||
|
ArgCopyDone: mov ax, di ; ax = unused space
|
|||
|
sub ax, wild_buff_max
|
|||
|
jz ArgNoWaste ; skip if all used
|
|||
|
push dx
|
|||
|
push di
|
|||
|
ifndef __HUGE__
|
|||
|
mov ds, savedDS
|
|||
|
endif
|
|||
|
push ax
|
|||
|
call sbrk@ ; release unused memory
|
|||
|
pop cx ; toss parameter
|
|||
|
pop di
|
|||
|
pop dx
|
|||
|
ArgNoWaste: lds si, dword ptr wild_buff_addr
|
|||
|
mov cx, di
|
|||
|
sub cx, si ; cx = number of bytes in expanded line
|
|||
|
inc dx ; count program name
|
|||
|
jmp BuildArgv
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Routine to retrieve the next character from the command line.
|
|||
|
; Sets CF when end of line reached.
|
|||
|
; Sets ZF when \ character found (i.e. \")
|
|||
|
;
|
|||
|
; bh.bit0 set if wildcard chars found (* or ?)
|
|||
|
; bh.bit1 set if \ character found (\")
|
|||
|
;
|
|||
|
GetChar proc near
|
|||
|
|
|||
|
jcxz GchEnd ; jump if no more
|
|||
|
lodsb
|
|||
|
dec cx
|
|||
|
cmp al, '\' ; escape ?
|
|||
|
je GchEsc
|
|||
|
cmp al, '?'
|
|||
|
je GchWild
|
|||
|
cmp al, '*'
|
|||
|
je GchWild
|
|||
|
GchRet: or ah, 1 ; clear CF and ZF
|
|||
|
ret
|
|||
|
GchWild: test bh, bh
|
|||
|
jnz GchRet ; give up if \" has been found
|
|||
|
or bh, 1
|
|||
|
ret
|
|||
|
GchEsc: jcxz GchRet ; check for \ at end of line
|
|||
|
cmp byte ptr [si],'"'
|
|||
|
jne GchRet ; only \" is special
|
|||
|
lodsb
|
|||
|
dec cx
|
|||
|
mov bh, 2 ; set \ flag
|
|||
|
xor ah, ah ; clear CF, set ZF
|
|||
|
ret
|
|||
|
GchEnd: stc
|
|||
|
ret
|
|||
|
|
|||
|
GetChar endp
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Routine to expand a wildcard parameter.
|
|||
|
;
|
|||
|
; DS:SI = argument address
|
|||
|
; ES:DI = destination
|
|||
|
; Returns:
|
|||
|
; CX = number of expanded arguments (0 = no match)
|
|||
|
;
|
|||
|
WildExpand proc near
|
|||
|
|
|||
|
push ds
|
|||
|
mov wild_argument, si
|
|||
|
mov wild_argument+2, ds
|
|||
|
mov wild_destin, di
|
|||
|
mov wild_destin+2, es
|
|||
|
mov word ptr wild_argc, 0
|
|||
|
;
|
|||
|
; Find the length of the path prefix, if any.
|
|||
|
;
|
|||
|
mov bx, si
|
|||
|
WildFindPath: lodsb
|
|||
|
and al, al
|
|||
|
jz WildEndPath
|
|||
|
cmp al, '\'
|
|||
|
je WildDelimiter
|
|||
|
cmp al, ':'
|
|||
|
je WildDelimiter
|
|||
|
cmp al, '\'
|
|||
|
jne WildFindPath
|
|||
|
WildDelimiter: mov bx, si ; save addr past last delimiter
|
|||
|
jmp SHORT WildFindPath
|
|||
|
WildEndPath: sub bx, wild_argument
|
|||
|
mov wild_path_len, bx
|
|||
|
|
|||
|
mov ah, 4eh
|
|||
|
mov cx, wild_attr ; file attribute
|
|||
|
lds dx, dword ptr wild_argument
|
|||
|
int 21h ; find first matching file ...
|
|||
|
jc WildDone
|
|||
|
;
|
|||
|
; We have a matching file. Add it to the destination string (unless "." or "..")
|
|||
|
;
|
|||
|
WildAddArg:
|
|||
|
;
|
|||
|
; If directories are included (10h set in wild_attr), ignore "." and ".."
|
|||
|
;
|
|||
|
if wild_attr AND 10h
|
|||
|
push ss
|
|||
|
pop ds
|
|||
|
lea si,wild_ffblk.ff_name
|
|||
|
cmp byte ptr [si],'.' ; skip if doesn't start with "."
|
|||
|
jne WildNoDir
|
|||
|
cmp byte ptr [si+1],0 ; check for "."
|
|||
|
je WildNameNext
|
|||
|
cmp word ptr [si+1],'.' ; check for ".."
|
|||
|
je WildNameNext
|
|||
|
WildNoDir:
|
|||
|
endif
|
|||
|
|
|||
|
inc word ptr wild_argc
|
|||
|
les di, dword ptr wild_destin
|
|||
|
mov cx, wild_path_len ; prefix filename with path
|
|||
|
jcxz WildCopyName
|
|||
|
lds si, dword ptr wild_argument
|
|||
|
WildCopyPath: lodsb
|
|||
|
call ArgPushChar
|
|||
|
loop WildCopyPath
|
|||
|
WildCopyName: lea si,wild_ffblk.ff_name ; copy filename from ffblk
|
|||
|
WildNameLoop: lods byte ptr ss:[si]
|
|||
|
push ax
|
|||
|
call ArgPushChar ; store char in destination
|
|||
|
pop ax
|
|||
|
and al, al ; continue until \0
|
|||
|
jnz WildNameLoop
|
|||
|
mov wild_destin, di
|
|||
|
WildNameNext: mov ah, 4fh
|
|||
|
int 21h ; find next matching file
|
|||
|
jnc WildAddArg
|
|||
|
;
|
|||
|
; Done with expansion. Restore ES:DI, set CX, and return.
|
|||
|
;
|
|||
|
WildDone: mov cx, wild_argc
|
|||
|
les di, dword ptr wild_destin
|
|||
|
pop ds
|
|||
|
ret
|
|||
|
|
|||
|
WildExpand endp
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Routine to store a character in the destination string.
|
|||
|
;
|
|||
|
ArgPushChar proc near
|
|||
|
|
|||
|
cmp di, wild_buff_max ; space available ?
|
|||
|
jae ArgMoreSpace
|
|||
|
stosb ; yes --> store character
|
|||
|
ret
|
|||
|
;
|
|||
|
; No more argument space. Grab some more memory through sbrk.
|
|||
|
;
|
|||
|
ArgMoreSpace: push ds
|
|||
|
push es
|
|||
|
push si
|
|||
|
push di
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
|
|||
|
ifndef __HUGE__
|
|||
|
mov ds, savedDS
|
|||
|
endif
|
|||
|
mov ax, wild_more_space
|
|||
|
add wild_buff_size, ax ; bump allocated size
|
|||
|
add wild_buff_max, ax ; bump end pointer
|
|||
|
push ax
|
|||
|
call sbrk@
|
|||
|
pop cx
|
|||
|
if LDATA
|
|||
|
and ax, dx
|
|||
|
endif
|
|||
|
cmp ax, -1
|
|||
|
je NoArgSpace ; abort if not enough space
|
|||
|
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop es
|
|||
|
pop ds
|
|||
|
stosb ; store character
|
|||
|
ret
|
|||
|
|
|||
|
ArgPushChar endp
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Not enough space to process the command line .... abort.
|
|||
|
;
|
|||
|
NoArgSpace: jmp abort@
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Routine to process an argument.
|
|||
|
;
|
|||
|
ProcessArg proc near
|
|||
|
|
|||
|
push bx
|
|||
|
xor al, al
|
|||
|
call ArgPushChar ; null-terminate
|
|||
|
pop bx
|
|||
|
test bh, 1 ; wildcards present ?
|
|||
|
jnz ArgWild
|
|||
|
inc dx ; bump arg count
|
|||
|
ret
|
|||
|
;
|
|||
|
; We have a wildcard argument. Expand it.
|
|||
|
;
|
|||
|
ArgWild: push cx
|
|||
|
push [si] ; save word following argument
|
|||
|
mov byte ptr [si],0 ; null-terminate argument
|
|||
|
xchg si, wild_arg_src ; si = argument address
|
|||
|
push di
|
|||
|
mov di, wild_arg_dst
|
|||
|
push dx
|
|||
|
call WildExpand
|
|||
|
pop dx
|
|||
|
pop bx
|
|||
|
and cx, cx ; see if any matched
|
|||
|
jnz ArgWildSome
|
|||
|
mov di, bx ; none ---> use unexpanded argument
|
|||
|
mov cx, 1 ; bump arg count by 1
|
|||
|
ArgWildSome: add dx, cx
|
|||
|
mov si, wild_arg_src
|
|||
|
pop [si] ; restore word following argument
|
|||
|
pop cx
|
|||
|
ret
|
|||
|
|
|||
|
ProcessArg endp
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Build the argv array. [DS:SI] is the expanded command line, CX its length.
|
|||
|
; DX has the number of arguments (including the program name).
|
|||
|
;
|
|||
|
BuildArgv: push ds
|
|||
|
push dx
|
|||
|
lds dx, dword ptr wild_DTA_save
|
|||
|
mov ah, 1ah
|
|||
|
int 21h ; switch to original DTA
|
|||
|
pop dx
|
|||
|
pop ds
|
|||
|
|
|||
|
add sp, wild_frame_size ; remove local variables
|
|||
|
|
|||
|
mov es,savedDS
|
|||
|
mov es:[_argc@], dx
|
|||
|
inc dx ; argv ends with a NULL pointer
|
|||
|
shl dx, 1 ; argc * 2 (LDATA = 0)
|
|||
|
IF LDATA
|
|||
|
shl dx, 1 ; argc * 4 (LDATA = 1)
|
|||
|
ENDIF
|
|||
|
mov bx, sp ; point to program name
|
|||
|
mov bp, sp
|
|||
|
sub bp, dx
|
|||
|
jb NoArgSpace
|
|||
|
mov sp, bp ; SS:BP = argv array address
|
|||
|
mov word ptr es:[_argv@], bp
|
|||
|
IF LDATA
|
|||
|
mov word ptr es:[_argv@+2], ss
|
|||
|
ENDIF
|
|||
|
mov [bp], bx ; set argv[0] to program name
|
|||
|
IF LDATA
|
|||
|
mov [bp+2], ss ; program name is on the stack
|
|||
|
ENDIF
|
|||
|
add bp, dPtrSize
|
|||
|
|
|||
|
SetArgvX label near
|
|||
|
jcxz SetLastArg
|
|||
|
mov [bp], si ; Set argv[n]
|
|||
|
IF LDATA
|
|||
|
mov [bp+2], ds
|
|||
|
ENDIF
|
|||
|
add bp, dPtrSize
|
|||
|
CopyArg label near
|
|||
|
lodsb
|
|||
|
or al, al
|
|||
|
loopnz CopyArg
|
|||
|
jz SetArgvX
|
|||
|
SetLastArg label near
|
|||
|
xor ax, ax
|
|||
|
mov [bp], ax
|
|||
|
IF LDATA
|
|||
|
mov [bp+2], ax
|
|||
|
ENDIF
|
|||
|
mov ds, savedDS
|
|||
|
|
|||
|
;==============================================================================
|
|||
|
else
|
|||
|
;==============================================================================
|
|||
|
|
|||
|
mov ds, bp
|
|||
|
xchg si, dx ; DS: SI = Command Line address
|
|||
|
xchg bx, cx ; CX = Command Line size including \r
|
|||
|
mov ax, bx
|
|||
|
mov dx, ax ; AX = BX = DX = 0
|
|||
|
inc bx ; BX = Nb of arguments (at least 1)
|
|||
|
Processing label near
|
|||
|
call NextChar
|
|||
|
ja NotQuote ; Not a quote and there are more
|
|||
|
InString label near
|
|||
|
jb BuildArgv ; Command line is empty now
|
|||
|
call NextChar
|
|||
|
ja InString ; Not a quote and there are more
|
|||
|
NotQuote label near
|
|||
|
cmp al, ' '
|
|||
|
je EndArgument ; Space is an argument separator
|
|||
|
cmp al, 13
|
|||
|
je EndArgument ; \r is an argument separator
|
|||
|
cmp al, 9
|
|||
|
jne Processing ; \t is an argument separator
|
|||
|
EndArgument label near
|
|||
|
xor al, al ; Space and TAB are argument separators
|
|||
|
jmp short Processing
|
|||
|
|
|||
|
; Character test function used in SetArgs
|
|||
|
; On entry AL holds the previous character
|
|||
|
; On exit AL holds the next character
|
|||
|
; ZF on if the next character is quote (") and AL = 0
|
|||
|
; CF on if end of command line and AL = 0
|
|||
|
|
|||
|
NextChar PROC NEAR
|
|||
|
or ax, ax
|
|||
|
jz NextChar0
|
|||
|
inc dx ; DX = Actual length of CmdLine
|
|||
|
stosb
|
|||
|
or al, al
|
|||
|
jnz NextChar0
|
|||
|
inc bx ; BX = Number of parameters
|
|||
|
NextChar0 label near
|
|||
|
xchg ah, al
|
|||
|
xor al, al
|
|||
|
stc
|
|||
|
jcxz NextChar2 ; End of command line --> CF ON
|
|||
|
lodsb
|
|||
|
dec cx
|
|||
|
sub al, '"'
|
|||
|
jz NextChar2 ; Quote found --> AL = 0 and ZF ON
|
|||
|
add al, '"'
|
|||
|
cmp al,'\'
|
|||
|
jne NextChar1 ; It is not a \
|
|||
|
cmp byte ptr ds:[si], '"'
|
|||
|
jne NextChar1 ; Only " is transparent after \
|
|||
|
lodsb
|
|||
|
dec cx
|
|||
|
NextChar1 label near
|
|||
|
or si, si ; Be sure both CF & ZF are OFF
|
|||
|
NextChar2 label near
|
|||
|
ret
|
|||
|
NextChar ENDP
|
|||
|
|
|||
|
; Invalid program name
|
|||
|
|
|||
|
BadProgName label near
|
|||
|
jmp abort@
|
|||
|
|
|||
|
; Now, build the argv array
|
|||
|
|
|||
|
BuildArgv label near
|
|||
|
pop cx
|
|||
|
add cx, dx ; CX = Argument area size
|
|||
|
mov ds, SavedDS
|
|||
|
mov _argc@, bx
|
|||
|
inc bx ; argv ends with a NULL pointer
|
|||
|
add bx, bx ; argc * 2 (LDATA = 0)
|
|||
|
IF LDATA
|
|||
|
add bx, bx ; argc * 4 (LDATA = 1)
|
|||
|
ENDIF
|
|||
|
mov si, sp
|
|||
|
mov bp, sp
|
|||
|
sub bp, bx
|
|||
|
jb BadProgName
|
|||
|
mov sp, bp ; SS:BP = argv array address
|
|||
|
mov word ptr _argv@, bp
|
|||
|
IF LDATA
|
|||
|
mov word ptr _argv@+2, ss
|
|||
|
ENDIF
|
|||
|
SetArgvX label near
|
|||
|
jcxz SetLastArg
|
|||
|
mov [bp], si ; Set argv[n]
|
|||
|
IF LDATA
|
|||
|
mov [bp+2], ss
|
|||
|
ENDIF
|
|||
|
add bp, dPtrSize
|
|||
|
CopyArg label near
|
|||
|
lods byte ptr ss:[si]
|
|||
|
or al, al
|
|||
|
loopnz CopyArg
|
|||
|
jz SetArgvX
|
|||
|
SetLastArg label near
|
|||
|
xor ax, ax
|
|||
|
mov [bp], ax
|
|||
|
IF LDATA
|
|||
|
mov [bp+2], ax
|
|||
|
ENDIF
|
|||
|
|
|||
|
;==============================================================================
|
|||
|
endif ; ifdef WILD
|
|||
|
;==============================================================================
|
|||
|
|
|||
|
; Restore caller context and exit
|
|||
|
|
|||
|
IF LPROG
|
|||
|
jmp dword ptr SavedReturn
|
|||
|
ELSE
|
|||
|
jmp word ptr SavedReturn
|
|||
|
ENDIF
|
|||
|
|
|||
|
ifdef WILD
|
|||
|
EndProc@ _wildargv, __CDECL__
|
|||
|
else
|
|||
|
EndProc@ _setargv, __CDECL__
|
|||
|
endif
|
|||
|
|
|||
|
CSegEnd@
|
|||
|
END
|
|||
|
|