*DECK,CMDPRSR 
USETEXT COMCBEG 
USETEXT COMQDEF 
USETEXT COMQCMD 
USETEXT COMQPAR 
      PROC CMDPRSR; 
        BEGIN    # CMDPRSR #
# 
**    CMDPRSR     COMMAND PARSER. 
* 
*     PARSES ONE COMMAND USING A FINITE-STATE RECOGNIZER. 
* 
*     PROC CMDPRSR
* 
*     ENTRY      COMMAND = COMMAND TO BE PROCESSED. 
* 
*     EXIT       PARM$STAT = STATUS OF PARSE, 
*                PARM$VERB = COMMAND VERB,
*                PARM$VERBL = LENGTH OF VERB, 
*                PARM$PCNT = PARAMETER COUNT, 
*                PARM$CMDL = LENGTH OF COMMAND. 
*                PARM$ECOL = COLUMN WHERE PARSER STOPPED. 
*                PARMS[1]..PARMS[PARM$PCNT] CONTAIN PARSED PARAMETERS:  
*                  PARM$KEY[I]   = KEYWORD OR POSITIONAL NAME,
*                  PARM$VTYPE[I] = VALUE TYPE,
*                  PARM$COL[I]   = STARTING COLUMN OF PARAMETER,
*                  PARM$VALUE[I] = VALUE: 
*                                  NAME, IF *=NAME*,
*                                  BINARY INTEGER, IF *=INTEGER*, 
*                                  BINARY RANGE, IF *=I..J*.
*                  PARM$PLEN[1]  = KEYWORD LENGTH,
*                  PARM$VLEN[1]  = VALUE LENGTH.
* 
*     PROCESS    INITIALIZE VARIABLES 
*                SET CURRENT-STATE TO START 
*                WHILE CURRENT-STATE NOT EQUAL HALT:  
*                  GET NEXT TOKEN 
*                  SET NEXT-STATE FROM PARSETABLE INDEXED BY
*                      CURRENT-STATE, TOKENTYPE 
*                  SET ACTION FROM PARSETABLE INDEXED BY
*                      CURRENT-STATE, TOKENTYPE 
*                  PERFORM ACTION 
*                  IF NEXT-STATE IS HALT: 
*                    SET PARM$STAT FROM PARSETABLE INDEXED BY 
*                        CURRENT-STATE, TOKENTYPE 
*                  SET CURRENT-STATE TO NEXT-STATE
*                IF NOT AT ZERO-BYTE OR END OF STRING:  
*                  BLANK FILL COMMAND FROM ZERO-BYTE TO END.
* 
# 
  
# 
****  XREF
# 
      XREF
        BEGIN 
        PROC NAME;                 # DEBUG CODE # 
        FUNC XDXB       B;         # CONVERT DISPLAY CODE TO INTEGER #
        END 
  
# 
****  XREF END
# 
  
      STATUS CH                    # INPUT CHARACTERS (DISPLAY CODE) #
         NULL                      # START OF ZERO-BYTE (OR COLON) #
        ,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
        ,ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE
        ,PLUS, MINUS, ASTERISK
        ,SLASH, LEFTPAR, RIGHTPAR, DOLLAR 
        ,EQUAL, SPACE, COMMA, PERIOD
        ,OTHER;                    # OTHERS (DPC 60B AND ABOVE) # 
  
      STATUS TOKENTYPE             # TOKENS RECOGNIZED #
         SPACE                     #   #
        ,LETTER                    # A ... Z #
        ,DIGIT                     # 0 ... 9 #
        ,SEPARATOR                 # , #
        ,TERMINATOR                # . (ZERO-BYTE) #
        ,ASTERISK                  # * #
        ,ELLIPSIS                  # .. # 
        ,EQUALS                    # = #
        ,PLUSMINUS                 # + - #
        ,OTHER                     # ANYTHING ELSE #
        ; 
  
      STATUS PARSESTATE            # RECOGNIZER STATE # 
         HALT 
        ,START                     # INITIAL, SKIP LEADING SPACES # 
        ,VERB                      # PARSING COMMAND VERB # 
        ,SPACES                    # SKIP SPACES BEFORE SEP OR PARM # 
        ,SEPARATOR                 # SEPARATOR PARSED # 
        ,KEYWORD                   # PARSING KEYWORD OR POSITION NAME # 
        ,KEYEQUALS                 # *KEYWORD=* RECOGNIZED #
        ,NAME                      # PARSING NAME # 
        ,ASTERISK                  # * RECOGNIZED # 
        ,INTEGER                   # PARSING INT OR RANGE LB #
        ,ELLIPSIS                  # ELLIPSIS RECOGNIZED #
        ,RANGE                     # PARSING RANGE UB # 
        ; 
  
      STATUS PARSEACT              # PARSER ACTION #
         NOTHING                   # DO NOTHING # 
        ,STARTVERB                 # STARTING VERB #
        ,VERB                      # STORE NEXT CHARACTER OF VERB # 
        ,STARTKEYW                 # STARTING KEYWORD/NAME #
        ,KEYWORD                   # STORE NEXT CHARACTER OF KEY/NAME # 
        ,KWEQUALS                  # DECREMENT PARAMETER COUNT #
        ,STARTNAME                 # STARTING NAME OR INTEGER VALUE # 
        ,NAME                      # STORE NEXT CHARACTER OF NAME # 
        ,CONVERINTG                # CONVERT NAME TO BINARY INTEGER # 
        ,STARTRANG                 # START UPPER BOUND OF RANGE # 
        ,RANGE                     # ADD DIGIT TO UPPER BOUND # 
        ,ASTERVALUE                # STORE ASTERISK VALUE # 
        ,KEYWVALUE                 # STORE KEYWORD ONLY VALUE # 
        ,EMPTYVALUE                # STORE EMPTY VALUE #
        ,DEFVALUE                  # STORE DEFAULT VALUE #
        ; 
  
      ARRAY TOKENTABLE [TOKENTYPE"SPACE":TOKENTYPE"OTHER"] S(1);
        BEGIN 
        ITEM CHTOKENSET U(00,00,60);  # SET OF CH # 
  
        ITEM CH$A      B(00,CH"A"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$B      B(00,CH"B"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$C      B(00,CH"C"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$D      B(00,CH"D"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$E      B(00,CH"E"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$F      B(00,CH"F"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$G      B(00,CH"G"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$H      B(00,CH"H"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$I      B(00,CH"I"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$J      B(00,CH"J"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$K      B(00,CH"K"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$L      B(00,CH"L"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$M      B(00,CH"M"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$N      B(00,CH"N"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$O      B(00,CH"O"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$P      B(00,CH"P"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$Q      B(00,CH"Q"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$R      B(00,CH"R"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$S      B(00,CH"S"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$T      B(00,CH"T"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$U      B(00,CH"U"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$V      B(00,CH"V"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$W      B(00,CH"W"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$X      B(00,CH"X"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$Y      B(00,CH"Y"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$Z      B(00,CH"Z"       ,01) = [FALSE,TRUE,8(FALSE)]; 
        ITEM CH$0      B(00,CH"ZERO"    ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$1      B(00,CH"ONE"     ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$2      B(00,CH"TWO"     ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$3      B(00,CH"THREE"   ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$4      B(00,CH"FOUR"    ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$5      B(00,CH"FIVE"    ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$6      B(00,CH"SIX"     ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$7      B(00,CH"SEVEN"   ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$8      B(00,CH"EIGHT"   ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$9      B(00,CH"NINE"    ,01) = [2(FALSE),TRUE,7(FALSE)];
        ITEM CH$PLUS   B(00,CH"PLUS"    ,01) = [8(FALSE),TRUE,1(FALSE)];
        ITEM CH$MINUS  B(00,CH"MINUS"   ,01) = [8(FALSE),TRUE,1(FALSE)];
        ITEM CH$ASTERI B(00,CH"ASTERISK",01) = [5(FALSE),TRUE,4(FALSE)];
        ITEM CH$SLASH  B(00,CH"SLASH"   ,01) = [9(FALSE),TRUE]; 
        ITEM CH$LEFTPA B(00,CH"LEFTPAR" ,01) = [8(FALSE),TRUE,1(FALSE)];
        ITEM CH$RIGHTP B(00,CH"RIGHTPAR",01) = [8(FALSE),TRUE,1(FALSE)];
        ITEM CH$DOLLAR B(00,CH"DOLLAR"  ,01) = [9(FALSE),TRUE]; 
        ITEM CH$EQUAL  B(00,CH"EQUAL"   ,01) = [7(FALSE),TRUE,2(FALSE)];
        ITEM CH$SPACE  B(00,CH"SPACE"   ,01) = [TRUE,9(FALSE)]; 
        ITEM CH$COMMA  B(00,CH"COMMA"   ,01) = [3(FALSE),TRUE,6(FALSE)];
        ITEM CH$PERIOD B(00,CH"PERIOD"  ,01) = [4(FALSE),TRUE,5(FALSE)];
        ITEM CH$NULL   B(00,CH"NULL"    ,01) = [4(FALSE),TRUE,5(FALSE)];
        ITEM CH$OTHER  B(00,CH"OTHER"   ,01) = [9(FALSE),TRUE]; 
  
        ITEM TOKENSTAT  S:TOKENTYPE(00,54,06) = 
        [S"SPACE",S"LETTER",S"DIGIT",S"SEPARATOR",S"TERMINATOR",
         S"ASTERISK",S"ELLIPSIS",S"EQUALS",S"PLUSMINUS",S"OTHER"];
  
        # ENSURE ALL CHARACTERS APPEAR IN AT LEAST ONE SET (OTHER) #
  
        ITEM CH$CHECK   U(00,00,54) = 
        [        ,         ,        ,            ,             ,
                    ,           ,         ,            ,
         O"7777 7777 7777 7777 77"];
  
        END 
  
      ARRAY PARSETABLE [PARSESTATE"START":PARSESTATE"RANGE"] S(3);
        BEGIN 
  
        ITEM PAR$ACT    U(00,00,60);  # TRANSITION ACTION # 
  
        ITEM PAR$ACT0   S:PARSEACT(00,00,06) =  # SPACE # 
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"KEYWVALUE" ,S"EMPTYVALUE",S"NOTHING"   ,S"NOTHING"    ,
         S"CONVERINTG",S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT1   S:PARSEACT(00,06,06) =  # LETTER #
        [S"STARTVERB" ,S"VERB"      ,S"STARTKEYW" ,S"STARTKEYW"  ,
         S"KEYWORD"   ,S"STARTNAME" ,S"NAME"      ,S"NOTHING"    ,
         S"NAME"      ,S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT2   S:PARSEACT(00,12,06) =  # DIGIT # 
        [S"NOTHING"   ,S"VERB"      ,S"STARTNAME" ,S"STARTNAME"  ,
         S"KEYWORD"   ,S"STARTNAME" ,S"NAME"      ,S"NOTHING"    ,
         S"NAME"      ,S"STARTRANG" ,S"RANGE"     ];
        ITEM PAR$ACT3   S:PARSEACT(00,18,06) =  # SEPARATOR # 
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"DEFVALUE"   ,
         S"KEYWVALUE" ,S"EMPTYVALUE",S"NOTHING"   ,S"NOTHING"    ,
         S"CONVERINTG",S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT4   S:PARSEACT(00,24,06) =  # TERMINATOR #
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"DEFVALUE"   ,
         S"KEYWVALUE" ,S"EMPTYVALUE",S"NOTHING"   ,S"NOTHING"    ,
         S"CONVERINTG",S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT5   S:PARSEACT(00,30,06) =  # ASTERISK #
        [S"NOTHING"   ,S"NOTHING"   ,S"ASTERVALUE",S"ASTERVALUE" ,
         S"NOTHING"   ,S"ASTERVALUE",S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT6   S:PARSEACT(00,36,06) =  # ELLIPSIS #
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"CONVERINTG",S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT7   S:PARSEACT(00,42,06) =  # EQUALS #
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"KWEQUALS"  ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT8   S:PARSEACT(00,48,06) =  # PLUSMINUS # 
        [S"STARTVERB" ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ];
        ITEM PAR$ACT9   S:PARSEACT(00,54,06) =  # OTHER # 
        [S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"    ,
         S"NOTHING"   ,S"NOTHING"   ,S"NOTHING"   ];
  
        ITEM PAR$NXT    U(01,00,60);  # NEXT STATE #
  
        ITEM PAR$NXT0   S:PARSESTATE(01,00,06) =  # SPACE # 
        [S"START"     ,S"SPACES"    ,S"SPACES"    ,S"SEPARATOR"  ,
         S"SPACES"    ,S"SPACES"    ,S"SPACES"    ,S"SPACES"     ,
         S"SPACES"    ,S"HALT"      ,S"SPACES"    ];
        ITEM PAR$NXT1   S:PARSESTATE(01,06,06) =  # LETTER #
        [S"VERB"      ,S"VERB"      ,S"KEYWORD"   ,S"KEYWORD"    ,
         S"KEYWORD"   ,S"NAME"      ,S"NAME"      ,S"HALT"       ,
         S"NAME"      ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT2   S:PARSESTATE(01,12,06) =  # DIGIT # 
        [S"HALT"      ,S"VERB"      ,S"INTEGER"   ,S"INTEGER"    ,
         S"KEYWORD"   ,S"INTEGER"   ,S"NAME"      ,S"HALT"       ,
         S"INTEGER"   ,S"RANGE"     ,S"RANGE"     ];
        ITEM PAR$NXT3   S:PARSESTATE(01,18,06) =  # SEPARATOR # 
        [S"HALT"      ,S"SEPARATOR" ,S"SEPARATOR" ,S"SEPARATOR"  ,
         S"SEPARATOR" ,S"SEPARATOR" ,S"SEPARATOR" ,S"SEPARATOR"  ,
         S"SEPARATOR" ,S"HALT"      ,S"SEPARATOR" ];
        ITEM PAR$NXT4   S:PARSESTATE(01,24,06) =  # TERMINATOR #
        [S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT5   S:PARSESTATE(01,30,06) =  # ASTERISK #
        [S"HALT"      ,S"HALT"      ,S"ASTERISK"  ,S"ASTERISK"   ,
         S"HALT"      ,S"ASTERISK"  ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT6   S:PARSESTATE(01,36,06) =  # ELLIPSIS #
        [S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"ELLIPSIS"  ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT7   S:PARSESTATE(01,42,06) =  # EQUALS #
        [S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"KEYEQUALS" ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT8   S:PARSESTATE(01,48,06) =  # PLUSMINUS # 
        [S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ];
        ITEM PAR$NXT9   S:PARSESTATE(01,54,06) =  # OTHER # 
        [S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ,S"HALT"       ,
         S"HALT"      ,S"HALT"      ,S"HALT"      ];
  
        ITEM PAR$STA    U(02,00,60);  # HALT STATUS # 
  
        ITEM PAR$STA0   S:STAT(02,00,06) =  # SPACE # 
        [S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"RANGERR"   ,S"OK"        ];
        ITEM PAR$STA1   S:STAT(02,06,06) =  # LETTER #
        [S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"OK"        ,S"OK"        ,S"ASTKERR"    ,
         S"OK"        ,S"RANGERR"   ,S"RANGERR"   ];
        ITEM PAR$STA2   S:STAT(02,12,06) =  # DIGIT # 
        [S"VERBERR"   ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"OK"        ,S"OK"        ,S"ASTKERR"    ,
         S"OK"        ,S"OK"        ,S"OK"        ];
        ITEM PAR$STA3   S:STAT(02,18,06) =  # SEPARATOR # 
        [S"VERBERR"   ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"RANGERR"   ,S"OK"        ];
        ITEM PAR$STA4   S:STAT(02,24,06) =  # TERMINATOR #
        [S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"OK"        ,S"OK"        ,S"OK"         ,
         S"OK"        ,S"RANGERR"   ,S"OK"        ];
        ITEM PAR$STA5   S:STAT(02,30,06) =  # ASTERISK #
        [S"ASTKERR"   ,S"SEPERR"    ,S"OK"        ,S"OK"         ,
         S"ASTKERR"   ,S"OK"        ,S"ASTKERR"   ,S"ASTKERR"    ,
         S"ASTKERR"   ,S"RANGERR"   ,S"ASTKERR"   ];
        ITEM PAR$STA6   S:STAT(02,36,06) =  # ELLIPSIS #
        [S"VERBERR"   ,S"SEPERR"    ,S"ELIPERR"   ,S"ELIPERR"    ,
         S"ELIPERR"   ,S"ELIPERR"   ,S"ELIPERR"   ,S"ELIPERR"    ,
         S"OK"        ,S"RANGERR"   ,S"ELIPERR"   ];
        ITEM PAR$STA7   S:STAT(02,42,06) =  # EQUALS #
        [S"VERBERR"   ,S"SEPERR"    ,S"EQUALERR"  ,S"EQUALERR"   ,
         S"OK"        ,S"EQUALERR"  ,S"EQUALERR"  ,S"EQUALERR"   ,
         S"EQUALERR"  ,S"RANGERR"   ,S"EQUALERR"  ];
        ITEM PAR$STA8   S:STAT(02,48,06) =  # PLUSMINUS # 
        [S"OK"        ,S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"    ,
         S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"    ,
         S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"   ];
        ITEM PAR$ST98   S:STAT(02,54,06) =  # OTHER # 
        [S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"    ,
         S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"    ,
         S"INVCHAR"   ,S"INVCHAR"   ,S"INVCHAR"   ];
        END 
  
      SWITCH SW$ACT:PARSEACT       # PARSER ACTION #
         SW$NOTHING:NOTHING        # DO NOTHING # 
        ,SW$STARTVE:STARTVERB      # STARTING VERB #
        ,SW$VERB   :VERB           # STORE NEXT CHARACTER OF VERB # 
        ,SW$STARTKE:STARTKEYW      # STARTING KEYWORD/NAME #
        ,SW$KEYWORD:KEYWORD        # STORE NEXT CHARACTER OF KEY/NAME # 
        ,SW$KWEQUAL:KWEQUALS       # DECREMENT PARAMETER COUNT #
        ,SW$STARTNA:STARTNAME      # STARTING NAME OR INTEGER VALUE # 
        ,SW$NAME   :NAME           # STORE NEXT CHARACTER OF NAME # 
        ,SW$CONVERI:CONVERINTG     # CONVERT NAME TO BINARY INTEGER # 
        ,SW$STARTRA:STARTRANG      # START UPPER BOUND OF RANGE # 
        ,SW$RANGE  :RANGE          # ADD DIGIT TO UPPER BOUND # 
        ,SW$ASTERVA:ASTERVALUE     # STORE ASTERISK VALUE # 
        ,SW$KEYWVAL:KEYWVALUE      # STORE KEYWORD ONLY VALUE # 
        ,SW$EMPTYVA:EMPTYVALUE     # STORE EMPTY VALUE #
        ,SW$DEFVALU:DEFVALUE       # STORE DEFAULT VALUE #
        ; 
  
      ARRAY [0:0] S(1); 
        BEGIN 
        ITEM CHARNXT    C(00,48,02); # CURRENT AND NEXT CHARACTER # 
        ITEM CHARNXTU   U(00,48,12); # BOTH CHARACTERS IN BINARY #
        ITEM CHAR       C(00,48,01); # CURRENT CHARACTER #
        ITEM CHARU      U(00,48,06); # CHARACTER IN BINARY #
        ITEM NXTCHAR    C(00,54,01); # NEXT CHARACTER # 
        ITEM NXTCHARU   U(00,54,06); # NEXT CHARACTER IN BINARY # 
        END 
  
      ITEM CHA        S:CH;          # CURRENT CHARACTER #
      ITEM COLUMN     U;             # CURRENT COLUMN # 
      ITEM CURSTATE   S:PARSESTATE;  # CURRENT STATE #
      ITEM CURTOKTYPE S:TOKENTYPE;   # CURRENT TOKEN TYPE # 
      ITEM INTEG      I;             # INTEGER VALUE #
      ITEM NEXTSTATE  S:PARSESTATE;  # NEXT STATE # 
  
        $BEGIN
        NAME("CMDPRSR");           # DEBUG CODE # 
        $END
  
      PARM$PCNT  = MXPARMS; 
      ASLONGAS PARM$PCNT NE 0 
      DO
        BEGIN 
        PARM$KEY[PARM$PCNT] = " ";
        PARM$VTYPE[PARM$PCNT] = S"DEFAULT"; 
        PARM$NAME[PARM$PCNT] = " "; 
        PARM$PLEN[PARM$PCNT] = 0; 
        PARM$VLEN[PARM$PCNT] = 0; 
        PARM$PCNT = PARM$PCNT - 1;
        END 
  
      PARM$VERB  = " ";            # NO VERB #
      PARM$VERBL = 0;              # VERB LENGTH #
      COLUMN = 0;                  # INITIAL COLUMN # 
      NEXTSTATE = S"START";        # INITIAL STATE #
      ASLONGAS NEXTSTATE NE S"HALT" 
      DO
        BEGIN 
        CURSTATE = NEXTSTATE; 
        CHARNXT = C<COLUMN,2>COMMAND; 
        IF CHARU GT CH"OTHER" 
        THEN
          BEGIN 
          CHA = S"OTHER"; 
          END 
  
        ELSE
          BEGIN 
          CHA = CHARU;
          END 
  
        CURTOKTYPE = S"SPACE";
        ASLONGAS B<CHA,01>CHTOKENSET[CURTOKTYPE] NE 1 
        DO
          BEGIN 
          CURTOKTYPE = CURTOKTYPE + 1;
          END 
  
        IF (CURTOKTYPE EQ S"TERMINATOR")
        THEN
          BEGIN 
          IF (CHARNXT EQ "..")
          THEN
            BEGIN 
            COLUMN = COLUMN + 1;   # SKIP OVER EXTRA CHARACTER #
            CURTOKTYPE = S"ELLIPSIS"; 
            END 
  
          ELSE
            BEGIN 
            IF (CHARU EQ 0) 
              AND (NXTCHARU NE 0)  # IF NOT ZERO-BYTE # 
            THEN
              BEGIN 
              CURTOKTYPE = S"OTHER";
              END 
  
            END 
  
          END 
  
        NEXTSTATE = B<CURTOKTYPE*6,6>PAR$NXT[CURSTATE]; 
        GOTO SW$ACT[B<CURTOKTYPE*6,6>PAR$ACT[CURSTATE] ]; 
  
SW$NOTHING:                        # DO NOTHING # 
          GOTO SW$END;
  
SW$STARTVE:                        # STARTING VERB #
          PARM$VERB = CHAR; 
          PARM$VERBL = 1; 
          GOTO SW$END;
  
SW$VERB:                           # STORE NEXT CHARACTER OF VERB # 
          IF PARM$VERBL LT MXTKLEN
          THEN
            BEGIN 
            C<PARM$VERBL,1>PARM$VERB = CHAR;
            END 
  
          PARM$VERBL = PARM$VERBL + 1;
          GOTO SW$END;
  
SW$STARTKE:                        # STARTING KEYWORD/NAME #
          IF PARM$PCNT EQ MXPARMS 
          THEN
            BEGIN 
            GOTO SW$MXPARS; 
            END 
  
          PARM$PCNT = PARM$PCNT + 1;
          PARM$COL[PARM$PCNT] = COLUMN + 1; 
          PARM$KEY[PARM$PCNT] = CHAR; 
          PARM$PLEN[PARM$PCNT] = 1; 
          GOTO SW$END;
  
SW$KEYWORD:                        # STORE NEXT CHARACTER OF KEY/NAME # 
          IF PARM$PLEN[PARM$PCNT] LT MXTKLEN
          THEN
            BEGIN 
            C<PARM$PLEN[PARM$PCNT],1>PARM$KEY[PARM$PCNT] = CHAR;
            END 
  
          PARM$PLEN[PARM$PCNT] = PARM$PLEN[PARM$PCNT] + 1;
          GOTO SW$END;
  
SW$KWEQUAL:                        # DECREMENT PARAMETER COUNT #
  
                                   # NOTE, PARAMETER COUNT WAS #
                                   # INCREMENTED AT THE START OF #
                                   # THE KEYWORD.  WE NOW HAVE #
                                   # RECOGNIZED AN EQUAL (KW=). # 
                                   # DECREMENT PARAMETER COUNT #
                                   # SINCE START OF VALUE PART #
                                   # (INCLUDING EMPTY VALUE) WILL # 
                                   # INCREMENT PARAMETER COUNT. # 
  
          PARM$PCNT = PARM$PCNT - 1;
          GOTO SW$END;
  
SW$STARTNA:                        # STARTING NAME OR INTEGER VALUE # 
          IF PARM$PCNT EQ MXPARMS 
          THEN
            BEGIN 
            GOTO SW$MXPARS; 
            END 
  
          PARM$PCNT = PARM$PCNT + 1;
          PARM$COL[PARM$PCNT] = COLUMN + 1; 
          PARM$NAME[PARM$PCNT] = CHAR;
          PARM$VLEN[PARM$PCNT] = 1; 
          PARM$VTYPE[PARM$PCNT] = S"NAME";
          GOTO SW$END;
  
SW$NAME:                           # STORE NEXT CHARACTER OF NAME # 
          IF PARM$VLEN[PARM$PCNT] LT MXTKLEN
          THEN
            BEGIN 
            C<PARM$VLEN[PARM$PCNT],1>PARM$NAME[PARM$PCNT] = CHAR; 
            END 
  
          PARM$VLEN[PARM$PCNT] = PARM$VLEN[PARM$PCNT] + 1;
          GOTO SW$END;
  
SW$CONVERI:                        # CONVERT NAME TO BINARY INTEGER # 
          IF XDXB(PARM$NAME[PARM$PCNT], 1, INTEG) 
          THEN
            BEGIN 
            PARM$INT[PARM$PCNT] = 0;
            END 
  
          ELSE
            BEGIN 
            PARM$INT[PARM$PCNT] = INTEG;
            END 
  
          PARM$VTYPE[PARM$PCNT] = S"INTEGER"; 
          GOTO SW$END;
  
SW$STARTRA:                        # START UPPER BOUND OF RANGE # 
          PARM$LB[PARM$PCNT] = PARM$INT[PARM$PCNT]; 
          PARM$UB[PARM$PCNT] = CHARU - O"33"; 
          PARM$VLEN[PARM$PCNT] = PARM$VLEN[PARM$PCNT] + 2;
          PARM$VTYPE[PARM$PCNT] = S"RANGE"; 
          GOTO SW$END;
  
SW$RANGE:                          # ADD DIGIT TO UPPER BOUND # 
          PARM$UB[PARM$PCNT] = (10*PARM$UB[PARM$PCNT]) + (CHARU-O"33"); 
          PARM$VLEN[PARM$PCNT] = PARM$VLEN[PARM$PCNT] + 1;
          GOTO SW$END;
  
SW$ASTERVA:                        # STORE ASTERISK VALUE # 
          IF PARM$PCNT EQ MXPARMS 
          THEN
            BEGIN 
            GOTO SW$MXPARS; 
            END 
  
          PARM$PCNT = PARM$PCNT + 1;
          PARM$COL[PARM$PCNT] = COLUMN + 1; 
          PARM$VLEN[PARM$PCNT] = 1; 
          PARM$NAME[PARM$PCNT] = CHAR;
          PARM$VTYPE[PARM$PCNT] = S"ASTERISK";
          GOTO SW$END;
  
SW$KEYWVAL:                        # STORE KEYWORD ONLY VALUE # 
          PARM$VLEN[PARM$PCNT] = PARM$PLEN[PARM$PCNT];
          PARM$NAME[PARM$PCNT] = PARM$KEY[PARM$PCNT]; 
          PARM$VTYPE[PARM$PCNT] = S"KEYWORD"; 
          GOTO SW$END;
  
SW$EMPTYVA:                        # STORE EMPTY VALUE (KW=) #
          IF PARM$PCNT EQ MXPARMS 
          THEN
            BEGIN 
            GOTO SW$MXPARS; 
            END 
  
          PARM$PCNT = PARM$PCNT + 1;
          PARM$VTYPE[PARM$PCNT] = S"EMPTY"; 
          GOTO SW$END;
  
SW$DEFVALU:                        # STORE DEFAULT VALUE #
          IF PARM$PCNT EQ MXPARMS 
          THEN
            BEGIN 
            GOTO SW$MXPARS; 
            END 
  
          PARM$PCNT = PARM$PCNT + 1;
          PARM$COL[PARM$PCNT] = COLUMN + 1; 
          PARM$VTYPE[PARM$PCNT] = S"DEFAULT"; 
          GOTO SW$END;
  
SW$MXPARS:                         # TOO MANY PARAMETERS PARSED # 
          NEXTSTATE = S"HALT";     # STOP PARSING # 
          CURTOKTYPE = S"OTHER";   # FORCE INVALID CHARACTER ERROR #
          GOTO SW$END;
  
SW$END:                            # END OF CASE #
        COLUMN = COLUMN + 1;
        END                        # ASLONGAS # 
  
      PARM$STAT = B<CURTOKTYPE*6,6>PAR$STA[CURSTATE]; 
      PARM$ECOL = COLUMN;          # COLUMN STARTING FROM 1 # 
      ASLONGAS (COLUMN LT MXCMD)   # NOT END OF STRING #
           AND (CHARNXTU NE 0)     # NO ZERO-BYTE # 
      DO
        BEGIN 
        CHARNXT = C<COLUMN,2>COMMAND; 
        COLUMN = COLUMN + 1;
        END 
  
      PARM$CMDL = COLUMN;          # LENGTH OF COMMAND #
      IF (CHARNXTU EQ 0)
        AND (COLUMN LE MXCMD) 
      THEN
        BEGIN 
        COLUMN = COLUMN - 1;
        C<COLUMN,MXCMD-COLUMN>COMMAND = " ";  # BLANK-FILL COMMAND #
        END 
  
      END  # CMDPRSR #
    TERM
