
;----------------------------------------------------------------
; CMDLINE.INC
; JIM TUCKER <jtucker@adam.com.au>
; Last modified: 20 August 1994

; LANGUAGE: A86

; This processes the command line for switches, drives and filenames.
; It uses about 240 bytes. You could do it in less but I have put
; emphasis on readability. To encourage beginners I have commented
; more than usual. - JT

; 1) Just returns if cmdline is empty
; 2) Makes cmdline ASCIIZ caps
; 3) Puts switches in a buffer and blanks them on the cmdline
; 4) Stores drive chars in a list and blanks them on the cmdline
; 5) Keeps filenames on cmdline as ASCIIZ with pointers in a list

; DOS command:     FOOBAR/sw1/sw2 a: file1/sw3 file2   <cr>
; 81h after caps:        /SW1/SW2 A: FILE1/SW2 FILE2   <0>
; 81h after switches:             A: FILE1     FILE2   <0>
; 81h after drives:                  FILE1     FILE2   <0>
; 81h after filenames:               FILE1<0>  FILE2<0><0>
; Switch buffer:         /SW1/SW2/SW3<0>

; USAGE: call cmdline 
;	 lea si,switch_buffer  ; Scan ASCIIZ string for switches
;        mov al,drive1	       ; AL contains drive *char*	 
;        mov dx,filename1      ; DX contains address of string
;        mov dx,filename2... etc

;----------------------------------------------------------------

SWITCH_BUFFER	db 64 dup 0	;will be ASCIIZ string of switches
SWB_SIZE	= ($-OFFSET switch_buffer)-1 ;-1 preserves zero byte

DRIVE1		db	0	;will be drive char in caps
DRIVE2		db	0	;  in order found on cmd line
DRIVE3		db	0
DRIVE4		db	0
MAX_DRIVES	= $-OFFSET drive1

FILENAME1	dw	0	;will point to ASCIIZ *strings*
FILENAME2	dw	0	;  in order found on cmd line.
FILENAME3	dw	0
FILENAME4	dw	0	;you may add more if you need them
MAX_FILES	= ($-OFFSET filename1)/2

;----------------------------------------------------------------
; Procedure begins here. The command line (tail) CS:80h = # chars
; on cmdline including ALL blanks (eg the first n after a filename)
; but not including the terminating return (0Dh). The first char is
; at 81h and may be "/" as in "FOOBAR/SWITCH". Redirection <>| is
; not saved and cannot be read here.

CMDLINE:	test	B[80h]		;anybody home?
		jz	ret		;no (but it will be NZ even
					;if blanks and no data)

; These calls must be performed in the following order

		call	cmd_caps
		call	cmd_switches	
		call	cmd_drives
		call	cmd_files
		ret

;----------------------------------------------------------------

CMD_CAPS:	mov	bx,81h		;zero the cr at end of cmdline
		add	bl,[bx-1]B	;bx -> cr
		mov	B[bx],bh	;bh is zero

		mov	si,81h		;where to get
		mov	di,si		;where to put
L1:		lodsb			;get
		or	al,al		;zero is end of cmdline
		jz	ret		;A86 will find an address
		cmp	al,'a'		;little a?
		jb	>l2		;too small
		cmp	al,'z'		;little z?
		ja	>l2		;too big
		and	al,5Fh		;mask out lower case bit
L2:		stosb			;put
		jmp	l1		;do more

;----------------------------------------------------------------
; Switch "/" and following chars put in our buffer until a space or
; zero byte found. This reads multiple switches such as /aaaa/bb...
; as well as switches separated by a space. NOTE: When you process
; the buffer, a switch is terminated by "/" (another switch) or
; a zero byte (end of buffer).

CMD_SWITCHES:	mov	si,81h		;where get
		lea	di,switch_buffer ;where put
		mov	cl,swb_size	;buffer size

L1:		lodsb			;get
		or	al,al		;end of cmdline?
		jz	ret		;yes, done
		cmp	al,'/'		;switch char?
		jne	l1		;no

L2:		or	cl,cl		;buffer full?
		jz	>l3		;yes
		stosb			;put it in buffer
		dec	cl		;one less buffer byte available
L3:		mov	B[si-1],' '	;blank char on command line
		lodsb			;get next
		cmp	al,' '		;end of it?
		ja	l2		;no, must be a char
		je	l1		;space, keep scanning cmdline
		ret			;must be a zero byte so done

;----------------------------------------------------------------
; Drives are the char before ':' when ':' is followed by space or zero
; "/DRIVE=x:" has been removed by the switch routine. "A:FILENAME" is
; not a drive because a char follows ":" "A:/SWITCH" is a drive because
; "/SWITCH" is now blank (by the switch routine).

CMD_DRIVES:	mov	si,81h		;where get
		lea	di,drive1	;where put
		mov	cl,max_drives	;number allowed

L1:		lodsb			;get
		or	al,al		;end of it?
		jz	ret		;yes
		cmp	al,':'		;possible drive?
		jne	l1		;no
		mov	dl,[si]		;peek next char (don't bump si)
		cmp	dl,' '		;space?
		ja	l1		;bigger, must be a char

		mov	al,[si-2]	;get the drive letter
		mov	W[si-2],2020h	;blank "x:"
		or	cl,cl		;room for more?
		jz	l1		;no, don't save (table full)
		stosb			;save it (bumps di)
		dec	cl		;one less
		jmp	l1

;----------------------------------------------------------------
; Search for filenames inserting the pointer into table and
; terminating each with ASCIIZ. You may change the number of file
; names you expect in the table. Maximum is the entire command line
; allowing one char and a space for each filename!

CMD_FILES:	mov	si,81h		;where get
		lea	bx,filename1	;where put
		mov	cl,max_files	;how many

L1:		mov	B[si-1],0	;done on entry, but no harm
L2:		lodsb			;get
		cmp	al,' '		;space?
		je	l2		;yes, ignore leading spaces
		jb	ret		;below " " so zero byte, exit
		or	cl,cl		;a char, empty table entry left?
		jz	>l3		;no, don't save but do cmdline

		mov	[bx],si		;save pointer
		dec	W[bx]		;  but si pointed one too far
		add	bx,2		;bx -> next filename
		dec	cl		;one less

L3:		lodsb			;now look for end of filename
		cmp	al,' '		;space?
		ja	l3		;char so keep going
		je	l1		;space, insert zero byte
		ret			;must be zero so cmd line done

; END CMDLINE.INC
