home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgLangD.iso
/
Fortran.51
/
DISK5
/
OS2
/
STDARGV.AS$
/
STDARGV.bin
Wrap
Text File
|
1989-08-31
|
15KB
|
770 lines
page ,132
title stdargv.asm - OS/2 standard & wildcard _setargv routine
;***
;stdargv.asm - OS/2 standard & wildcard _setargv routine
;
; Copyright (c) 1985-1990, Microsoft Corporation. All rights reserved.
;
;Purpose:
; processes program command line, with or without wildcard expansion
;
;*******************************************************************************
; _SSNEDS flag set means SS not necessarily equal to DS; this requires
; special processing to preserve the value of DS in places
ifdef FARSTACK
_SSNEDS equ 1
else
_SSNEDS equ 0
endif
ifdef WILDCARD
name _setargv ; wildcard _setargv routine
else
name stdargv ; standard _setargv routine
endif
.xlist
include version.inc
include cmacros.inc
include msdos.inc
include rterr.inc
.list
ifdef FARSTACK
ife sizeD
error <You cannot have a far stack in Small or Medium memory models.>
endif
endif
sBegin data
assumes ds,data
C_BLANK equ ' ' ; ASCII space character
C_TAB equ 09h ; ASCII horizontal tab character
C_QUOTE equ '"' ; ASCII (double) Quote Charater
C_BACKSLASH equ '\' ; ASCII backward slash character
externDP __argv ; argument string array address
externW __argc ; count of argument strings
externW _aenvseg ; environment segment
externW _acmdln ; offset of command line in env. seg.
externD _pgmptr ; far pointer to program name
staticW cmdstart,0 ; start of command line string
ife _SSNEDS
staticCP retadr,0 ; return address
endif
ifdef WILDCARD
staticW findhandle,1 ; handle used for wildcard matching
FileFindBuf struc
create_date dw ? ;* date of file creation
create_time dw ? ;* time of file creation
access_date dw ? ;* date of last access
access_time dw ? ;* time of last access
write_date dw ? ;* date of last write
write_time dw ? ;* time of last write
file_size dd ? ;* file size (end of data)
falloc_size dd ? ;* file allocated size
attributes dw ? ;* attributes of the file
string_len db ? ;* returned length of ascii name str.
file_name db 257 dup (?) ;* name string
FileFindBuf ends
findbuf FileFindBuf <> ;* struct FileFindBuf findbuf;
endif ; WILDCARD
sEnd data
;=========================================
ifdef WILDCARD
extrn DOSFINDFIRST:far
extrn DOSFINDNEXT:far
externP _cwild ; Wildcard Expander
endif
;=========================================
jmps MACRO target
jmp short target
ENDM
lje MACRO target
LOCAL temp
jne temp
jmp target
temp:
ENDM
DELIM MACRO
or al,al ;; Test for end-of-line character (null)
ENDM
;=========================================
sBegin code
externNP _stdalloc ; routine to allocate heap memory
externNP _amsg_exit ; error handler (unable to allocate)
assumes ds,data
if _SSNEDS
assumes ss,nothing
else
assumes ss,data
endif ;_SSNEDS
assumes cs,code
page
;***
;_setargv, __setargv - set up "argc" and "argv" for C programs
;
;Purpose:
; Read the command line and create the argv array for C
; programs.
;
;Entry:
; Arguments are retrieved from the program command line.
;
;Exit:
; "argv" points to a null-terminated list of pointers to ASCIZ
; strings, each of which is an argument from the command line.
; "argc" is the number of arguments. The strings are copied from
; the environment segment into space allocated on the heap/stack.
; The list of pointers is also located on the heap or stack.
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
ifdef WILDCARD ; **********************************************
labelP <PUBLIC,__setargv>
else ; **********************************************
labelP <PUBLIC,_setargv>
endif ; WILDCARD ; **********************************************
ife _SSNEDS
pop word ptr [retadr] ; get return address (offset)
if sizeC
pop word ptr [retadr+2] ; get return address (segment)
endif
endif ;_SSNEDS
mov ax,_acmdln
if _SSNEDS
push ds
pop es
assumes es,data
endif ;_SSNEDS
mov ds,_aenvseg
assumes ds,nothing
mov si,ax
;
; If there is no argument string, use the
; program name for the command line string.
; Scan back for the null before "PgmPtr"
;
find_argv0:
dec si
jz found_argv0
cmp byte ptr ds:[si-1],0
jne find_argv0
found_argv0:
mov word ptr [_pgmptr],si
mov word ptr [_pgmptr+2],ds
xchg ax,si ; restore SI to [_acmdln]
test byte ptr ds:[si],-1
jnz store_cmdstart
xchg ax,si ; use PgmPtr instead of ArgPtr
store_cmdstart:
mov [cmdstart],si
xor dx,dx ; Start with zero bytes
mov di,1 ; Start with one arguments
count_argv0:
lodsb
inc dx ; count each byte in argv[0]
or al,al ; including the terminator
jnz count_argv0
;*
;* Count the command line arguments
;*
;* ... previous environment strings ...
;* null byte (end of last environment string)
;* null byte (end of environment)
;* program name string
;* null byte
;* DS:SI ==> raw command line string
;* null byte
;* null byte
;*
;* DI will count the number of arguments
;*
;* DX will count the number of bytes needed to
;* store the arguments themselves, incl. final nulls
;*
;*
;* Count the command tail arguments
;*
;
; DI will count the number of arguments
; DX will count the number of bytes needed for the arguments
; (not including the null terminators)
;
arg100:
arg110:
lodsb
cmp al,C_BLANK
je arg110
cmp al,C_TAB
je arg110
DELIM
je arg400
inc di ; Another argument
;
; Parse an argument
;
arg200:
dec si ; back up to reload character
arg210:
lodsb
cmp al,C_BLANK
je arg100
cmp al,C_TAB
je arg100 ; white space terminates argument
DELIM
je arg400
cmp al,C_QUOTE
je arg310
cmp al,C_BACKSLASH
je arg220
inc dx
jmps arg210
;
; Count backslashes
;
arg220:
xor cx,cx
arg221:
inc cx ; CX counts the backslashes
lodsb
cmp al,C_BACKSLASH
je arg221
;
cmp al,C_QUOTE
je arg230
add dx,cx ; not followed by `"' -- treat `\'s normally
jmp arg200
;
arg230:
mov ax,cx
shr cx,1
adc dx,cx ; add 1 for every pair of backslashes
test al,1 ; plus 1 for the " if odd number of \
jnz arg210 ; " was escaped with a \
jmps arg310 ; " opens a quoted substring
;
; Enter a quoted string
;
arg300:
dec si ; back up to reload character
arg310:
lodsb
DELIM
je arg400
cmp al,C_QUOTE
je arg210 ; end of quoted portion of string
cmp al,C_BACKSLASH
je arg320
inc dx
jmp arg310
;
; Count backslashes
;
arg320:
xor cx,cx
arg321:
inc cx ; CX counts the backslashes
lodsb
cmp al,C_BACKSLASH
je arg321
;
cmp al,C_QUOTE
je arg330
add dx,cx ; not followed by `"' -- treat `\'s normally
jmp arg300
;
arg330:
mov ax,cx
shr cx,1
adc dx,cx ; add 1 for every pair of backslashes
test al,1 ; plus 1 for the " if odd number of \
jnz arg310 ; " was escaped with a \
jmps arg210 ; " closes a quoted substring
;
; Command line is fully parsed - compute number of bytes needed
;
arg400:
;
; Number of bytes needed =
; Number of bytes used to make strings +
; Number of bytes used to terminate strings +
; sizeof(DATAPTR) * ( number of arguments + 1 )
;
if _SSNEDS
push es
else
push ss
endif ;_SSNEDS
pop ds ; Restore DS = DGROUP
assumes ds,data
mov __argc,di ; Store number of arguments
add dx,di ; add in terminator bytes
ifdef WILDCARD
add dx,di ; add in Wildcard flag bytes
endif
inc di ; add one for NULL pointer
shl di,1
if sizeD
shl di,1
endif
mov ax,di
add ax,dx ; add space for pointers to space for chars
inc ax
and al,not 1 ; Round up to an even number of bytes
;
; Allocate space on the heap (or the stack in non-DLL)
;
; AX is the total number of bytes needed for strings and pointers
; DI is the number of bytes needed for the pointers
;
call _stdalloc ; dx:ax = allocated memory
jnc args_ok
arg_error:
mov ax,_RT_SPACEARG ; Out of heap space
jmp _amsg_exit
args_ok:
mov word ptr (__argv),ax ; offset
if sizeD
mov word ptr (__argv+2),dx ; segment
endif
;
; Copy argument strings and addresses onto heap/stack
; Address table is on the top, strings below that
;
if _SSNEDS
push ds ; save two copies of DGROUP for later
push ds
endif ;_SSNEDS
mov bx,ax
add di,ax
mov es,dx ; ES:DI is where the string copies will go
assumes es,data
;
; DS:SI points to the argv[0]
;
; ES:BX points to where argv[0],argv[1],argv[2],... go
; ES:DI points to where *argv[0],*argv[1],*argv[2],... go
; For wildcard version only (DX initialized below):
; ES:DX points to the wildcard flag character (prepended to argument)
; during the creation of each argument
;
mov es:[bx],di ; argv[i] - offset part
if sizeD
mov es:[bx+2],es ; argv[i] - segment part
add bx,4
else
inc bx
inc bx
endif
mov si,cmdstart ; Get pointer to argv[0]
mov ds,_aenvseg
assumes ds,nothing
ifdef WILDCARD
movsb
dec si ; copy first character as quote flag
endif
copy_argv0:
lodsb
stosb
or al,al
jnz copy_argv0
;
; DS:SI points to the raw command tail string
;
jmps arg510
;
; Skip blanks
;
arg500:
xor ax,ax
stosb
arg510:
lodsb
cmp al,C_BLANK
je arg510
cmp al,C_TAB
je arg510
DELIM
ifdef WILDCARD
if sizeD
lje arg810
else
je arg810
endif
else
je arg810
endif
mov es:[bx],di
if sizeD
mov es:[bx+2],es
add bx,4
else
inc bx
inc bx
endif
ifdef WILDCARD
mov dx,di
stosb ; initialize wildcard flag
endif
;
;
; Parse an argument
;
arg600:
dec si ; back up to reload character
arg610:
lodsb
cmp al,C_BLANK
je arg500
cmp al,C_TAB
je arg500 ; white space terminates argument
DELIM
je arg800
cmp al,C_QUOTE
je arg710x
cmp al,C_BACKSLASH
je arg620
stosb
jmps arg610
;
; Count backslashes
;
arg620:
xor cx,cx
arg621:
inc cx ; CX counts the backslashes
lodsb
cmp al,C_BACKSLASH
je arg621
;
cmp al,C_QUOTE
je arg630
mov al,C_BACKSLASH
rep stosb ; not followed by `"' -- treat `\'s normally
jmp arg600
;
arg630:
mov al,C_BACKSLASH
shr cx,1
rep stosb
jnc arg710x ; " opens a quoted substring
mov al,C_QUOTE
stosb
jmp arg610 ; " was escaped with a \
;
; Enter a quoted string
;
ifdef WILDCARD
arg710x:
inc si ; undoes the "DEC SI" between arg700 and arg710
endif
arg700x:
ifdef WILDCARD
xchg dx,di ; set the wildcard flag character to `"'
mov al,C_QUOTE
stosb
dec di
xchg dx,di
endif
arg700:
dec si ; back up to reload character
ifndef WILDCARD
arg710x:
endif
arg710:
lodsb
DELIM
je arg800
cmp al,C_QUOTE
je arg610 ; end of quoted portion of string
cmp al,C_BACKSLASH
je arg720
stosb
jmp arg710
;
; Count backslashes
;
arg720:
xor cx,cx
arg721:
inc cx ; CX counts the backslashes
lodsb
cmp al,C_BACKSLASH
je arg721
;
cmp al,C_QUOTE
je arg730
mov al,C_BACKSLASH
rep stosb ; not followed by `"' -- treat `\'s normally
jmp arg700x
;
arg730:
mov al,C_BACKSLASH
shr cx,1
rep stosb ; store 1 for every pair of backslashes
jnc arg610 ; " closes a quoted substring
mov al,C_QUOTE ; " was escaped with a \
stosb
jmps arg710x
;
; Terminate last argument string, terminate list of argument pointers
;
arg800:
xor ax,ax
stosb ; null-terminate final argument
arg810:
mov word ptr es:[bx],0 ; add null pointer to __argv[]
if sizeD
mov word ptr es:[bx+2],0
endif
if _SSNEDS
pop es ; ES = DS = DGROUP
pop ds
else
push ss
pop ds ; restore ds
endif ;_SSNEDS
assumes ds,data
ifndef WILDCARD
if _SSNEDS
if sizeC
retf ; THE END
else
retn ; THE END
endif
else ;_SSNEDS
jmp [retadr] ; THE END
endif ;_SSNEDS
else ; WILDCARD
call _cwild
test ax,ax
jnz to_arg_error
if _SSNEDS
if sizeC
retf ; THE END
else
retn ; THE END
endif
else ; _SSNEDS
jmp [retadr] ; THE END
endif ;_SSNEDS
to_arg_error:
jmp arg_error
page
;***
;_find(pattern) - find matching filename
;
;Purpose:
; if argument is non-null, do a DosFindFirst on that pattern
; otherwise do a DosFindNext call. Return matching filename
; or NULL if no more matches.
;
; char *_find(pattern)
; char *pattern;
; {
; static struct FileFindBuf findbuf;
; static unsigned findhandle=1;
; unsigned findcount=1;
; int rc;
;
; if(pattern)
; rc = DOSFINDFIRST((char far *) pattern,
; (unsigned far *) &findhandle, A_D,
; (struct FileFindBuf far *) &findbuf, sizeof(findbuf),
; (unsigned far *) &findcount, 0L);
; else
; rc = DOSFINDNEXT(findhandle,
; (struct FileFindBuf far *) &findbuf, sizeof(findbuf),
; (unsigned far *) &findcount);
;
; return(rc ? NULL : findbuf.file_name);
; }
;
;Entry:
; pattern = pointer to pattern or NULL
; (NULL means find next matching filename)
;
;Exit:
; AX (or DX:AX) = pointer to matching file name
; or NULL if no more matches.
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
cProc _find,<PUBLIC>,<>
parmDP pattern
; localW findcount
findcount equ (word ptr [bp-2])
cBegin
mov ax,1
push ax ; mov [findcount],1
mov bx,dataOFFSET findbuf
mov dx,size findbuf
lea ax,findcount
;
; DS:BX = &findbuf
; DX = sizeof(findbuf)
; SS:AX = &findcount
; CX = FP_OFF(pattern)
;
if sizeD
les cx,pattern
cmp word ptr [pattern+2],0
jz find_next
else
mov cx,pattern
jcxz find_next
endif
;
; Make first call to DOSFINDFIRST
;
if sizeD
push es
else
push ds
endif
push cx ; (char far *) pattern
mov cx,dataOFFSET findhandle
mov [findhandle],1 ; always use handle 1
push ds
push cx ; (unsigned far *) & findhandle
mov cx,A_D
push cx ; match attribute: normal files + directories
push ds
push bx ; (struct FileFindBuf far *) &findbuf
push dx ; sizeof(findbuf)
push ss
push ax ; (unsigned far *) &findcount
xor ax,ax
push ax
push ax ; 0L (reserved)
call DOSFINDFIRST
jmp short check_rc
;
; get next match
;
find_next:
push [findhandle] ; findhandle
push ds
push bx ; (struct FileFindBuf far *) &findbuf
push dx ; sizeof(findbuf)
push ss
push ax
call DOSFINDNEXT
;
check_rc:
add bx,dataOFFSET file_name ; BX = findbuf.file_name
if sizeD
mov dx,ds
endif
test ax,ax ; check for error in system call
xchg ax,bx ; return findbuf.file_name if successful
jz rc_zero
;
xor ax,ax ; return NULL for error
if sizeD
cwd
endif
rc_zero:
cEnd
endif ; WILDCARD
sEnd code
end