home *** CD-ROM | disk | FTP | other *** search
- page ,132
- title stdargv - standard & wildcard _setargv routine
- ;***
- ;stdargv.asm - standard & wildcard _setargv routine
- ;
- ; Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
- ;
- ;Purpose:
- ; processes program command line, with or without wildcard expansion
- ;
- ;*******************************************************************************
-
-
- ifdef WILDCARD
- name _setargv ; wildcard _setargv routine
- else
- name stdargv ; standard _setargv routine
- endif
-
- ifdef WILDCARD
- ?DF = 1 ; tell cmacros.inc we want to define our own segments
- endif
-
- .xlist
- include version.inc
- include cmacros.inc
- include msdos.inc
- include defsegs.inc
- include rterr.inc
- .list
-
- ifdef _WINDOWS
-
- _MAX_PATH equ 260 ; max path (should match stdlib.h)
-
- extrn pascal GETMODULEFILENAME:far ; get argv[0]
- extrn __myalloc:near ; allocation routine for arguments
-
- endif
-
- ifdef FARSTACK
- ife sizeD
- error <You cannot have a far stack in Small or Medium memory models.>
- endif
- endif
-
- ifdef WILDCARD ; **********************************************
-
- CrtDefSegs <code, data>
- CrtDefSegs <nmsg>
-
- codeOFFSET equ <offset _TEXT:>
- dataOFFSET equ <offset DGROUP:>
-
- ; Message used by ___setargv (wildcard version of __setargv)
-
- sBegin nmsg
- assumes ds,data
-
- _RTERR _RT_SPACEARG, _RT_SPACEARG_TXT, _RT_STANDARD ; 'not enough space for arguments'
-
- sEnd
-
- sBegin npad
- assumes ds,data
- dw -1
- ; no padding for now;
- ; MAX padding would be
- ; db 25 dup(0)
- sEnd
-
- externP _cwild ; Wildcard Expander
- externNP _amsg_exit ; error handler (unable to allocate)
-
- endif ; WILDCARD ; **********************************************
-
-
- sBegin data
- assumes ds,data
-
- C_CR equ 0DH ; ASCII carriage return
-
- 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 _psp ; address of Program Segment Prefix
- externD _pgmptr ; far ptr to name of program
-
- ifdef _BAT16
- externD __cmdLine ; cmdLine ptr
- endif
-
-
- ifdef _WINDOWS
- ifdef _WINDLL
- externW _hModule ; identifies module
- else
- externW _hInstance ; identifies instance of module
- endif
- else ;!_WINDOWS
- externW _osversion ; address of OS version
- endif
-
-
- staticCP retadr,0 ; return address
-
-
- ifdef WILDCARD ; **********************************************
-
- dta_flag db 0 ; Has DMA been set yet?
-
- file_reserv db 21 dup (0)
- file_attrib db 0
- file_time dw 0
- file_date dw 0
- file_sizel dw 0
- file_sizeh dw 0
- file_name db 13 dup (0)
-
- endif ; WILDCARD ; **********************************************
-
-
- sEnd
-
- ; ****************************************
-
- jmps MACRO target
- jmp short target
- ENDM
-
- lje MACRO target
- LOCAL temp
- jne temp
- jmp target
- temp:
- ENDM
-
-
- DELIM MACRO target
- cmp al,C_CR ;; Test for end-of-line character
- je target
- or al,al ;; Either Carriage Return or Null
- je target
- ENDM
-
- LDELIM MACRO target
- cmp al,C_CR ;; Test for end-of-line character
- lje target
- or al,al ;; Either Carriage Return or Null
- lje target
- ENDM
-
- ; ****************************************
-
- sBegin code
-
- assumes ds,data
- ifdef FARSTACK
- assumes ss,nothing
- else
- assumes ss,data
- endif
- assumes cs,code
-
- ifdef _WINDOWS
- if sizeD
- externP _GetDGROUP
- endif
- endif
-
- page
- ;***
- ;_setargv, __setargv - set up "argc" and "argv" for C programs
- ;
- ;Purpose:
- ; Gets the command line from the PSP and moves the information
- ; to its place on the stack.
- ;
- ; SIDE EFFECTS:
- ; Allocates space on the stack for the argument strings
- ; and a list of pointers to them.
- ; ASSUMPTIONS:
- ; Under DOS 2, there is no argv[0] string, so we store a null
- ; char ('\0').
- ;
- ; Under DOS 3 and later, the argv[0] string is found in the
- ; environment segment, after the double null that terminates
- ; that segment and after a word of value 1. The rest of the
- ; command line is found in the Program Segment Prefix at
- ; offset 81H, and is terminated by a 0DH. This command "tail"
- ; cannot be greater than 126 bytes in length.
- ;
- ; Quote marks and backslashes are treated specially. A quoted
- ; string is passed as a single argument, not including the
- ; opening and closing quote characters. A quote may be imbedded
- ; in a string by placing an odd number of backslashes (`\')
- ; before it. Each pair of backslashes which precedes a quote
- ; results in a single backslash in the resultant string.
- ; An even number of backslashes followed by a quote results in
- ; half that many backslashes, and the quote begins or ends the
- ; quoted part of the string as is appropriate. Backslashes not
- ; followed by a quote are treated normally.
- ;
- ; [""] ==> []
- ; [\"] ==> ["]
- ; [" \" "] == [ " ]
- ; [" \\"] == [ \]
- ; [" \\ "] == [ \\ ]
- ; [" \\\" "] == [ \" ]
- ; etc.
- ; ["one two three"] ==> [one two three]
- ; [one" two "three] ==> [one two three]
- ; [o"ne two t"hree] ==> [one two three]
- ; ["one \"two\" three"] ==> [one "two" three]
- ; ["x\\\"x"] ==> [x\"x]
- ;
- ;Entry:
- ;
- ;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 Program Segment Prefix into space allocated on the stack.
- ; The list of pointers is also located on the stack.
- ;
- ;Uses:
- ; All registers except DS, SS, and BP are modified
- ; Note especially that SI and DI are NOT preserved!
- ;
- ;Exceptions:
- ;
- ;*******************************************************************************
-
- ifdef WILDCARD ; **********************************************
-
- labelP <PUBLIC,__setargv>
-
- else ; **********************************************
-
- labelP <PUBLIC,_setargv>
-
- endif ; WILDCARD ; **********************************************
-
- pop word ptr [retadr] ; get return address (offset)
- if sizeC
- pop word ptr [retadr+2] ; get return address (segment)
- endif
-
- ifdef _WINDOWS
- ifndef _BAT16
-
- ;
- ; In windows, get argv[0] from the system, not from the DOS segment
- ;
- mov ax,_MAX_PATH ; maximum length of path
- mov cx,_RT_SPACEARG ; Out of heap space
- call __myalloc ; get argv[0] memory
- ; *** DIES ON ERROR ***
- ifdef WILDCARD
- inc ax ; room for wildcard flag
- endif
- mov word ptr [_pgmptr+2],dx ; set global variable "_pgmptr"
- mov word ptr [_pgmptr],ax
-
- push dx ; save ptr across call
- push ax
-
- ifdef _WINDLL
- push _hModule ; module instance
- else
- push _hInstance ; module instance
- endif
- push dx ; address of name buffer
- push ax
- mov ax,_MAX_PATH ; size of buffer
- push ax
- call GETMODULEFILENAME ; ax = length of actual string
- ; no error return defined
-
- pop bx
- pop es ; es:bx = pointer to string
- add bx,ax ; es:bx = end of string
- mov byte ptr es:[bx],0 ; store a final null byte
-
- mov dx,1 ; dx = number of bytes in argv[0]
-
- endif ;!_BAT16
- else ;!_WINDOWS
- ;
- ; Check DOS version.
- ;
- mov ax,[_osversion] ; ax = OS version number
- mov dx,1 ; dx = number of bytes in argv[0] if DOS 2.x
- cmp al,2
- je dos_two
-
- mov es,_psp
- mov es,es:[DOS_envp] ; get environment segment
- mov word ptr [_pgmptr+2],es ; set global variable "_pgmptr"
- xor ax,ax
- cwd ; DX=0
- mov cx,8000H
- xor di,di ; scan from beginning of environment
- find_env_end:
- repne scasb
- scasb
- jne find_env_end
- ;
- inc di ; skip count word (always 0x0001)
- inc di
- mov word ptr [_pgmptr],di ; set global variable "_pgmptr"
- mov cx,-1
- repne scasb
- not cx
- mov dx,cx ; DX=number of bytes in argv[0]
-
- endif ;_WINDOWS
-
- dos_two:
- ifdef FARSTACK
- push ds
- pop es
- assumes es,data ; set ES=DGROUP
- endif
- ifndef _BAT16
- mov di,1 ; always start with one argument
- mov si,81H
- mov ds,_psp
-
- else ; _BAT16
- xor dx,dx ;no byte yet
- xor di,di ;always start with no arguments
- lds si,ss:[__cmdLine] ;* Point to beg of command line
- endif ; _BAT16
-
- assumes ds,nothing
- ;*
- ;* 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 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 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 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 )
- ;
- ifdef FARSTACK
- push es
- else
- push ss
- endif ;FARSTACK
- 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
- add dx,di ; add space for pointers to space for chars
-
- inc dx
- and dl,not 1 ; Round up to an even number of bytes
- ;
- ; Allocate space on the stack
- ;
- ; DX is the total number of bytes needed for strings and pointers
- ; DI is the number of bytes needed for the pointers
- ;
- sub sp,dx
- mov ax,sp
-
- mov word ptr (__argv),ax
- if sizeD
- mov word ptr (__argv+2),ss
- endif
- ;
- ; Copy argument strings and addresses onto heap/stack
- ; Address table is on the top, strings below that
- ;
- mov bx,ax
- add di,bx
-
- push ss ; ES=SS
- pop es ; ES:DI is where the string copies will go
- ifndef FARSTACK
- assumes es,data
- endif
-
- ifndef _BAT16
- ;
- ; 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:
- ; ES:DX points to the wildcard flag character (prepended to argument)
- ; during the creation of each argument
- ;
-
- ifdef _WINDOWS
-
- ; move the pointer, no need to move the string
- lds si,[_pgmptr] ; copy argv[0], either fake or from env seg
- assumes ds,nothing
-
- ifdef WILDCARD
- dec si ; room for wildcard flag
- endif
- mov ss:[bx],si ; argv[0] - offset part
- if sizeD
- mov ss:[bx+2],ds ; argv[0] - segment part
- add bx,4
- else
- inc bx
- inc bx
- endif
-
- else ;!_WINDOWS
-
- mov ss:[bx],di ; argv[i] - offset part
- if sizeD
- mov ss:[bx+2],ss ; argv[i] - segment part
- add bx,4
- else
- inc bx
- inc bx
- endif
-
- lds si,[_pgmptr] ; copy argv[0], either fake or from env seg
- 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
-
- endif ;_WINDOWS
-
-
- ;
- ; DS:SI points to the raw command tail string
- ;
-
- ifdef FARSTACK
-
- ifdef _WINDOWS
- push ax
- callcrt _GetDGROUP
- mov ds, ax ; DS = DGROUP
- pop ax
- else ;not _WINDOWS
- mov si, DGROUP
- mov ds, si ; DS = DGROUP
- endif ;not _WINDOWS
-
- assumes ds, data
- mov ds, [_psp]
- assumes ds, nothing ; let DS = psp
- else
- mov ds,ss:[_psp] ; DS:SI is where the source strings are
- endif ;FARSTACK
- mov si,81H ; address of strings
-
- else ; _BAT16
- lds si,ss:[__cmdLine] ;* Point to the comand line again
- endif ; _BAT16
-
- assumes ds,nothing
-
- jmps arg510
- ;
- ; Skip blanks
- ;
- arg500:
- xor ax,ax
- stosb
- arg510:
- lodsb
- cmp al,C_BLANK
- je arg510
- cmp al,C_TAB
- je arg510
-
- ifdef WILDCARD
- LDELIM arg810
- else
- if sizeD
- LDELIM arg810
- else
- DELIM arg810
- endif
- endif
-
- mov ss:[bx],di
- if sizeD
- mov ss:[bx+2],ss
- 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 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 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:
-
- ifdef FARSTACK
- ifdef _WINDOWS
- callcrt _GetDGROUP
- mov ds, ax
- else
- mov ax, DGROUP
- mov ds, ax
- endif
- else
- push ss ; default is SS == DGROUP
- pop ds
- endif
- assumes ds,data
-
- ifdef FARSTACK
- mov word ptr ss:[bx],0
- mov word ptr ss:[bx+2],0
- else
- mov word ptr [bx],0 ; add null pointer to __argv[]
- if sizeD
- mov word ptr [bx+2],0
- endif
- endif ;FARSTACK
-
- ifndef WILDCARD
- jmp [retadr] ; THE END
- else
- call _cwild
- test ax,ax
- jz no_arg_err
-
- mov ax,_RT_SPACEARG ; 'not enough space for arguments'
- jmp _amsg_exit ;
-
- no_arg_err:
- jmp [retadr]
-
- page
- ;***
- ;_find(dir) - find first matching file name against pattern "dir"
- ;
- ;Purpose:
- ; _find(dir) - Find first matching file name against pattern "dir"
- ; If dir == NULL, then get next match for current pattern.
- ;
- ;Entry:
- ; dir = DATA PTR of pattern to match
- ;
- ;Exit:
- ; AX = the address of a static area containing the file name if a
- ; match was found. Returns NULL if no match was found.
- ;
- ;Uses:
- ; CX,DX, [dta_flag].
- ;
- ;Exceptions:
- ;
- ;*******************************************************************************
-
- cProc _find,<PUBLIC>
- parmdp dir
- cBegin
- test [dta_flag],-1
- jnz not_very_first
-
- mov [dta_flag],-1
- ;
- ; Set DTA, where the match structure is returned
- ;
- mov dx,dataOFFSET file_reserv
- callos setdma
- ;
- not_very_first:
- mov ah,DOS_findnext ; assume not first
-
- if sizeD
- push ds
- lds dx,dir
- mov cx,ds
- jcxz find_next
- else
- mov dx,dir
- test dx,dx
- jz find_next
- endif
- mov cx,A_D ; match directories as well as files
- mov ah,DOS_findfirst
- find_next:
- callos
- if sizeD
- pop ds
- endif
- mov ax,dataOFFSET file_name
- if sizeD
- mov dx,ds
- endif
- jnc retname
-
- xor ax,ax ; return 0 for no more matches
- if sizeD
- cwd
- endif
-
- retname:
-
- cEnd
-
- endif ; WILDCARD ; ***********************************************
-
- sEnd code
-
- end
-