*DECK FCSRPUC 
USETEXT TEXTFCS;
      PROC FCSRPUC; 
*CALL COPYRITE
# TITLE FCSRPUC - PARSE USER COMMAND.                                  #
  
      BEGIN                            # FCSRPUC                       #
  
# 
**    FCSRPUC - PARSE USER COMMAND. 
* 
*     C. J. RAMSAY                     87/11/03 
* 
*     THIS PROCEDURE PARSES THE CURRENT USER COMMAND. 
* 
*     PROC FCSRPUC
* 
*     ENTRY   USC        = BUFFER CONTAINING CURRENT COMMAND. 
*             USCLEN     = NUMBER OF OCTETS IN CURRENT COMMAND. 
* 
*     EXIT    FTPCOMMAND = COMMAND NUMBER IF PARSING SUCCESSFUL.
*                        = *CMDERROR* IF ERROR DETECTED.
*                        = *CMDNULL* IF NULL INPUT DETECTED.
*             PARMS      = COMMAND PARAMETERS IF PARSING SUCCESSFUL.
* 
*     METHOD  A USER COMMAND CONSISTS OF A COMMAND NAME AND ZERO
*             OR MORE PARAMETERS SEPARATED BY A SPACE OR A COMMA. 
*             PARAMETERS MAY TAKE THE FORM OF A PARAMETER NAME, AN
*             EQUAL SIGN AND THE PARAMETER VALUE, OR MAY CONSIST
*             OF JUST THE PARAMETER VALUE BY ITSELF (POSITIONAL). 
* 
*             OPTIONAL COMMENTS MAY BE PRESENT IN A USER COMMAND
*             AND ARE DELIMITED BY DOUBLE QUOTES. THESE COMMENTS
*             ARE IGNORED AS ARE ANY LEADING, EMBEDDED OR TRAILING
*             SPACES ENCOUNTERED. 
* 
*             EACH ELEMENT OF THE USER COMMAND (COMMAND NAME, 
*             PARAMETER NAME, AND PARAMETER VALUE) IS REFERRED TO 
*             AS A TOKEN. FROM THE ABOVE ONE CAN SEE THAT A TOKEN 
*             CANNOT CONTAIN THE CHARACTERS SPACE, DOUBLE QUOTE,
*             COMMA, (OR EQUAL SIGN FOR A POSITIONAL PARAMETER).
*             TO SPECIFY THESE CHARACTERS THE FIRST CHARACTER OF
*             THE TOKEN MUST BE AN APOSTROPHE AND THE TOKEN WILL
*             CONSIST OF ALL CHARACTERS UP TO THE DELIMITING
*             APOSTROPHE AND ANY FOLLOWING CHARACTERS UP TO THE 
*             TOKEN SEPARATOR. IN THIS MODE THE APOSTROPHE CHARACTER
*             IS REPRESENTED BY TWO CONSECUTIVE APOSTROPHE CHARACTERS.
* 
*             PARAMETER VALUES MAY BE OF THE FOLLOWING TYPES: 
*              *PTNAME*     VALUE IS 1 - 60 CASE SENSITIVE CHARACTERS.
*              *PTUNAME*    VALUE IS 1 - 60 CASE SENSITIVE CHARACTERS.
*              *PTFILE*     VALUE IS A VALID NOS FILE NAME. 
*              *PTBOOLEAN*  VALUE IS A BOOLEAN CONSTANT.
*              *PTKEYWORD*  VALUE IS A KEYWORD OF 1 - 10 CHARACTERS.
* 
*             THE PARSING IS TABLE DRIVEN BASED ON COMMAND AND PARAMETER
*             TABLES INITIALIZED BY THE ROUTINE *FCSIICT*.
* 
# 
  
# 
****  PROC FCSRPUC - XREF LIST
# 
      XREF
        BEGIN 
        PROC FCSOWOF;                  # WRITE TO OUTPUT FILE          #
        FUNC FCSUVFN B;                # VALIDATE NOS FILE NAME        #
        PROC MOVE;                     # MOVE A NUMBER OF WORDS        #
        PROC NETUCAC;                  # COPY AN ASCII CHARACTER       #
        PROC NETUCAD;                  # CONVERT ASCII TO DISPLAY CODE #
        PROC NETUCAS;                  # COPY AN ASCII STRING          #
        PROC NETUCDA;                  # CONVERT DISPLAY CODE TO ASCII #
        PROC NETUCLR;                  # CLEAR AN AREA OF MEMORY       #
        END 
# 
****
# 
      ITEM USCIND        I;            # CURRENT INDEX INTO COMMAND    #
      ITEM I             I;            # LOOP INDUCTION VARIABLE       #
      ITEM J             I;            # LOOP INDUCTION VARIABLE       #
      ITEM K             I;            # LOOP INDUCTION VARIABLE       #
      ITEM L             I;            # LOOP INDUCTION VARIABLE       #
      ITEM PNUM          I;            # INDEX INTO DESCRIPTOR TABLE   #
      ITEM PPOS          I;            # INDEX INTO PARAMETER BLOCKS   #
      ITEM PPTR          I;            # INDEX FIRST PARAMETER FOR CMD #
      ITEM PSIZ          I;            # NUMBER OF PARAMETERS FOR CMD  #
      ITEM SEPARATOR     U;            # SEPARATOR AFTER TOKEN         #
  
      ITEM CRLF          U = X"0D0A00000000000";
      ITEM PERIOD        U = X"2E0000000000000";
  
      ARRAY TOKEN [00:00] S(PARSIZ$);  # CURRENT ASSEMBLED TOKEN       #
        BEGIN 
        ITEM TKN$ABBR    C(00,00,20);  # ABBREVIATED NAME (15 OCTETS)  #
        ITEM TKN$NAME    C(00,00,40);  # FULL NAME (30 OCTETS)         #
        ITEM TKN$LEN     U(S$,00,60);  # TOKEN SIZE IN OCTETS          #
        END 
  
      ARRAY LOWER [00:00] S(PARSIZ$);  # TOKEN IN UPPER + LOWER CASE   #
        BEGIN 
        ITEM LWR$WORD    U(00,00,60);  # FULL WORD REFERENCE           #
        ITEM LWR$LEN     U(S$,00,60);  # TOKEN SIZE IN OCTETS          #
        END 
  
      ARRAY THISCHAR [00:00] S(1);     # CURRENT CHARACTER             #
        BEGIN 
        ITEM THISCHR     U(00,00,08); 
        END 
  
      DEF LBIGTKN        # 46 #;
      DEF LNOTERM        # 56 #;
      DEF LUNKCMD        # 28 #;
      DEF LTOOPAR        # 41 #;
      DEF LUNKPAR        # 30 #;
      DEF LMISVAL        # 40 #;
      DEF LDUPPAR        # 47 #;
      DEF LNOSVAL        # 62 #;
      DEF LBOOVAL        # 59 #;
      DEF LKEYVAL        # 63 #;
      DEF LRQDVAL        # 50 #;
  
      ARRAY EBIGTKN [00:00] S(5); 
        BEGIN 
        ITEM TBIGTKN     C(00,00,LBIGTKN) = 
       ["--ERROR--  COMMAND NAME OR PARAMETER TOO LONG."];
        ITEM ZBIGTKN     U(04,36,24) = [0]; 
        END 
  
      ARRAY ENOTERM [00:00] S(6); 
        BEGIN 
        ITEM TNOTERM     C(00,00,LNOTERM) = 
       ["--ERROR--  STRING MUST BE TERMINATED WITH AN APOSTROPHE."];
        ITEM ZNOTERM     U(05,36,24) = [0]; 
        END 
  
      ARRAY ETOOPAR [00:00] S(5); 
        BEGIN 
        ITEM TTOOPAR     C(00,00,LTOOPAR) = 
       ["--ERROR--  TOO MANY PARAMETERS SPECIFIED."]; 
        ITEM ZTOOPAR     U(04,06,54) = [0]; 
        END 
  
      ITEM EUNKCMD       C(LUNKCMD) = 
      "--ERROR--  UNKNOWN COMMAND, "; 
  
      ITEM EUNKPAR       C(LUNKPAR) = 
      "--ERROR--  UNKNOWN PARAMETER, "; 
  
      ITEM EMISVAL       C(LMISVAL) = 
      "--ERROR--  VALUE MISSING FOR PARAMETER, "; 
  
      ITEM EDUPPAR       C(LDUPPAR) = 
      "--ERROR--  DUPLICATE DECLARATION OF PARAMETER, ";
  
      ITEM ENOSVAL       C(LNOSVAL) = 
      "--ERROR--  VALUE MUST BE A VALID NOS FILE NAME FOR PARAMETER, "; 
  
      ITEM EBOOVAL       C(LBOOVAL) = 
      "--ERROR--  VALUE MUST BE A BOOLEAN CONSTANT FOR PARAMETER, ";
  
      ITEM EKEYVAL       C(LKEYVAL) = 
      "--ERROR--  VALUE MUST BE TEN CHARACTERS OR LESS FOR PARAMETER, ";
  
      ITEM ERQDVAL       C(LRQDVAL) = 
      "--ERROR--  VALUE MUST BE SPECIFIED FOR PARAMETER, "; 
      CONTROL EJECT;
      PROC FCS2WEM (EMESS, LMESS);
      BEGIN                            # FCS2WEM                       #
# 
*     INTERNAL PROCEDURE - FCS2WEM
* 
*     THIS EMBEDDED PROCEDURE WRITES AN ERROR MESSAGE TO THE
*     OUTPUT FILE. EACH MESSAGE CONSISTS OF A DISPLAY CODE ERROR
*     MESSAGE FOLLOWED BY THE PARAMETER NAME THE ERROR APPLIES TO.
*     IF NO PARAMETER NAME APPLIES THEN THE ERROR MESSAGE IS FOLLOWED 
*     BY THE CURRENT ASSEMBLED TOKEN. 
* 
# 
      ITEM EMESS         C(40);        # DISPLAY CODE ERROR MESSAGE    #
      ITEM LMESS         I;            # LENGTH OF ERROR MESSAGE       #
  
      OUTLEN = 0;                      # INITIALIZE MESSAGE LENGTH     #
      NETUCDA (EMESS, 0, LMESS, 
               OUTBUF, OUTLEN, FALSE); # COPY DISPLAY CODE MESSAGE     #
  
      IF PNUM EQ 0
      THEN
        BEGIN                          # NO VALID PARAMETER            #
        NETUCAS (LOWER, 0, LWR$LEN, 
                 OUTBUF, OUTLEN);      # COPY FROM CURRENT TOKEN       #
        END 
      ELSE
        BEGIN                          # VALID PARAMETER               #
        NETUCAS (FCS$PNT[PNUM], 0, PNT$SIZE[PNUM],
                 OUTBUF, OUTLEN);      # COPY FROM PARAMETER NAME TABLE#
        END 
  
      NETUCAC (PERIOD, 0, 
               OUTBUF, OUTLEN);        # COPY PERIOD                   #
      NETUCAS (CRLF, 0, 2,
               OUTBUF, OUTLEN);        # COPY CR + LF                  #
      FCSOWOF (OUTBUF, OUTLEN);        # WRITE TO OUTPUT FILE          #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2WEM                       #
      CONTROL EJECT;
      PROC FCS2GNC; 
      BEGIN                            # FCS2GNC                       #
# 
*     INTERNAL PROCEDURE - FCS2GNC
* 
*     THIS EMBEDDED PROCEDURE GETS THE NEXT CHARACTER.
* 
# 
  
      L = 0;
      NETUCAC (USC[0], USCIND,
               THISCHAR, L);           # GET NEXT CHARACTER            #
      USCIND = USCIND + 1;             # INCREMENT COMMAND INDEX       #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2GNC                       #
      CONTROL EJECT;
      PROC FCS2SCC; 
      BEGIN                            # FCS2SCC                       #
# 
*     INTERNAL PROCEDURE - FCS2SCC
* 
*     THIS EMBEDDED PROCEDURE STORES THE CURRENT CHARACTER. 
* 
# 
  
      IF TKN$LEN EQ PARMAX$ 
      THEN
        BEGIN                          # TOO MANY CHARACTERS IN TOKEN  #
        FCSOWOF (EBIGTKN, INTERNAL$);  # WRITE TO OUTPUT FILE          #
        FTPCOMMAND = CMDERROR;         # RETURN ERROR STATUS           #
        GOTO FCSRPUCEND;               # GET OUT OF HERE QUICKLY       #
        END 
  
      L = LWR$LEN;
      NETUCAC (THISCHAR, 0, 
               LOWER, L);              # STORE CHARACTER OF TOKEN      #
      LWR$LEN = LWR$LEN + 1;           # UPDATE TOKEN LENGTH           #
  
      IF (THISCHR GQ ASCILA) AND
         (THISCHR LQ ASCILZ)
      THEN
        BEGIN                          # LOWER CASE CHARACTER          #
        THISCHR = THISCHR - X"20";     # CONVERT TO UPPER CASE         #
        END 
  
      L = TKN$LEN;
      NETUCAC (THISCHAR, 0, 
               TOKEN, L);              # STORE UPPER CASE TOKEN CHAR   #
      TKN$LEN = TKN$LEN + 1;           # UPDATE TOKEN LENGTH           #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2SCC                       #
      CONTROL EJECT;
      PROC FCS2SEC; 
      BEGIN                            # FCS2SEC                       #
# 
*     INTERNAL PROCEDURE - FCS2SEC
* 
*     THIS EMBEDDED PROCEDURE SKIPS TO THE END OF A COMMENT STRING. 
* 
# 
  
      THISCHR = ASCISPACE;             # SKIP CURRENT DOUBLE QUOTE     #
      FOR K = 1 
        WHILE (USCIND LQ USCLEN) AND
              (THISCHR NQ ASCIDBLQU) DO 
        BEGIN                          # TILL DOUBLE QUOTE OR END      #
        FCS2GNC;                       # GET NEXT CHARACTER            #
        END 
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2SEC                       #
      CONTROL EJECT;
      PROC FCS2SBC; 
      BEGIN                            # FCS2SBC                       #
# 
*     INTERNAL PROCEDURE - FCS2SBC
* 
*     THIS EMBEDDED PROCEDURE SKIPS ALL BLANKS AND COMMENTS.
* 
# 
      FOR K = 1 
        WHILE (USCIND LQ USCLEN) AND
              (THISCHR EQ ASCISPACE OR THISCHR EQ ASCIDBLQU) DO 
        BEGIN                          # END OR NON-BLANK + NOT COMMENT#
        IF THISCHR EQ ASCIDBLQU 
        THEN
          BEGIN                        # START OF COMMENT              #
          FCS2SEC;                     # SKIP TO END OF COMMENT        #
          END 
        FCS2GNC;                       # GET NEXT CHARACTER            #
        END 
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2SBC                       #
      CONTROL EJECT;
      PROC FCS2ANT (EQUALSEP);
      BEGIN                            # FCS2ANT                       #
# 
*     INTERNAL PROCEDURE - FCS2ANT
* 
*     THIS EMBEDDED PROCEDURE ASSEMBLES THE NEXT TOKEN STARTING FROM
*     *USCIND*. THE UPPER + LOWER CASE TOKEN IS PLACED IN THE ARRAY 
*     *LOWER* AND THE UPPER CASE VERSION IS PLACED IN THE ARRAY *TOKEN*.
*     TOKEN SEPARATOR CHARACTER IS PLACED IN THE VARIABLE *SEPARATOR*.
* 
# 
      ITEM EQUALSEP      B;            # EQUAL SIGN GOOD FOR SEPARATOR #
  
      NETUCLR (LOC(TOKEN), PARSIZ$);   # CLEAR TOKEN                   #
      NETUCLR (LOC(LOWER), PARSIZ$);   # CLEAR UPPER + LOWER VERSION   #
      FCS2GNC;                         # GET FIRST CHARACTER           #
      FCS2SBC;                         # SKIP PAST BLANKS + COMMENTS   #
      IF USCIND GR USCLEN 
      THEN
        BEGIN                          # AT END OF COMMAND LINE        #
        RETURN;                        # RETURN TO CALLER              #
        END 
# 
*     IF FIRST CHARACTER OF TOKEN IS AN APOSTROPHE THEN TOKEN COMPRISES 
*     ALL CHARACTERS UP TO THE NEXT APOSTROPHE. THE APOSTROPHE
*     CHARACTER IS REPRESENTED BY TWO CONSECUTIVE APOSTROPHES.
# 
      IF THISCHR EQ ASCIAPOSTP
      THEN
        BEGIN                          # FIRST CHARACTER AN APOSTROPHE #
        FOR K = 1 
          WHILE USCIND LS USCLEN DO 
          BEGIN                        # TILL APOSTROPHE OR END        #
          FCS2GNC;                     # GET NEXT CHARACTER            #
          IF THISCHR EQ ASCIAPOSTP
          THEN
            BEGIN                      # CURRENT CHARACTER = APOSTROPHE#
            IF USCIND EQ USCLEN 
            THEN
              BEGIN                    # AND END OF COMMAND            #
              USCIND = USCIND + 1;     # DEFINITELY END OF COMMAND     #
              RETURN;                  # COMPLETE TOKEN ASSEMBLED      #
              END 
            FCS2GNC;                   # GET NEXT CHARACTER            #
            IF THISCHR NQ ASCIAPOSTP
            THEN
              BEGIN                    # FOUND APOSTROPHE ENDING STRING#
              GOTO APOSTEND;           # GET OUT OF LOOP               #
              END 
            END 
          FCS2SCC;                     # STORE CURRENT CHARACTER       #
          END 
        FCSOWOF (ENOTERM, INTERNAL$);  # WRITE MESSAGE TO OUTPUT FILE  #
        FTPCOMMAND = CMDERROR;         # RETURN ERROR STATUS           #
        GOTO FCSRPUCEND;               # GET OUT OF HERE QUICKLY       #
        END 
APOSTEND: 
# 
*     ASSEMBLE ALL CHARACTERS OF TOKEN, DISCARDING ANY EMBEDDED 
*     COMMENTS. 
# 
      FOR K = 1 
        WHILE (USCIND LQ USCLEN) AND
              (THISCHR NQ ASCISPACE) AND
              (THISCHR NQ ASCICOMMA) AND
              (THISCHR NQ ASCIEQUAL OR NOT EQUALSEP) DO 
        BEGIN 
        IF THISCHR EQ ASCIDBLQU 
        THEN
          BEGIN                        # START OF COMMENT              #
          FCS2SEC;                     # SKIP TO END OF COMMENT        #
          END 
        ELSE
          BEGIN 
          FCS2SCC;                     # STORE CURRENT CHARACTER       #
          END 
        FCS2GNC;                       # GET NEXT CHARACTER            #
        END 
# 
*     DETERMINE SEPARATOR CHARACTER DISCARDING ANY EMBEDDED BLANKS OR 
*     COMMENTS. 
# 
      FCS2SBC;                         # SKIP PAST BLANKS + COMMENTS   #
      IF USCIND GR USCLEN 
      THEN
        BEGIN                          # END OF USER COMMAND           #
        THISCHR = ASCISPACE;           # DEFAULT SEPARATOR TO A SPACE  #
        END 
      IF (USCIND LQ USCLEN) AND 
         (THISCHR NQ ASCICOMMA) AND 
         (THISCHR NQ ASCIEQUAL OR NOT EQUALSEP) 
      THEN
        BEGIN                          # NOT *=* OR *,*  AS SEPARATOR  #
        THISCHR = ASCISPACE;           # DEFAULT SEPARATOR TO A SPACE  #
        USCIND  = USCIND - 1;          # BACK UP TO PREVIOUS CHARACTER #
        END 
      SEPARATOR = THISCHR;             # STORE SEPARATOR USED, IF ANY  #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2ANT                       #
      CONTROL EJECT;
# 
*     START MAIN PROCEDURE
# 
      USCIND = 0;                      # INITIALIZE COMMAND INDEX      #
      PNUM   = 0;                      # PARAMETER NOT APPLICABLE      #
# 
*     PARSE THE COMMAND NAME, AND RETURN NULL INPUT IF NO TOKEN 
*     ASSEMBLED.
# 
      FCS2ANT (FALSE);                 # ASSEMBLE TOKEN OF COMMAND     #
      IF (USCIND GR USCLEN) AND 
         (TKN$LEN EQ 0) 
      THEN
        BEGIN                          # ONLY BLANKS AND/OR COMMENT    #
        FTPCOMMAND = CMDNULL;          # NULL INPUT FOR COMMAND        #
        GOTO FCSRPUCEND;               # GET OUT OF HERE QUICKLY       #
        END 
# 
*     SEARCH FOR MATCHING ENTRY IN COMMAND DESCRIPTOR TABLE OR COMMAND
*     NAME TABLE, AND RETURN COMMAND ERROR IF ENTRY NOT FOUND.
# 
      FTPCOMMAND = CMDERROR;           # INITIALIZE COMMAND NOT FOUND  #
      FOR I = 1 STEP 1
        WHILE (I LQ CDTSIZ$) AND
              (FTPCOMMAND EQ CMDERROR) DO 
        BEGIN                          # LOOP COMMAND DESCRIPTOR TABLE #
        IF TKN$ABBR EQ CDT$NAME[I]
        THEN
          BEGIN                        # MATCHING COMMAND NAME         #
          FTPCOMMAND = CDT$CNUM[I];    # PICK UP COMMAND NUMBER        #
          END 
        END 
      FOR I = 1 STEP 1
        WHILE (I LQ CNTSIZ$) AND
              (FTPCOMMAND EQ CMDERROR) DO 
        BEGIN                          # LOOP COMMAND NAME TABLE       #
        IF TKN$NAME EQ CNT$NAME[I]
        THEN
          BEGIN                        # MATCHING COMMAND NAME         #
          FTPCOMMAND = CDT$CNUM[I];    # PICK UP COMMAND NUMBER        #
          END 
        END 
      IF FTPCOMMAND EQ CMDERROR 
      THEN
        BEGIN                          # COMMAND NOT RECOGNIZED        #
        FCS2WEM (EUNKCMD, LUNKCMD);    # WRITE MESSAGE TO OUTPUT FILE  #
        GOTO FCSRPUCEND;               # GET OUT OF HERE QUICKLY       #
        END 
# 
*     FOR EACH POSSIBLE PARAMETER INITIALIZE ITS PARAMETER BLOCK AND
*     RESET THE PARAMETER SEEN FLAG.
# 
      NETUCLR (LOC(PARMS[1]), 
               MAXPARMS$ * PARSIZ$);   # CLEAR ALL PARAMETER BLOCKS    #
      PPTR = CDT$PPTR[FTPCOMMAND];     # INDEX OF FIRST PARAMETER      #
      PSIZ = CDT$PSIZ[FTPCOMMAND];     # NUMBER OF PARAMETERS          #
      FOR PNUM = PPTR STEP 1
        WHILE PNUM LS PPTR + PSIZ DO
        BEGIN                          # LOOP THRU ALL PARAMETERS      #
        PDT$SEEN[PNUM] = FALSE;        # RESET PARAMETER SEEN  #
        END 
# 
*     PARSE ALL PARAMETERS OF THE COMMAND.
# 
      PPOS = 0;                        # INITIALIZE PARAMETER POSITION #
      FOR J = 1 STEP 1
        WHILE USCIND LQ USCLEN DO 
        BEGIN                          # LOOP THRU REMAINDER OF COMMAND#
        FCS2ANT (TRUE);                # ASSEMBLE NEXT TOKEN           #
        IF (USCIND GR USCLEN) AND 
           (TKN$LEN EQ 0) 
        THEN
          BEGIN                        # NO FURTHER PARAMETERS         #
          TEST J;                      # EXIT PARAMETER PARSING        #
          END 
# 
*     SEARCH FOR MATCHING ENTRY IN PARAMETER DESCRIPTOR TABLE OR
*     PARAMETER NAME TABLE. 
# 
        PNUM = 0;                      # PARAMETER NOT FOUND           #
        FOR I = PPTR STEP 1 
          WHILE (I LS PPTR + PSIZ) AND
                (PNUM EQ 0) DO
          BEGIN                        # LOOP PARAMETER DESCRIPTOR TBL #
          IF TKN$ABBR EQ PDT$NAME[I]
          THEN
            BEGIN                      # MATCHING PARAMETER NAME       #
            PNUM = I;                  # PICK UP PARAMETER NUMBER      #
            END 
          END 
        FOR I = PPTR STEP 1 
          WHILE (I LS PPTR + PSIZ) AND
                (PNUM EQ 0) DO
          BEGIN                        # LOOP PARAMETER NAME TABLE     #
          IF TKN$NAME EQ PNT$NAME[I]
          THEN
            BEGIN                      # MATCHING PARAMETER NAME       #
            PNUM = I;                  # PICK UP PARAMETER NUMBER      #
            END 
          END 
# 
*     VALIDATE PARAMETER NAME AND/OR EVALUATE PARAMETER POSITION. 
# 
        IF (PNUM EQ 0) AND
           (SEPARATOR EQ ASCIEQUAL) 
        THEN
          BEGIN                        # UNRECOGNIZED PARAMETER = VALUE#
          FCS2WEM (EUNKPAR, LUNKPAR);  # WRITE MESSAGE TO OUTPUT FILE  #
          FTPCOMMAND = CMDERROR;       # RETURN ERROR STATUS           #
          GOTO FCSRPUCEND;             # GET OUT OF HERE QUICKLY       #
          END 
  
        IF SEPARATOR EQ ASCIEQUAL 
        THEN
          BEGIN                        # RECOGNIZED PARAMETER = VALUE  #
          PPOS = PNUM - PPTR + 1;      # DETERMINE PARAMETER POSITION  #
          FCS2ANT (FALSE);             # ASSEMBLE VALUE TOKEN          #
          IF TKN$LEN EQ 0 
          THEN
            BEGIN                      # NO VALUE SPECIFIED            #
            FCS2WEM (EMISVAL, LMISVAL);# WRITE MESSAGE TO OUTPUT FILE  #
            FTPCOMMAND = CMDERROR;     # RETURN ERROR STATUS           #
            GOTO FCSRPUCEND;           # GET OUT OF HERE QUICKLY       #
            END 
          END 
        ELSE
          BEGIN                        # POSITIONAL PARAMETER          #
          PPOS = PPOS + 1;             # DETERMINE PARAMETER POSITION  #
          PNUM = PPTR + PPOS - 1;      # DETERMINE PARAMETER NUMBER    #
          IF PPOS GR PSIZ 
          THEN
            BEGIN                      # TOO MANY PARAMETERS           #
            FCSOWOF (ETOOPAR, 
                     INTERNAL$);       # WRITE MESSAGE TO OUTPUT FILE  #
            FTPCOMMAND = CMDERROR;     # RETURN ERROR STATUS           #
            GOTO FCSRPUCEND;           # GET OUT OF HERE QUICKLY       #
            END 
          IF TKN$LEN EQ 0 
          THEN
            BEGIN                      # NO VALUE SPECIFIED            #
            TEST J;                    # ADVANCE TO NEXT PARAMETER     #
            END 
          END 
# 
*     CHECK FOR DUPLICATE PARAMETER SPECIFICATION.
# 
        IF PDT$SEEN[PNUM] 
        THEN
          BEGIN                        # PARAMETER ALREADY DETECTED    #
          FCS2WEM (EDUPPAR, LDUPPAR);  # WRITE MESSAGE TO OUTPUT FILE  #
          FTPCOMMAND = CMDERROR;       # RETURN ERROR STATUS           #
          GOTO FCSRPUCEND;             # GET OUT OF HERE QUICKLY       #
          END 
        PDT$SEEN[PNUM] = TRUE;         # FLAG PARAMETER DETECTED       #
# 
*     PARSE PARAMETER VALUE.
# 
        MOVE (PARSIZ$, LOWER,          # PARAMETER VALUE CASE SENSITIVE#
              PARMS[PPOS]);            # MOVE VALUE + SIZE INTO BLOCK  #
# 
*     PARAMETER TYPE IS 1 - 60 CASE INSENSITIVE CHARACTERS. 
# 
        IF PDT$TYPE[PNUM] EQ PTUNAME
        THEN
          BEGIN                        # PARAMETER TYPE IS *PTUNAME*   #
          MOVE (PARSIZ$, TOKEN,        # PARAM VALUE NOT CASE SENSITIVE#
                PARMS[PPOS]);          # MOVE VALUE + SIZE INTO BLOCK  #
          END 
# 
*     PARAMETER TYPE IS A VALID NOS FILE NAME.
# 
        ELSE IF PDT$TYPE[PNUM] EQ PTFILE
        THEN
          BEGIN                        # PARAMETER TYPE IS *PTFILE*    #
          IF NOT FCSUVFN (PARMS[PPOS])
          THEN
            BEGIN                      # NOT VALID NOS FILE NAME       #
            FCS2WEM (ENOSVAL, LNOSVAL);# WRITE MESSAGE TO OUTPUT FILE  #
            FTPCOMMAND = CMDERROR;     # RETURN ERROR STATUS           #
            GOTO FCSRPUCEND;           # GET OUT OF HERE QUICKLY       #
            END 
          END 
# 
*     PARAMETER TYPE IS A BOOLEAN CONSTANT. 
# 
        ELSE IF PDT$TYPE[PNUM] EQ PTBOOLEAN 
        THEN
          BEGIN                        # PARAMETER TYPE IS *PTBOOLEAN* #
          MOVE (PARSIZ$, TOKEN,        # PARAM VALUE NOT CASE SENSITIVE#
                PARMS[PPOS]);          # MOVE VALUE + SIZE INTO BLOCK  #
          IF (PARAM[PPOS] EQ PARON$) OR 
             (PARAM[PPOS] EQ PARTRUE$) OR 
             (PARAM[PPOS] EQ PARYES$) 
          THEN
            BEGIN                      # *ON* OR *TRUE* OR *YES*       #
            PARAMNB[PPOS] = OPTON$;    # STORE DISPLAY CODE *ON*       #
            END 
          ELSE IF (PARAM[PPOS] EQ PAROFF$) OR 
                  (PARAM[PPOS] EQ PARFALSE$) OR 
                  (PARAM[PPOS] EQ PARNO$) 
          THEN
            BEGIN                      # *OFF* OR *FALSE* OR *NO*      #
            PARAMNB[PPOS] = OPTOFF$;   # STORE DISPLAY CODE *OFF*      #
            END 
          ELSE
            BEGIN                      # NOT VALID BOOLEAN VALUE       #
            FCS2WEM (EBOOVAL, LBOOVAL);# WRITE MESSAGE TO OUTPUT FILE  #
            FTPCOMMAND = CMDERROR;     # RETURN ERROR STATUS           #
            GOTO FCSRPUCEND;           # GET OUT OF HERE QUICKLY       #
            END 
          END 
# 
*     PARAMETER TYPE IS A KEYWORD OF 1 - 10 CHARACTERS. 
# 
        ELSE IF PDT$TYPE[PNUM] EQ PTKEYWORD 
        THEN
          BEGIN                        # PARAMETER TYPE IS *PTKEYWORD* #
          IF TKN$LEN GR 10
          THEN
            BEGIN                      # TOO MANY CHARACTERS           #
            FCS2WEM (EKEYVAL, LKEYVAL);# WRITE TO OUTPUT FILE          #
            FTPCOMMAND = CMDERROR;     # RETURN ERROR STATUS           #
            GOTO FCSRPUCEND;           # GET OUT OF HERE QUICKLY       #
            END 
          PARAMNB[PPOS] = "          ";# BLANK FILL PARAMETER          #
          P<TBUF> = LOC(PARAMNB[PPOS]);# POINTER TO PARAMETER VALUE    #
          L = 0;                       # CONVERT TO DISPLAY CODE       #
          NETUCAD (TOKEN, 0, TKN$LEN, 
                   TBUF, L);
          END 
        END 
# 
*     COMMAND, PARAMETER NAMES AND PARAMETER VALUES PARSED SUCCESSFULLY.
*     CHECK THAT ALL REQUIRED PARAMETERS HAVE BEEN SPECIFIED. 
# 
      FOR PNUM = PPTR STEP 1
        WHILE PNUM LS PPTR + PSIZ DO
        BEGIN                          # LOOP THRU ALL PARAMETERS      #
        IF (PDT$REQD[PNUM] EQ RQYES) AND
           (NOT PDT$SEEN[PNUM]) 
        THEN
          BEGIN                        # REQUIRED PARAMETER MISSING    #
          FCS2WEM (ERQDVAL, LRQDVAL);  # WRITE MESSAGE TO OUTPUT FILE  #
          FTPCOMMAND = CMDERROR;       # RETURN ERROR STATUS           #
          GOTO FCSRPUCEND;             # GET OUT OF HERE QUICKLY       #
          END 
        END 
  
FCSRPUCEND: 
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCSRPUC                       #
  
      TERM
