	PAGE	90,132			;AN000;A2
	TITLE	DCOPYPAR.SAL - LOOK AT COMMAND LINE PARMS
;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      All Rights Reserved.
; */
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: DCOPYPAR.SAL
;
; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters
;		    and the interface to the DOS system PARSER.
;
;FUNCTION: The static data areas are prescribed by the DOS system PARSER
;	   to define the several parameters presented to DISKCOPY.  These
;	   data areas are passed to the PARSER, and its responses checked
;	   to determine the nature of the user's specifications.  Any errors
;	   found in the user's parameters are defined in messages back
;	   to the user.
;
; ENTRY POINT: PARSER, near
;
; INPUT: (DOS COMMAND LINE PARAMETERS)
;
;	      [d:][path] DISKCOPY  [d: [d:]][/1]
;
;	 WHERE
;	      [d:][path] - Path where the DISKCOPY command resides.
;
;	      [d:] - To specify the Source drive
;
;	      [d:] - To specify the Destination drive
;
;	      [/1] - To copy only the first side of the diskette,
;		     regardless of the diskette or drive type.
;
;	Upon entry to PARSER in this module,
;	"CURRENT_PARM" = offset to start of parm text in command string
;	"ORDINAL" = initialized to zero
;	PSP+81H = text of DOS command line parms string

; EXIT-NORMAL:
;      "SOURCE_DRIVE" = CHAR OF FIRST DRIVE ID SPECIFIED, BLANK IF NONE
;      "TARGET_DRIVE" = CHAR OF SECOND DRIVE ID IF BOTH SPECIFIED, BLANK
;		   IF NONE OR ONLY ONE SPECIFIED
;      "USER_OPTION" = 01 ON IF /1, -1 IF /1 NOT SPECIFIED.

; EXIT-ERROR:
;      IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR".

; INTERNAL REFERENCES:
;    ROUTINES:
;	PARSER:NEAR Call the system Parser to decode command line
;	PARSE_ERROR:NEAR Display the appropriate Parse error message.

;    DATA AREAS:
;	The several parameter control blocks, defined by the System
;	PARSER interface, defining the DISKCOPY parameters.

; EXTERNAL REFERENCES:
;    ROUTINES:
;	SENDMSG:NEAR	Uses Msg Descriptor to drive message handler.
;	SYSPARSE:NEAR	System Command Line Common Parser.
;
;    DATA AREAS:
;	EXITFL:BYTE	Errorlevel return code.
;	MSGNUM_PARSE:WORD Message descriptor for all parse errors.
;	USER_OPTION:BYTE /1 parm indicator
;	SOURCE_DRIVE:BYTE character of first specified drive
;	TARGET_DRIVE:BYTE character of second specified drive
;
; NOTES:
;	 This module should be processed with the SALUT preprocessor
;	 with the re-alignment not requested, as:
;
;		SALUT DCOPYPAR,NUL
;
;	 To assemble these modules, the alphabetical or sequential
;	 ordering of segments may be used.
;
;	 For LINK instructions, refer to the PROLOG of the main module,
;	 DISKCOPY.SAL.
;
;PROGRAM AUTHOR: DOS 4.00 EMK
;****************** END OF SPECIFICATIONS *****************************
	IF1				;AN000;
	    %OUT    COMPONENT=DISKCOPY, MODULE=DCOPYPAR.SAL... ;AN000;
	ENDIF				;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
	INCLUDE PATHMAC.INC		;AN015;PATHGEN MACRO
; =  =	=  =  =  =  =  =  =  =	=  =
HEADER	MACRO	TEXT			;;AN000;
.XLIST					;;AN000;
	SUBTTL	TEXT			;;AN000;
.LIST					;;AN000;
	PAGE				;;AN000;
	ENDM				;;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
;		      $SALUT (4,23,28,36) ;AN000;
;		LOCAL EQUATES

FALSE		      EQU  0	   ;AN000;RETURN VALUES FOR
TRUE		      EQU  NOT FALSE ;AN000; /1 SWITCH
CHAR_A		      EQU  "A"	   ;AN000;ASCII VALUE OF CHARACTER "A"
BLANK		      EQU  " "	   ;AN001;
NUL		      EQU  0	   ;AN003;
; =  =	=  =  =  =  =  =  =  =	=  =
;		EXIT CODES FROM SYSPARSE (WHEN CY=0)

SYSPRM_EX_OK	      EQU  0	   ;AN000; no error
SYSPRM_EX_MANY	      EQU  1	   ;AN000; too many operands
SYSPRM_EX_MISSING     EQU  2	   ;AN000; required operand missing
SYSPRM_EX_NOT_SWLIST  EQU  3	   ;AN000; not in switch list provided
SYSPRM_EX_NOT_KEYLIST EQU  4	   ;AN000; not in keyword list provided
SYSPRM_EX_RANGE       EQU  6	   ;AN000; out of range specified
SYSPRM_EX_VALUE       EQU  7	   ;AN000; not in value list provided
SYSPRM_EX_STRING      EQU  8	   ;AN000; not in string list provided
SYSPRM_EX_SYNTAX      EQU  9	   ;AN000; syntax error
SYSPRM_EX_EOL	      EQU  -1	   ;AN000; end of command line
; =  =	=  =  =  =  =  =  =  =	=  =
		      HEADER <STRUC - DEFINITIONS OF EXTERNAL CONTROL BLOCKS> ;AN000;
PSP		      STRUC	   ;AN000;
		      DB   80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP
PSP_PARMLEN	      DB   ?	   ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE
PSP_COMMAND	      DB   127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE
PSP		      ENDS	   ;AN000;

MSG_DESC	      STRUC	   ;AN003;
MSG_NUM 	      DW   ?	   ;AN003;MESSAGE NUMBER (TO AX)
MSG_HANDLE	      DW   ?	   ;AN003;HANDLE OF OUTPUT DEVICE (TO BX)
MSG_SUBLIST	      DW   ?	   ;AN003;POINTER TO SUBLIST (TO SI)
MSG_COUNT	      DW   ?	   ;AN003;SUBSTITUTION COUNT (TO CX)
MSG_CLASS	      DW   ?	   ;AN003;MESSAGE CLASS (IN HIGH BYTE, TO DH)
				   ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL)
MSG_DESC	      ENDS	   ;AN003;

ONE_SUBS	      EQU  1	   ;AN003;NUMBER OF VARIABLES

SUBLIST 	      STRUC	   ;AN000;
SUB_SIZE	      DB   ?	   ;AN003;SUBLIST SIZE (POINTER TO NEXT SUBLIST)
SUB_RES 	      DB   ?	   ;AN003;RESERVED
				   ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD
SUB_VALUE	      DW   ?	   ;AN003;TIME, DATE, OR PTR TO DATA ITEM
SUB_VALUE_SEG	      DW   ?	   ;AN003;SEG ID OF PTR
				   ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME
				   ; IF THIS IS A .COM FILE)
SUB_ID		      DB   ?	   ;AN003;N OF %N
SUB_FLAGS	      DB   ?	   ;AN003;DATA TYPE FLAGS
SUB_MAX_WIDTH	      DB   ?	   ;AN003;MAXIMUM FIELD WIDTH (0=UNLIMITED)
SUB_MIN_WIDTH	      DB   ?	   ;AN003;MINIMUM FIELD WIDTH
SUB_PAD_CHAR	      DB   ?	   ;AN003;CHARACTER FOR PAD FIELD
				   ; CAN BE " ", "0" OR ",".
				   ; "," CAUSES INSERTION OF THE ACTIVE
				   ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS.
SUBLIST 	      ENDS	   ;AN003;

; =  =	=  =  =  =  =  =  =  =	=  =
		      HEADER <PARSING WORKAREAS> ;AN000;
;	     $SALUT (4,14,19,36)   ;AN000;
	     EXTRN EXPAR:ABS	   ;AN000;ERRORLEVEL VALUE FOR BAD PARMS
	     EXTRN FINE:ABS	   ;AN000;RETURN STATUS INDICATOR
CSEG	     SEGMENT PARA PUBLIC 'CODE' ;AN000;
	     ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000;

	     EXTRN SENDMSG:NEAR    ;AN000;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR
	     EXTRN SYSPARSE:NEAR   ;AN000;SYSTEM COMMAND LINE PARSER

	     EXTRN EXITFL:BYTE	   ;AN000;ERRORLEVEL RETURN CODE

	     EXTRN SOURCE_DRIVE:BYTE ;AN000;FIRST DRIVE LETTER SPECIFIED IN PARMS
	     EXTRN TARGET_DRIVE:BYTE ;AN000;SECOND DRIVE LETTER SPECIFIED

	     EXTRN USER_OPTION:BYTE ;AN000;NO OPTION (-1)  /1 (1), INVALID (9)
	     EXTRN VERIFY_OPTION:BYTE ; 0 - do not verify, 1 - verify
	     EXTRN SHOW_OPTIONS:BYTE ; 0 - do not show options, 1 - show 'em
NO_OPTION    EQU  -1		   ;AN000;NO OPTION "/1" SPECIFIED
OPTION_1     EQU  1		   ;AN000;OPTION "/1" SPECIFIED
	     EXTRN MSGNUM_PARSE:WORD ;AN000;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS
	     EXTRN MSGNUM_INVALID_PARM2:WORD ;AN005;HELP INFO
	     EXTRN SUBLIST_PARSE:WORD ;AN003;POINTS TO INVALID PARM
; =  =	=  =  =  =  =  =  =  =	=  =

CURRENT_PARM DW   81H		   ;AN000;POINTER INTO COMMAND OF NEXT OPERAND
	     PUBLIC CURRENT_PARM   ;AN000;

ORDINAL      DW   0		   ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE
	     PUBLIC ORDINAL	   ;AN000;

; =  =	=  =  =  =  =  =  =  =	=  =
	     HEADER <DOS COMMAND LINE PARSER CONTROL BLOCKS> ;AN000;

;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER

	     PUBLIC PARMS	   ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE
PARMS	     LABEL BYTE 	   ;AN000;PARMS CONTROL BLOCK
	     DW   PARMSX	   ;AN000;POINTER TO PARMS EXTENSION
	     DB   0		   ;AN000; NUMBER OF STRINGS (0, 1, 2)
				   ; NEXT LIST WOULD BE EXTRA DELIM LIST
				   ;  (,& WHITESPACE ALWAYS)
				   ; NEXT LIST WOULD BE EXTRA END OF LINE LIST
				   ;  (CR,LF,0 ALWAYS)

;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK
PARMSX	     LABEL BYTE 	   ;AN000;PARMS EXTENSION CONTROL BLOCK
	     DB   0,2		   ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED
	     DW   CONTROL_POS	   ;AN000; DESCRIPTION OF POSITIONAL 1
	     DW   CONTROL_POS	   ;AN000; DESCRIPTION OF POSITIONAL 2

	     DB   3		   ;AN000; MAX SWITCH OPERANDS ALLOWED
	     DW   CONTROL_SW1	   ;AN000; DESCRIPTION OF SWITCH 1
	     DW   CONTROL_SW2	   ;AN000; DESCRIPTION OF SWITCH 2
	     DW   CONTROL_SW3	   ;4/18/90 /? switch

	     DB   0		   ;AN000; MAX KEYWORD OPERANDS ALLOWED
				   ; THERE IS NO CONTROL BLOCK
				   ;  DEFINING KEYWORDS

; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	     HEADER <POSITIONAL PARM DESCRIPTOR BLOCK> ;AN000;
;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL

;FIRST POSITIONAL PARAMETER IS:
;	[D:] - SPECIFY THE SOURCE DRIVE.

	     PUBLIC CONTROL_POS    ;AN000;LET LINK MAKE THIS ADDRESSABLE
CONTROL_POS  LABEL BYTE 	   ;AN000;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC,
				   ; OPTIONAL
	     DW   0101H 	   ;AN000; CONTROLS TYPE MATCHED
				   ; SELECTED BITS: "DRIVE ONLY" AND "OPTIONAL"

				   ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED)
				   ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE
				   ;   CHECKED)
				   ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED)
				   ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED)
				   ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED)
				   ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED)
				   ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0010H=IGNORE ":" AT END IN MATCH
				   ; 0002H=REPEATS ALLOWED
				   ; 0001H=OPTIONAL

	     DW   0002H 	   ;AN000;FUNCTION_FLAGS
				   ; 0001H=CAP RESULT BY FILE TABLE
				   ; 0002H=CAP RESULT BY CHAR TABLE
				   ; 0010H=REMOVE ":" AT END
	     DW   RESULT1	   ;AN000; RESULT BUFFER
	     DW   NOVALS	   ;AN000; NO VALUE LISTS
	     DB   0		   ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
				   ;   IN FOLLOWING LIST

;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS
NOVALS	     DB   0		   ;AN000;NO VALUE DEFINITIONS

;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER
RESULT1      LABEL BYTE 	   ;AN000; BELOW FILLED IN FOR DEFAULTS
	     DB   6		   ;AN000; TYPE RETURNED: 0=RESERVED,
				   ;	   1=NUMBER, 2=LIST INDEX,
				   ;	   3=STRING, 4=COMPLEX,
				   ;	   5=FILESPEC, 6=DRIVE
				   ;	   7=DATE, 8=TIME
				   ;	   9=QUOTED STRING
RESULT_TAG   DB   0FFH		   ;AN000; MATCHED ITEM TAG
	     DW   0		   ;AN000;POINTER TO SYNONYM

RESULT_PTR1  DB   ?		   ;AN000;DRIVE NUMBER (A=1, B=2, ETC)

; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	     HEADER <SWITCH PARM DESCRIPTOR BLOCK> ;AN000;
;PARSER CONTROL BLOCK DEFINING THE SWITCHES, OPTIONAL

;THE SWITCH IS "/1", MEANING ONLY COPY FIRST SIDE.

	     PUBLIC CONTROL_SW1    ;AN000;LET LINK MAKE THIS ADDRESSABLE
CONTROL_SW1   LABEL BYTE	   ;AN000;SWITCH DESCRIPTOR FOR /1
	     DW   0001H 	   ;AN000; CONTROLS TYPE MATCHED
				   ;SELECTED BITS: "OPTIONAL"
				   ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED)
				   ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE
				   ;   CHECKED)
				   ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED)
				   ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED)
				   ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED)
				   ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED)
				   ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED)
				   ; 0010H=IGNORE ":" AT END IN MATCH
				   ; 0002H=REPEATS ALLOWED
				   ; 0001H=OPTIONAL

	     DW   0002H 	   ;AN000;FUNCTION_FLAGS
				   ; 0001H=CAP RESULT BY FILE TABLE
				   ; 0002H=CAP RESULT BY CHAR TABLE
				   ; 0010H=REMOVE ":" AT END

	     DW   RESULTSW1	   ;AN000; RESULT BUFFER
	     DW   NOVALS	   ;AN000; VALUE LISTS
	     DB   1		   ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
				   ;   IN FOLLOWING LIST
SW_1	     DB   "/1",0	   ;AN000; IF n >0, SWITCH 1

;RESULTS CONTROL BLOCK FOR THE SWITCHES
RESULTSW1    LABEL BYTE 	   ;AN000; BELOW FILLED IN FOR DEFAULTS
	     DB   3		   ;AN000; TYPE RETURNED: 0=RESERVED,
				   ;	   1=NUMBER, 2=LIST INDEX,
				   ;	   3=STRING, 4=COMPLEX,
				   ;	   5=FILESPEC, 6=DRIVE
				   ;	   7=DATE, 8=TIME
				   ;	   9=QUOTED STRING
	     DB   0FFh		   ;AN000; MATCHED ITEM TAG

	     DW   0		   ;AN000; SYNONYM POINTER (BASED ON ES:)
RESULT_PTR21 DD   ?		   ;AN000; OFFSET OF STRING VALUE

;THE SWITCH IS "/V", MEANING VERIFY ALL TRACK WRITES

	     PUBLIC CONTROL_SW2    ;AN000;LET LINK MAKE THIS ADDRESSABLE
CONTROL_SW2   LABEL BYTE	   ;AN000;SWITCH DESCRIPTOR FOR /1
	     DW   0001H 	   ;AN000; CONTROLS TYPE MATCHED
				   ;SELECTED BITS: "OPTIONAL"

	     DW   0002H 	   ;AN000;FUNCTION_FLAGS
				   ; 0001H=CAP RESULT BY FILE TABLE
				   ; 0002H=CAP RESULT BY CHAR TABLE
				   ; 0010H=REMOVE ":" AT END

	     DW   RESULTSW2	   ;AN000; RESULT BUFFER
	     DW   NOVALS	   ;AN000; VALUE LISTS
	     DB   1		   ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
				   ;   IN FOLLOWING LIST
SW_2	     DB   "/V",0	   ;AN000; IF n >0, SWITCH 1

;RESULTS CONTROL BLOCK FOR THE SWITCHES
RESULTSW2    LABEL BYTE 	   ;AN000; BELOW FILLED IN FOR DEFAULTS
	     DB   3		   ;AN000; TYPE RETURNED: 0=RESERVED,
				   ;	   1=NUMBER, 2=LIST INDEX,
				   ;	   3=STRING, 4=COMPLEX,
				   ;	   5=FILESPEC, 6=DRIVE
				   ;	   7=DATE, 8=TIME
				   ;	   9=QUOTED STRING
	     DB   0FFh		   ;AN000; MATCHED ITEM TAG

	     DW   0		   ;AN000; SYNONYM POINTER (BASED ON ES:)
RESULT_PTR22 DD   ?		   ;AN000; OFFSET OF STRING VALUE

;THE SWITCH IS "/?", MEANING DISPLAY OPTIONS MESSAGE

	     PUBLIC CONTROL_SW3
CONTROL_SW3   LABEL BYTE
	     DW   0000H 	   ; MatchMask bits
	     DW   0000H 	   ; FuncMask bits
	     DW   RESULTSW3	   ; ptr to Result Buffer
	     DW   NOVALS	   ; ptr to Value Buffer
	     DB   1		   ; count of synonyms that follow
SW_3	     DB   "/?",0	   ; text of /? switch

;RESULTS CONTROL BLOCK FOR THIS SWITCH

RESULTSW3    LABEL BYTE
	     DB   0		   ; ValueType
	     DB   0FFh		   ; Value List Tag
	     DW   0		   ; ptr to Synonym (filled in)
RESULT_PTR3  DD   ?		   ; Value returned (dummy)

; =  =	=  =  =  =  =  =  =  =	=  =
	     PATHLABL DCOPYPAR	   ;AN015;
	     HEADER <PARSER - ASK SYSPARM TO DECODE PARAMETERS> ;AN000;
;  $SALUT (4,4,9,36)		   ;AN000;
PARSER PROC NEAR		   ;AN000;
   PUBLIC PARSER		   ;AN000;

;INPUT: "CURRENT_PARM" = OFFSET TO NEXT PARM IN COMMAND STRING
;	"ORDINAL" = COUNT OF NEXT PARM TO PARSE
;	PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING
;OUTPUT: "SOURCE_DRIVE" = VALUE OF FIRST DRIVE ID SPECIFIED, 0 IF NONE
;	 "TARGET_DRIVE" = VALUE OF SECOND DRIVE ID IF BOTH SPECIFIED, 0
;		     IF NONE OR ONLY ONE SPECIFIED
;	 "USER_OPTION" = "OPTION_1" IF /1 SPECIFIED, -1 IF NOT SPECIFIED
;	IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR".
;	DX="FINE" IF NO ERROR, OR HAS OFFSET OF PARSE ERROR DESCRIPTOR IF PROBLEM
; =  =	=  =  =  =  =  =  =  =	=  =

   mov	VERIFY_OPTION, 0	   ; assume no verify option
   MOV	USER_OPTION, NO_OPTION	   ;AN000;ASSUME NO /1 IS ENTERED.
;  $SEARCH COMPLEX		   ;AN000;LOOP THRU COMMAND LINE
   JMP SHORT $$SS1
$$DO1:
				   ;LOOKING AT RETURN CODE FROM SYSPARSE...
       CMP  AX,SYSPRM_EX_OK	   ;AN000;WERE THERE ANY ERRORS?
;  $EXITIF NE			   ;AN000;HAD A PROBLEM
   JE $$IF1
       CALL PARSE_ERROR 	   ;AN000;DISPLAY REASON FOR ERROR

;  $ORELSE			   ;AN000;SINCE NO PROBLEM, SO FAR
   JMP SHORT $$SR1
$$IF1:
       MOV  ORDINAL,CX		   ;AN000;SAVE UPDATED COUNT
       MOV  CURRENT_PARM,SI	   ;AN000;REMEMBER HOW FAR I GOT
       MOV  BX,DX		   ;AN000;SET DATA BASE REG TO POINT TO THIS OPERAND
       CMP  BX,OFFSET RESULT1	   ;AN000;WAS POSITIONAL PARM SPECIFIED?
;      $IF  E			   ;AN000;IF POSITIONAL PARM SPECIFIED,
       JNE $$IF4
	   MOV	SI,CX		   ;AN000;USE COUNT OF POSITIONALS AS INDEX
	   MOV	AL,RESULT_PTR1	   ;AN000;GET VALUE OF DRIVE (A=1, B=2, ETC)
	   MOV	SOURCE_DRIVE-1[SI],AL ;AN000;SAVE RESPONSE VALUE
				   ;IN EITHER SOURCE_DRIVE OR TARGET_DRIVE
				   ;ACCORDING TO ORDINAL IN SI (FROM CX)
;      $ELSE			   ;AN000;SINCE NOT POSITIONAL PARM SPECIFIED
       JMP SHORT $$EN4
$$IF4:

; Check to see if the parameter is one of
; the switches.

	; Check Switch 1 (/1)

	cmp	bx, offset RESULTSW1	   ; was it /1 ?
	jne	NotSwitch1 	   ; no, it should be /V
	   MOV	SW_1,BLANK	   ;AN001;AVOID GETTING DUPLICATE SWITCH
	   MOV	USER_OPTION,OPTION_1 ;AN000;MUST HAVE BEEN THE SWITCH, /1
	   jmp	short sw_set
NotSwitch1:

	; Check Switch 2 (/V)

	cmp	bx, offset RESULTSW2	; was it /V?
	jne	NotSwitch2
	  mov	SW_2, BLANK	   ; only one /V allowed
	  mov	VERIFY_OPTION, 1   ; enable Verify operation
	  jmp	short sw_set
NotSwitch2:

	; Check Switch 3 (/?)

	cmp	bx, offset RESULTSW3	; was it /?
	jne	NotSwitch3		; jump if not
	  mov	SHOW_OPTIONS, 1		; set flag for INIT
	  jmp	short sw_set		; (multiple /?s okay)
NotSwitch3:

	; Not one of the valid switches.
	; What do we do now?
	; When in doubt, fall thru to:

sw_set:
;      $ENDIF			   ;AN000;
$$EN4:
;  $STRTSRCH			   ;AN000;
$$SS1:
       LEA  DI,PARMS		   ;AN000; ES:DI = PARSE CONTROL DEFINITON
       MOV  SI,CURRENT_PARM	   ;AN000; DS:SI = COMMAND STRING, NEXT PARM
       XOR  DX,DX		   ;AN000; RESERVED, INIT TO ZERO
       MOV  CX,ORDINAL		   ;AN000; OPERAND ORDINAL, INITIALLY ZERO
       CALL SYSPARSE		   ;AN000;LOOK AT DOS PARMS
				   ; AX=EXIT CODE
				   ; BL=TERMINATED DELIMETER CODE
				   ; CX=NEW OPERAND ORDINAL
				   ; SI=SET TO PAST SCANNED OPERAND
				   ; DX=SELECTED RESULT BUFFER
       CMP  AX,SYSPRM_EX_EOL	   ;AN000; IS THAT THE END OF THE PARMS?
				   ;IF NOT, LOOP BACK AND FIND OUT
				   ; WHAT THAT PARM IS
;  $ENDLOOP E			   ;AN000;END OF LIST
   JNE $$DO1
       MOV  DX,FINE		   ;AN000;REPORT THAT PARSER WENT OK
;  $ENDSRCH			   ;AN000;FINISHED WITH DOS COMMAND LINE
$$SR1:
   RET				   ;AN000;RETURN TO CALLER
PARSER ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
   HEADER <PARSE_ERROR - DISPLAY REASON FOR PARSE ERROR> ;AN000;
PARSE_ERROR PROC NEAR		   ;AN000;
;INPUT:  AX - ERROR NUMBER RETURNED FROM PARSE.
;	 "CURRENT_PARM" - OFFSET TO WHERE THE BAD PARM STARTED
;OUTPUT: APPROPRIATE ERROR MESSAGE IS PREPARED FOR DISPLAY.
;	 DX IS SET TO OFFSET OF PARSE ERROR DESCRIPTOR.
; =  =	=  =  =  =  =  =  =  =	=  =

   MOV	MSGNUM_PARSE,AX 	   ;AN000;PASS MESSAGE NUMBER TO DESCRIPTOR
   MOV	EXITFL,EXPAR		   ;AN000;ERRORLEVEL CODE TO "PARM ERROR"
   MOV	AX,CURRENT_PARM 	   ;AN003;GET POINTER TO START OF BAD PARM
   CMP	SI,AX			   ;AN003;HAS THE INDEX TO COMMAND LINE MOVED?
;  $IF	NE			   ;AN003;YES, THERE IS A FAULTY PARM
   JE $$IF10
       MOV  BYTE PTR [SI],NUL	   ;AN003;DELIMIT THE BAD PARM
       MOV  SUBLIST_PARSE.SUB_VALUE,AX ;AN000;POINT SUBLIST TO BAD PARM

       MOV  MSGNUM_PARSE.MSG_SUBLIST,OFFSET SUBLIST_PARSE ;AN003;POINT TO SUBLIST
       MOV  MSGNUM_PARSE.MSG_COUNT,ONE_SUBS ;AN003;SET COUNT OF SUBLISTS TO ONE
;  $ENDIF			   ;AN003;INDEX MOVED?
$$IF10:
   MOV	DI,OFFSET MSGNUM_PARSE	   ;AC005;PASS BACK OFFSET TO PARSE ERR DESCRIPTOR
   CALL SENDMSG 		   ;AN005;DISPLAY THE ERROR MESSAGE

				   ; "Do not specify filename(s)",CR,LF
				   ; "Command Format: DISKCOPY d: d: [/1]",CR,LF
   MOV	DX,OFFSET MSGNUM_INVALID_PARM2 ;AN005;DISPLAY HELP INFO
   RET				   ;AN000;RETURN TO CALLER
PARSE_ERROR ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
   PATHLABL DCOPYPAR		   ;AN015;
CSEG ENDS			   ;AN000;
   END				   ;AN000;
