dos_compilers/Microsoft C v4/SETARGV.ASM
2024-07-01 10:35:17 -07:00

280 lines
5.1 KiB
NASM

title stdargv - standard _setargv routine
;--------------------------------------------------------------------------
;
; Microsoft C Compiler Runtime for MS-DOS
;
; (C)Copyright Microsoft Corporation, 1984,1985,1986
;
;--------------------------------------------------------------------------
include version.inc
.xlist
include cmacros.inc
include msdos.inc
.list
TAB = 9 ; tab character
sBegin data
assumes ds,data
externW _psp ; psp segment #
externDP __argv ; argv address
externW __argc ; argc
externB _osmajor ; os major version #
staticCP retadr,0 ; return address
sEnd data
sBegin code
assumes ds,data
assumes cs,code
labelP <PUBLIC,_setargv>
pop word ptr [retadr] ; get return address
if sizeC
pop word ptr [retadr+2] ; seg part of return address
endif
mov ds,[_psp] ; get psp segment
push ss ; ss = ds assumption
pop es
assumes ds,nothing
assumes es,data
; move command line at (psp:80) to stack
mov si,DOS_CMDLINE ; point to command line
lodsb ; get length
cbw ; and convert to word
;xor dx,dx ; argv[0] valid? initially no
cmp __osmajor,3
jb tooold ; if < dos 3.0
push ax ; save length
mov es,ds:[DOS_ENVP] ; envp seg addr
assumes es,nothing
xor ax,ax ; 0
mov cx,ax
not cx ; -1
mov di,ax ; 0
again:
repne scasb ; find null
cmp es:[di],al ; env null?
jne again ; no
add di,3 ; to get to argv[0]
mov cx,ax
not cx ; -1
push di ; start of argv[0]
repne scasb ; search for argv[0] null & get length
pop si ; start of argv[0]
add cx,2 ; cx=-len(argv[0])
neg cx ; cx=+len(argv[0])
;inc dx ; valid argv[0]
pop bx ; len(argv[1]+...+argv[n])
mov ax,bx
add ax,cx ; +len(argv[0])
add ax,3 ; space, null, rounding
and ax,not 1 ; rounded even
sub sp,ax ; allocate space on stack
mov di,sp ; di=destination
push ds ; save psp
push es
pop ds ; ds=env seg
push ss
pop es ; es=stack seg
assumes es,data
rep movsb ; move argv[0]
mov al,' ' ; space following argv[0]
stosb
mov cx,bx ; len(argv[1]+...+argv[n])
pop ds ; psp seg
mov si,DOS_CMDLINE+1 ; restore si for command line move
jmp short moveit
tooold:
mov cx,ax ; save length
add al,4 ; pad for 'C ', term and rounding
and al,not 1 ; round even
sub sp,ax ; allocate space on stack
mov di,sp ; di = destination
mov ax,'C' + ' ' shl 8
stosw ; stuff 'C '
moveit:
rep movsb ; move command line
mov ax,cx ; ax=0
stosb ; stuff terminating 00
mov si,sp ; save command line ptr
push ss
pop ds
assumes ds,data
; crack command line arguments onto stack
push ax ; terminating NULL
if sizeD
push ax ; seg part for long model
endif
mov bx,sp ; remember top of argv (reversed)
nextarg:
mov di,si ; resync argument
lodsb ; get next char
or al,al ; check for end of line
je endline ; yes
call iswhite ; is it white space
jz nextarg ; yes - keep skipping
dec si ; point to 1st character
if sizeD
push ds
endif
push si ; argv entry is ds:si
inc [__argc] ; bump arg count
notspace:
lodsb ; get next char
call isquote
stosb
or al,al ; check for end of line
je endline ; yes
call iswhite ; is it white space
jnz notspace ; no - keep skipping
mov byte ptr [di-1],0 ; zero terminate arg
jmp short nextarg
endstoreb:
stosb ; save null terminator
endline:
mov si,sp ; si = last arg (reversed)
revloop:
if sizeD
sub bx,4
else
dec bx
dec bx
endif
cmp si,bx ; half way up or more
jae revdone ; yes - return
lodsw
xchg [bx],ax
mov [si-2],ax ; swap offsets
if sizeD
lodsw
xchg [bx+2],ax
mov [si-2],ax ; swap segments
endif
jmp short revloop ; keep looping
revdone:
mov bx,sp
;or dx,dx ; argv[0] valid?
;jnz keepit ; yes
; no, skip it
;inc word ptr [bx] ; argv[0] = null - skip past 'C'
keepit:
if sizeD
mov word ptr [__argv+2],ss
endif
mov word ptr [__argv],sp ; save argv pointer
jmp [retadr] ; return
iswhite:
cmp al,TAB ; is it a TAB
je iswret ; yes - exit
cmp al,' ' ; is it a space
iswret:
ret ; return
isquote:
cmp al, '\' ; is this a backslash
jne normquote
cmp byte ptr ds:[si],'"' ; check for \" must do this this way to avoid
jne normquote ; a first char quote with the byte before it
lodsb ; just happening to be a backslash.
jmp short isqret
normquote:
cmp al, '"' ; is it a quote
jne isqret
ifdef NOEATQUOTE
stosb
endif
notquote:
lodsb ; get next char
cmp al,13 ; check for eol
je isqret ; yes - early termination
cmp al,'"' ; ending quote
jne storeb ; no - keep scanning
cmp byte ptr ds:[si-2],'\' ; check for \"
jne endquote ; not \"
ifndef NOEATQUOTE
dec di
endif
storeb:
stosb ; stuff char
jmp short notquote
endquote:
ifdef NOEATQUOTE
stosb
endif
lodsb
jmp short isquote ; done with quotes
isqret:
ret ; return
sEnd code
end