home *** CD-ROM | disk | FTP | other *** search
- 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