	PAGE	90,132			;AN000;A2
	TITLE	GRTABPAR.SAL - LOOK AT COMMAND LINE PARMS ;AN000;
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: GRTABPAR.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 GRAFTABL.  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] GRAFTABL  [cp|?|/STA|/STATUS]

;	 WHERE
;	      [d:][path] - Path where the GRAFTABL command resides.

;	      [cp]	 - Codepage number to be loaded.  If blank,
;			   437 is assumed

;	      [?]	 - This requests a display of the parameters
;			   supported by the GRAFTABL command.

;	      [/STATUS]  - (May be shortened to just /STA.)  This
;			   requests the current codepage already
;			   loaded by a previous GRAFTABL, if any,
;			   be displayed.

;	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: If a Code Page number was specified
;		  BX = Offset to language table to be loaded
;		  DX = Integer value of Code Page specified
;	       If /STATUS (or /STA) was specified
;		  BX = 0
;	       If Question mark was specified
;		  BX=-1

; EXIT-ERROR: If there was any problem with the parms,
;	      the question mark is assumed, and the appropriate
;	      PARSE error message is displayed.
;	      The Errorlevel code of "EXPAR" (3), meaning: "PARM ERROR",
;	      set in "EXITFL", is requested to be returned to the user.

; INTERNAL REFERENCES:
;    ROUTINES:
;	PARSE_ERROR:NEAR Display the appropriate Parse error message.

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

; EXTERNAL REFERENCES:
;    ROUTINES:
;	SENDMSG:NEAR	Uses Msg Descriptor to drive message handler.
;	SYSPARSE:NEAR	System Command Line Common Parser.

;    DATA AREAS:
;	TABLEUS:BYTE	First table of Fonts, happens to be the USA version.
;	  (Format of language Font defined in LANGUAGE STRUC.)
;	EXITFL:BYTE	Errorlevel return code.
;	MSGNUM_PARSE:WORD Message descriptor for all parse errors.
;	ACTIVECPID:WORD Pointer to CPID entry of active entry, where the
;	CPID	table is a set of 4 byte asciiz strings,
;			each defining the number of a Code Page font.

; NOTES:
;	 This module should be processed with the SALUT preprocessor
;	 with the re-alignment not requested, as:

;		SALUT GRTABPAR,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,
;	 GRTAB.SAL.

; REVISION HISTORY:
;	A001 PTM 382 display "ACTIVE" OR "PREVIOUS" CP.
;	A002 PTM 474 Avoid duplicate switches
;	A003 PTM 538 Display parm in error

;****************** END OF SPECIFICATIONS *****************************
	IF1				;AN000;
	    %OUT    COMPONENT=GRAFTABL, MODULE=GRTABPAR.SAL... ;AN000;
	ENDIF				;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
	INCLUDE PATHMAC.INC		;AN006;
; =  =	=  =  =  =  =  =  =  =	=  =
HEADER	MACRO	TEXT			;;AN000;
.XLIST					;AN000;
	SUBTTL	TEXT			;AN000;
.LIST					;AN000;
	PAGE				;AN000;
	ENDM				;;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
;		      $SALUT (4,23,28,36) ;AN000;
		      EXTRN CPID_L:ABS ;AN000;BYTES PER CPID ENTRY

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);AN003;
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	   ;AN003;
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  ;AN003;
				   ; IF THIS IS A .COM FILE)			   ;AN003;
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 ",".			   ;AN003;
				   ; "," CAUSES INSERTION OF THE ACTIVE 	   ;AN003;
				   ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS.   ;AN003;
SUBLIST 	      ENDS	   ;AN003;

;		LOCAL EQUATES
ZERO		      EQU  0	   ;AN000;COMPARAND FOR MISSING PARMS
RETCODE_QUESTION      EQU  -1	   ;AN000;VALUE IN BX, IF PARM=?
EXPAR		      EQU  3	   ;AN000;RETURN TO DOS, INVALID DOS COMND LINE PARMS
CR		      EQU  13	   ;AN000;CARRIAGE RETURN
BLANK		      EQU  " "	   ;AN002;AVOIDS DUPLICATES SWITCHES
NUL		      EQU  0	   ;AN003;ASCIIZ DELIMITER
; =  =	=  =  =  =  =  =  =  =	=  =
;		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;
LANGUAGE	      STRUC	   ;AN000;DEFINITION OF EACH LANGUAGE TABLE
LANCHAR 	      DB   1024 DUP(?) ;AN000;8 BYTES PER EACH OF 128 CHARACTERS
LANID		      DW   ?	   ;AN000;TWO BYTE CODEPAGE ID, TO MATCH
				   ; GRAFTABL CMD LINE PARM
LANNAME 	      DB   14 DUP(?) ;AN000;ASCIIZ STRING NAME OF LANGUAGE
LANGUAGE	      ENDS	   ;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;
; =  =	=  =  =  =  =  =  =  =	=  =
		      HEADER <PARSING WORKAREAS> ;AN000;
;	     $SALUT (4,14,19,36)   ;AN000;
CSEG	     SEGMENT PARA PUBLIC   ;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 TABLEUS:BYTE    ;AN000;FIRST TABLE OF FONTS
	     EXTRN EXITFL:BYTE	   ;AN000;ERRORLEVEL RETURN CODE
	     EXTRN MSGNUM_PARSE:WORD ;AN000;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS
	     EXTRN SUBLIST_PARSE:WORD ;AN003;POINTS TO INVALID PARM
	     EXTRN ACTIVECPID:WORD ;AN000;POINTER TO CPID ENTRY OF ACTIVE ENTRY
; =  =	=  =  =  =  =  =  =  =	=  =

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;

FIRST_TIME   DB   0		   ;AN000;INDICATES IF A PARM ALREADY FOUND
PARSE_RESULT DW   0		   ;AN000;TEMP, HOLDS BX TO BE RETURNED
;	       If a Code Page number was specified
;		  BX = Offset to language table to be loaded
;		  DX = Integer value of Code Page specified
;	       If /STATUS (or /STA) was specified
;		  BX = 0
;	       If Question mark was specified
;		  BX=-1
; =  =	=  =  =  =  =  =  =  =	=  =
	     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,1		   ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED
	     DW   CONTROL_POS	   ;AN000; DESCRIPTION OF POSITIONAL 1

	     DB   1		   ;AN000; MAX SWITCH OPERANDS ALLOWED
	     DW   CONTROL_SW	   ;AN000; DESCRIPTION OF SWITCH 1

	     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:
;	[cp|?]	THE CODEPAGE NUMBER, OR THE QUESTION MARK

	     PUBLIC CONTROL_POS    ;AN000;LET LINK MAKE THIS ADDRESSABLE
CONTROL_POS  LABEL BYTE 	   ;AN000;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC,
				   ; OPTIONAL
	     DW   2001H 	   ;AN000; CONTROLS TYPE MATCHED
				   ; SELECTED BITS: "SIMPLE STRING" 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   0000H 	   ;AN000;FUNCTION_FLAGS ("NO CAPS")
				   ; 0001H=CAP RESULT BY FILE TABLE
				   ; 0002H=CAP RESULT BY CHAR TABLE
				   ; 0010H=REMOVE ":" AT END
	     DW   RESULT	   ;AN000; RESULT BUFFER
	     DW   VALS		   ;AN000; VALUE LISTS
	     DB   0		   ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
				   ;   IN FOLLOWING LIST

;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS
VALS	     DB   3		   ;AN000;NUMBER OF VALS DEFINITIONS (0-3)
	     DB   0		   ;AN000;NUMBER OF RANGES (NONE)
	     DB   0		   ;AN000;NUMBER OF NUMERIC CHOICES (NONE)
	     DB   6		   ;AN000;NUMBER OF CHOICE STRINGS


;THE ORDER OF THESE VALUE DEFINITIONS IS SIGNIFICANT.  THEIR ORDER MUST
;MATCH THE ORDER IN WHICH THE CORRESPONDING FONT TABLE MODULES ARE
;LINKED TOGETHER.  THUE THE "VALUE RETURNED" OF 1 MEANS THE FIRST LINKED
;FONT TABLE, THE VALUE OF 5 MEANS THE FIFTH LINKED FONT TABLE, ETC.

VAL_437      EQU  1		   ;AN000;VALUE RETURNED
	     DB   VAL_437	   ;AN000; FOR:
	     DW   S437		   ;AN000;SPECIFIC CHOICE IF STRING

VAL_850      EQU  2		   ;AN000;VALUE RETURNED
	     DB   VAL_850	   ;AN000; FOR:
	     DW   S850		   ;AN000;SPECIFIC CHOICE IF STRING

VAL_860      EQU  3		   ;AN000;VALUE RETURNED
	     DB   VAL_860	   ;AN000; FOR:
	     DW   S860		   ;AN000;SPECIFIC CHOICE IF STRING

VAL_863      EQU  4		   ;AN000;VALUE RETURNED
	     DB   VAL_863	   ;AN000; FOR:
	     DW   S863		   ;AN000;SPECIFIC CHOICE IF STRING

VAL_865      EQU  5		   ;AN000;VALUE RETURNED
	     DB   VAL_865	   ;AN000; FOR:
	     DW   S865		   ;AN000;SPECIFIC CHOICE IF STRING

VAL_QUESTION EQU  6		   ;AN000;VALUE RETURNED
	     DB   VAL_QUESTION	   ;AN000; FOR:
	     DW   SQU		   ;AN000;SPECIFIC CHOICE IF STRING

;		SET OF ASCIIZ STRINGS, DEFINING THE POSITIONAL PARAMETER
S437	     DB   "437",0	   ;AN000;USA
S850	     DB   "850",0	   ;AN000;MULTI-LINGUAL
S860	     DB   "860",0	   ;AN000;PORTUGUESE
S863	     DB   "863",0	   ;AN000;CANADIAN FRENCH
S865	     DB   "865",0	   ;AN000;NORDIC
SQU	     DB   "?",0 	   ;AN000;

;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER, AND SWITCH PARAMETER
RESULT	     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
RESULT_TAG   DB   0FFH		   ;AN000; MATCHED ITEM TAG
RESULT_SYN   DW   0		   ;AN000;POINTER TO SYNONYM

RESULT_PTR   DD   ?		   ;AN000;OFFSET OF STRING VALUE

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

;THE SWITCH IS "/STA" OR "/STATUS".  WHEN REQUESTED, IT MEANS TO IDENTIFY
;WHAT CODEPAGE IS CURRENTLY SUPPORTED BY THE PREVIOUS GRAFTABL, IF ANY.
	     PUBLIC CONTROL_SW	   ;AN000;LET LINK MAKE THIS ADDRESSABLE
CONTROL_SW   LABEL BYTE 	   ;AN000;SWITCH DESCRIPTOR FOR /STA
	     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   0000H 	   ;AN000;FUNCTION_FLAGS ("NO CAPS")
				   ; 0001H=CAP RESULT BY FILE TABLE
				   ; 0002H=CAP RESULT BY CHAR TABLE
				   ; 0010H=REMOVE ":" AT END

	     DW   RESULT	   ;AN000; RESULT BUFFER
				   ;(USE SAME RESULT BUF AS DID POSITIONAL PARM)
	     DW   NOVALS	   ;AN000; VALUE LISTS
	     DB   2		   ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
				   ;   IN FOLLOWING LIST
SW_STA	     DB   "/STA",0	   ;AN000; IF n >0, KEYWORD 1
SW_STATUS    DB   "/STATUS",0	   ;AN000;SECOND KEYWORD

;VALUE CONTROL BLOCK FOR THE SWITCHES
NOVALS	     LABEL BYTE 	   ;AN000;
	     DB   0		   ;AN000; NUMBER OF VALUE DEFINITIONS (0 - 3)
; =  =	=  =  =  =  =  =  =  =	=  =
	     PATHLABL GRTABPAR	   ;AN006;
	     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: IF A CODEPAGE NUMBER WAS SPECIFIED
;	    BX = OFFSET TO LANGUAGE TABLE TO BE LOADED
;	    DX = INTEGER VALUE OF CODEPAGE SPECIFIED
;	 IF /STATUS WAS SPECIFIED
;	    BX = 0
;	 IF QUESTION MARK WAS SPECIFIED
;	    BX=-1

;IF THERE WAS ANY PROBLEM WITH THE PARMS, THE QUESTION MARK IS ASSUMED,
;AND "EXITFL" SET TO "EXPAR" TO INDICATE PARM ERROR.

;IT A CP IS SPECIFIED, A STATUS REPORT IS ALWAYS GIVEN TO SAY WHAT WHAT
;THERE PREVIOUSLY, SO IF THE USER SPECIFIED A CP AND THE /STATUS SWITCH,
;THEN THE /STATUS DOES NOTHING BEYOND WHAT WOULD HAVE BEEN DONE ALREADY
;WITH JUST THE CP SPECIFICATION.  I ALWAYS REPORT STATUS.  THE ONLY
;REASON TO HAVE /STATUS IS TO BE ABLE TO SEE WHAT IS THERE ALREADY
;WITHOUT INVOKING THE DEFAULT OF 437 (USA) BY NOT SPECIFYING A CP.
; =  =	=  =  =  =  =  =  =  =	=  =

;  $SEARCH COMPLEX		   ;AN000;LOOP THRU COMMAND LINE
   JMP SHORT $$SS1
$$DO1:
				   ;LOOKING AT RET CODE IN AX SET BY SYSPARSE
       CMP  AX,ZERO		   ;AN000;WERE THERE ANY ERRORS?
;  $EXITIF NE			   ;AN000;HAD A PROBLEM
   JE $$IF1
       CALL PARSE_ERROR 	   ;AN000;DISPLAY REASON FOR ERROR

;  $ORELSE LONG 		   ;AN000;SINCE NO PROBLEM, SO FAR
   JMP $$SR1
$$IF1:
       MOV  ORDINAL,CX		   ;AN000;SAVE UPDATED COUNT
       CMP  FIRST_TIME,ZERO	   ;AN000;DO I HAVE A PARM YET?
;      $IF  E			   ;AN000;NOT YET, LOOK AT THIS ONE JUST FOUND
       JNE $$IF4
	   MOV	CURRENT_PARM,SI    ;AN000;REMEMBER HOW FAR I GOT
	   CMP	RESULT_SYN,ZERO    ;AN000;WAS POSITIONAL PARM SPECIFIED?
;	   $IF	E		   ;AN000;IF POSITIONAL PARM SPECIFIED,
	   JNE $$IF5
	       MOV  CL,RESULT_TAG  ;AN000;GET ID OF SPECIFIED PARM
	       XOR  CH,CH	   ;AN000;CLEAR HIGH BYTE
	       CMP  CL,VAL_QUESTION ;AN000;WAS "?" SPECIFIED?
;	       $IF  E		   ;AN000;IF "?" SPECIFIED
	       JNE $$IF6
		   MOV	BX,RETCODE_QUESTION ;AN000;INDICATE THAT "?" SPECIFIED
;	       $ELSE		   ;AN000;SINCE "?" NOT SPECIFIED
	       JMP SHORT $$EN6
$$IF6:
		   LEA	BX,TABLEUS ;AN000;GET WHERE FIRST CODEPAGE STARTS, USING CX
				   ; AS A COUNTER, STEP THRU THE LANGUAGE TABLES
				   ; UNTIL GETTING TO THE SPECIFIED ONE
;		   $DO	COMPLEX    ;AN000;
		   JMP SHORT $$SD8
$$DO8:
		       ADD  BX,TYPE LANGUAGE ;AN000;POINT TO NEXT TABLE
		       ADD  ACTIVECPID,CPID_L ;AN000;SELECT NEXT CPID ENTRY
;		   $STRTDO	   ;AN000;
$$SD8:
;		   $ENDDO LOOP	   ;AN000;DECREMENT INDEX
		   LOOP $$DO8
				   ;BX-OFFSET TO LANGUAGE TABLE
				   ; INDICATED BY POSITIONAL PARM
;	       $ENDIF		   ;AN000;"?" SPECIFIED?
$$EN6:
;	   $ELSE		   ;AN000;SINCE NOT POSITIONAL PARM SPECIFIED
	   JMP SHORT $$EN5
$$IF5:
				   ;RESULT_SYN POINTS TO A SWITCH
	       XOR  BX,BX	   ;AN000;  MUST HAVE BEEN THE SWITCH, /STATUS
	       MOV  SW_STA,BLANK   ;AN002;AVOID THE DUPLICATION OF THIS SWITCH
	       MOV  SW_STATUS,BLANK ;AN002;AVOID THE DUPLICATION OF THIS SWITCH
;	   $ENDIF		   ;AN000;POSITIONAL?
$$EN5:
	   INC	FIRST_TIME	   ;AN000;INDICATE A PARM HAS BEEN FOUND
;      $ELSE			   ;AN000;SINCE ALREADY HAVE A PARM
       JMP SHORT $$EN4
$$IF4:
	   PUSH SI		   ;AN003;SAVE NEW INDEX TO COMMAND LINE
	   CALL PARSE_ERROR	   ;AN000;FUSS ABOUT TOO MANY PARMS

	   POP	CURRENT_PARM	   ;AN000;REMEMBER HOW FAR I GOT

;      $ENDIF			   ;AN000;ALREADY HAVE A PARM?
$$EN4:
       MOV  PARSE_RESULT,BX	   ;AN000;SAVE THE RESULT OF THIS PARSE
;  $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
       CMP  FIRST_TIME,ZERO	   ;AN000;FIND ANYTHING YET?
;      $IF  E			   ;AN000;IF NO PARM SPECIFIED
       JNE $$IF18
	   LEA	BX,TABLEUS	   ;AN000;SPECIFY 437 (USA) AS DEFAULT
;      $ELSE			   ;AN000;SINCE A PARM WAS FOUND
       JMP SHORT $$EN18
$$IF18:
	   MOV	BX,PARSE_RESULT    ;AN000;REMEMBER PARM ALREADY FOUND
;      $ENDIF			   ;AN000;
$$EN18:
				   ;BX=-1, "?"; BX=0, "/STATUS";BX>0, CP TABLE
       CMP  BX,ZERO		   ;AN000;WAS A CP TABLE FOUND?
;      $IF  A			   ;AN000;IF A CP TABLE FOUND
       JNA $$IF21
	   MOV	DX,[BX].LANID	   ;AN000;FETCH THE TWO CHAR ID FROM TABLE
;      $ENDIF			   ;AN000;
$$IF21:
;  $ENDSRCH			   ;AN000;FINISHED WITH DOS COMMAND LINE
$$SR1:
   RET				   ;AN000;RETURN TO CALLER
PARSER ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =						;AN000;
   HEADER <PARSE_ERROR - DISPLAY REASON FOR PARSE ERROR> ;AN000;
PARSE_ERROR PROC NEAR		   ;AN000;
;INPUT: "FIRST_TIME" - IF NON-ZERO, FORCE ERROR CODE TO "TOO MANY PARMS"
;	 AX - ERROR NUMBER RETURNED FROM PARSE.
;	 SI - OFFSET INTO COMMAND OF FIRST BYTE BEYOND PARM IN ERROR
;	 "CURRENT_PARM" - OFFSET INTO COMMAND OF WHERE TO START LOOKING FOR PARM
;OUTPUT: APPROPRIATE ERROR MESSAGE IS DISPLAYED.
;	 BX IS SET TO PRETEND THAT THE "?" WAS SPECIFIED.
;	 "EXITFL" SET TO "EXPAR" TO INDICATE PARM ERROR.
; =  =	=  =  =  =  =  =  =  =	=  =

   CMP	FIRST_TIME,ZERO 	   ;AN000;ANY PARMS FOUND YET?
;  $IF	NE			   ;AN000;IF PARM ALREADY FOUND
   JE $$IF24
       MOV  AX,SYSPRM_EX_MANY	   ;AN000;CHANGE RETURN CODE TO "TOO MANY PARMS"
;  $ENDIF			   ;AN000;PARMS FOUND?
$$IF24:
   MOV	MSGNUM_PARSE,AX 	   ;AN000;PASS MESSAGE NUMBER TO DESCRIPTOR
   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 $$IF26
       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?
$$IF26:
   LEA	DI,MSGNUM_PARSE 	   ;AN000;PASS MESSAGE DESCRIPTOR
   CALL SENDMSG 		   ;AN000;DISPLAY ERROR MESSAGE

   MOV	BX,RETCODE_QUESTION	   ;AN000;INDICATE THAT "?" SPECIFIED
   MOV	EXITFL,EXPAR		   ;AN000;ERRORLEVEL CODE TO "PARM ERROR"
   RET				   ;AN000;RETURN TO CALLER
PARSE_ERROR ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
   PATHLABL GRTABPAR		   ;AN006;
CSEG ENDS			   ;AN000;
   END				   ;AN000;
