*DECK FFSICCC 
PROC FFSICCC(PARM$ARRAY,PDT$ARRAY,NUMPARMS,PROGNAME,COMMENT); 
*CALL COPYRITE
# TITLE FFSICCC - CONTROL CARD CRACKING PROCEDURE.                     #
  
      BEGIN                            # FFSICCC                       #
  
# 
****  FFSICCC - CONTROL CARD CRACKING PROCEDURE.
* 
*     R. A. MANN   84/12/04.
* 
*     THIS PROCEDURE CRACKS THE PARAMETERS PASSED ON THE CONTROL
*     STATEMENT.  A PARAMETER DESCRIPTOR ARRAY IS UTILIZED TO DEFINE
*     ALLOWABLE PARAMETERS AND ASSOCIATED ASPECTS OF EACH PARAMETER.
* 
*     ENTRY        PDT$ARRAY - PARAMETER DESCRIPTION ARRAY
*                  NUMPARMS -  NUMBER OF PARAMETERS IN PDT$ARRAY
*                  PROGNAME  - NAME OF CALLING PROGRAM
* 
*     EXIT         PARM$ARRAY - VALUES FOR EACH PARAMETER IN PDT$ARRAY
*                            ARE STORED IN PARM$ARRAY ALONG WITH A FLAG 
*                            INDICATING IF THE VALUE WAS USER SPECIFIED 
*                            OR A DEFAULT VALUE.
* 
*                  COMMENT   - ANY USER SUPPLIED COMMENT ON CONTROL CARD
# 
  
# 
****  PRGM FFSICCC - XREF LIST. 
# 
  
      XREF
        BEGIN 
        PROC ABORT;          # MACREL - ABORT CONTROL POINT            #
        PROC MESSAGE;        # MACREL - ISSUE DAYFILE MESSAGE          #
        FUNC FFSUVFN B;      # VALIDATE FILE NAME                      #
        FUNC FFSUVUN B;      # VALIDATE USER NAME                      #
        END 
  
# 
****
# 
CONTROL EJECT;
  
# 
*     PARAMETERS TO FFSICCC 
# 
      DEF NUMPARAMS # 1 #;   # NEEDED FOR COMMON DECK ARRAY EXTENT     #
# 
*     PARM$ARRAY - THIS ARRAY WILL CONTAIN VALID VALUES FOR EACH
*     PARAMETER SPECIFIED IN PDT$ARRAY. THE LOCATION OF VALUES IN 
*     THIS ARRAY CORRESPOND TO THE POSITION OF THE PARAMETERS IN
*     PDT$ARRAY.
* 
*     EACH ENTRY CONSISTS OF TWO WORDS. 
*     THE FIRST WORD IS THE VALUE VALUE OF THE PARAMETER. 
*     THE SECOND WORD CONTAINS TWO VALUES.  THE RIGHTMOST THIRTY BITS 
*     ARE A BOOLEAN INDICATING IF THE VALUE IN WORD ONE WAS USER
*     SPECIFIED (TRUE) OR A DEFAULT VALUE (FALSE).  THE LEFTMOST THIRTY 
*     BITS INDICATE WHETHER *VALUE* IS *KEYWORD* OR *KEYWORD=VALUE*.
# 
  
      ARRAY PARM$ARRAY[1:NUMPARAMS] S(2); 
        BEGIN 
        ITEM PARM$IVALUE U(00,00,60); 
        ITEM PARM$CVALUE C(00,00,07); 
        ITEM PARM$NUMARG U(01,00,30); 
        ITEM PARM$USED   B(01,30,30); 
        END 
  
# 
*     TYPE DECLARATIONS FOR PARM$TYPE FIELD IN PDT$ARRAY
# 
  
      DEF TYPE$NULL    # 0 #;          # NULL PARAMETER FIELD          #
      DEF TYPE$FILE    # 1 #;          # FILE TYPE PARAMETER           #
      DEF TYPE$INTEGER # 2 #;          # INTEGER TYPE PARAMETER        #
      DEF TYPE$NAME    # 3 #;          # NAME TYPE PARAMETER           #
      DEF TYPE$USER    # 4 #;          # USER NAME PARAMETER           #
  
# 
*     PDT$ARRAY - THIS ARRAY DEFINES THE ALLOWABLE PARAMETERS FOR THE 
*     CONTROL CARD. DEFAULTS ARE LISTED ALONG WITH THE MAXIMUM LENGTHS
*     OF EACH PARAMETER, WHETHER THE PARAMETER IS *KEYWORD* OR
*     *KEYWORD=VALUE*, THE TYPE OF THE PARAMETER, WHETHER THE 
*     KEYWORD IS REQUIRED OR OPTIONAL AND THE MINIMUM AND MAXIMUM 
*     VALUES ALLOWED (INTEGER TYPE PARAMETERS ONLY).
* 
*     PARM$NAME    - 1 TO 7 CHARACTERS, ZERO FILLED.
*     PARM$MXLEN   - INTEGER VALUE 1 THRU 7 
*     PARM$NARGS   - 1 => KEYWORD ONLY, 2 => KEYWORD=VALUE, 3 => EITHER.
*     PARM$TYPE    - 1 = FILE NAME
*                    2 = INTEGER
*                    3 = KEYWORD NAME 
*                    4 = USER NAME
*     PARM$REQRD   - BOOLEAN, TRUE => KEYWORD REQUIRED, FALSE =>OPTIONAL
*     PARM$DFAULT  - DEFAULT PARAMETER VALUE BINARY REPRESENTATION
*     PARM$MIN     - MINIMUM ALLOWABLE INTEGER VALUE
*     PARM$MAX     - MAXIMUM ALLOWABLE INTEGER VALUE
* 
* 
*     ARRAY PDT$ARRAY[1:NUMPARAMS] S(3) 
*       BEGIN 
*       ITEM PDT$WORD1  U(00,00,60) 
*       ITEM PARM$NAME  C(00,00,07) 
*       ITEM PARM$MXLEN U(00,42,09) 
*       ITEM PARM$NARGS U(00,51,03) 
*       ITEM PARM$TYPE  U(00,54,03) 
*       ITEM PARM$REQRD B(00,57,03) 
*       ITEM PDT$WORD2  U(01,00,60) 
*       ITEM PARM$DFALT U(01,00,60) 
*       ITEM PDT$WORD3  U(02,00,60) 
*       ITEM PARM$MIN   I(02,00,30) 
*       ITEM PARM$MAX   I(02,30,30) 
*       END 
# 
  
      ARRAY PDT$ARRAY[1:NUMPARAMS] S(3);
        BEGIN 
        ITEM PDT$WORD1  U(00,00,60);
        ITEM PARM$NAME  C(00,00,07);
        ITEM PARM$MXLEN U(00,42,09);
        ITEM PARM$NARGS U(00,51,03);
        ITEM PARM$TYPE  U(00,54,03);
        ITEM PARM$REQRD B(00,57,03);
        ITEM PDT$WORD2  U(01,00,60);
        ITEM PARM$DFALT U(01,00,60);
        ITEM PDT$WORD3  U(02,00,60);
        ITEM PARM$MIN   I(02,00,30);
        ITEM PARM$MAX   I(02,30,30);
        END 
  
# 
*     SINGLE VALUE PARAMETERS 
# 
  
      ITEM NUMPARMS  U;      # NUMBER OF PARAMETERS IN PDT$ARRAY       #
      ITEM PROGNAME  C(7);   # NAME OF CALLING PROGRAM                 #
      ITEM COMMENT   C(80);  # COMMENT STRING FROM CONTROL STATEMENT   #
  
CONTROL EJECT;
# 
****  FFSICCC - DAYFILE MESSAGES ISSUED 
# 
  
 ITEM DUPLPARM     C(46) =
      "-DUPLICATE CONTROL STATEMENT PARAMETER-XXXXXXX"; 
 ITEM DUPLFNAME    C(28) =
      "-DUPLICATE FILE NAME-XXXXXXX"; 
 ITEM ILLEGALFN    C(26) =
      "-ILLEGAL FILE NAME-XXXXXXX FOR PARAMETER-XXXXXXX"; 
 ITEM ILLEGALUN    C(26) =
      "-ILLEGAL USER NAME-XXXXXXX FOR PARAMETER-XXXXXXX"; 
 ITEM ILLEGALSEP   C(22) =
      "-ILLEGAL SEPARATOR-*X*"; 
 ITEM ILLEGALVALUE C(50) =
      "-ILLEGAL VALUE-XXXXXXX FOR PARAMETER-XXXXXXX"; 
 ITEM KEYWORDERR   C(35) =
      "-VALUE SUPPLIED FOR KEYWORD-XXXXXXX";
 ITEM MISSINGPARM  C(35) =
      "-REQUIRED PARAMETER MISSING-XXXXXXX";
 ITEM MISSINGVAL   C(42) =
      "-VALUE NOT SPECIFIED FOR PARAMETER-XXXXXXX"; 
 ITEM NOTINRANGE   C(45) =
      "-VALUE OUTSIDE OF RANGE FOR PARAMETER-XXXXXXX";
 ITEM PARM$ERROR   C(37) =
      "-CONTROL STATEMENT ERROR-JOB ABORTED.";
 ITEM TOOBIG       C(46) =
      "-VALUE XXXXXXX TOO LARGE FOR PARAMETER-XXXXXXX"; 
 ITEM UNRECPARM    C(48) =
      "-UNRECOGNIZED CONTROL STATEMENT PARAMETER-XXXXXXX";
  
# 
****
# 
CONTROL EJECT;
  
# 
*     LOCAL VARIABLES 
# 
      ITEM ARGINDEX U;       # ARGUMENT INDEX                          #
      ITEM CHAR     U;
      ITEM EOC      B;       # END OF COMMAND FLAG                     #
      ITEM ERROR    B;       # ERROR FLAG FOR CONTROL CARD ERROR       #
      ITEM ERROR1   B;       # ERROR FLAG                              #
      ITEM EQUALSIGN B;      # EQUAL SIGN SEPARATOR FLAG               #
      ITEM FOUND    B;       # PARAMETER MATCH FOUND FLAG              #
      ITEM I        U=0;     # COUNTER FOR PARAMETERS                  #
      ITEM J        U=0;     # LOOP INDEX VARIABLE                     #
      ITEM K        U=0;     # LOOP INDUCTION VARIABLE                 #
      ITEM L        U=0;     # LOOP VARIABLE                           #
      ITEM KEYEQVAL B;       # KEYWORD=VALUE SUPPLIED                  #
      ITEM KEYI     U;       # KEYWORD INDEX                           #
      ITEM KEYINDEX U;       # KEYWORD INDEX                           #
      ITEM NUMARGS  U;       # NUMBER OF ARGUMENTS                     #
      ITEM PNAMELEN I;       # LENGTH OF NAME OF CALLING PROGRAM       #
      ITEM PVALUE   U;
      ITEM SYNTAX   B;       # SYNTAX OF PARAMETER CORRECT             #
CONTROL EJECT;
# 
*     BASED ARRAYS - JOB COMMUNICATIONS AREA
# 
  
      BASED ARRAY ARG [1:22] S(1);     # RA COMMUNICATION AREA         #
        BEGIN                          # RA.ARGR                       #
        ITEM ARGSYM   C(00,00,07);     # ARGUMENT VALUE                #
        ITEM ARGSEP   U(00,42,18);     # ARGUMENT SEPARATOR            #
        ITEM ARGSEPVL C(00,54,01);     # ARG SEPARATOR CHARACTER VALUE #
        ITEM ARGWORD  U(00,00,60);     # WHOLE WORD                    #
        END 
  
      BASED ARRAY ACTRWD  [0:0] S(1); 
        BEGIN 
        ITEM ACTR$COUNT  U(00,42,18);  # ARGUMENT COUNT                #
        END 
  
      BASED ARRAY CCDR [1:8] S(1);     # COMMAND IMAGE                 #
        BEGIN 
        ITEM COMMANDIMAGE C(00,00,10);
        ITEM COMMANDLINE  C(00,00,80);
        END 
  
      DEF EQUAL        #O"54"#;        # EQUAL SIGN                    #
      DEF SCOPEQUAL    #O"02"#;        # PRODUCT SET EQUAL SIGN        #
      DEF CHARZERO     #O"33"#;        # ZERO                          #
      DEF CHARNINE     #O"44"#;        # NINE                          #
      DEF COMMA        #O"56"#;        # COMMA                         #
      DEF PERIOD       #O"57"#;        # PERIOD                        #
      DEF RPAREN       #O"52"#;        # RIGHT PARENTHESIS             #
      DEF SCOPECOMMA   #O"01"#;        # PRODUCT SET COMMA             #
      DEF SCOPETERM    #O"17"#;        # PRODUCT SET PERIOD OR R. PAREN#
CONTROL EJECT;
  
PROC MESSAGEX(STRING,MSGLENGTH);
  
      BEGIN        # MESSAGEX # 
  
# 
**    MESSAGEX - PROC TO DAYFILE MESSAGES 
* 
*     ENTRY -      STRING = ERROR MESSAGE TO BE ISSUED TO DAYFILE 
*                  MSGLENGTH = LENGTH OF ERROR MESSAGE
* 
*     EXIT  -      MESSAGE CONTAINING PROGRAM NAME CONCATENATED WITH
*                  *STRING* HAS BEEN DAYFILED.
* 
# 
  
      ITEM STRING  C(80);              # ERROR MESSAGE TEXT            #
      ITEM MSGLENGTH I;                # ERROR MESSAGE LENGTH          #
      ITEM I           U;              # INDEX                         #
      ITEM MSG     C(80);              # COMPLETED ERROR MESSAGE       #
  
      C<1,1>MSG = " ";
      C<2,PNAMELEN>MSG = PROGNAME;     # INSERT PROGRAM NAME INTO MSG  #
      C<PNAMELEN,80-PNAMELEN>MSG = STRING;       # INSERT MSG TEXT     #
      FOR I=MSGLENGTH + PNAMELEN STEP 1 
        WHILE ((I LQ MSGLENGTH+12) AND (I LQ 80)) 
      DO
        C<I,1>MSG = ":";
      MESSAGE(MSG,0);                  # DAYFILE MESSAGE               #
      RETURN; 
  
      END          # MESSAGEX # 
  
FUNC SIZE(PARAMETER) I; 
  
      BEGIN        # SIZE # 
  
# 
**    SIZE - FUNCTION THAT CALCULATES THE SIZE USER SUPPLIED PARAMETER
* 
*     ENTRY -      PARAMETER = USED SUPPLIED PARAMETER
* 
*     EXIT  -      LENGTH (IN CHARACTERS) OF USER SUPPLIED PARAMETER
* 
# 
  
      ITEM PARAMETER C(7);             # USER SUPPLIED PARAMETER       #
      ITEM I           U;              # INDEX                         #
  
      FOR I=0 STEP 1 WHILE I LS 7 
      DO
        IF C<I,1>PARAMETER EQ ":" THEN
          BEGIN 
          SIZE = I; 
          RETURN; 
          END 
      SIZE = 7; 
      RETURN; 
  
      END          # SIZE # 
  
FUNC BLANKFILL(PARAMETER) C(7); 
  
      BEGIN        # BLANKFILL #
  
# 
**    BLANKFILL -  FUNCTION THAT REPLACES COLONS WITH BLANKS
* 
*     ENTRY -      PARAMETER = USED SUPPLIED PARAMETER
* 
*     EXIT  -      COLONS REPLACED WITH BLANKS
* 
# 
  
      ITEM PARAMETER C(7);             # USER SUPPLIED PARAMETER       #
      ITEM I           U;              # INDEX                         #
  
      FOR I=0 STEP 1 WHILE I LS 7 
      DO
        IF C<I,1>PARAMETER EQ ":" THEN
          BEGIN 
          C<I,1>PARAMETER = " ";
          END 
      BLANKFILL = PARAMETER;
      RETURN; 
  
      END          # BLANKFILL #
CONTROL EJECT;
  
# 
*     MAIN PROGRAM
# 
  
      P<ARG> = 2;                      # BASE RA+2 COMMUNICATION AREA  #
      P<ACTRWD> = O"64";               # BASE ARGUMENT AREA            #
      P<CCDR> = O"70";                 # BASE COMMAND IMAGE AREA       #
      ERROR = FALSE;
  
      EQUALSIGN = FALSE;
      FOR PNAMELEN=0 STEP 1 WHILE (PNAMELEN LS 7 AND NOT EQUALSIGN) 
      DO
        BEGIN                          # DETERMINE PROGRAM NAME LENGTH #
                                       # FOR INSERTION INTO ERROR MSGS #
        IF C<PNAMELEN,1>PROGNAME EQ " " 
        THEN
          BEGIN 
          EQUALSIGN = TRUE; 
          END 
        END 
  
      FOR J=1 STEP 1 WHILE J LQ NUMPARMS
      DO
        BEGIN                          # INITIALIZE PARAMETER ARRAY    #
        PARM$IVALUE[J] = 0; 
        PARM$USED[J] = FALSE; 
        PARM$NUMARG[J] = 0; 
        END 
  
# 
*     LOOP TO PROCESS PARAMETERS
# 
  
      NUMARGS = ACTR$COUNT[0];         # NUMBER OF ARGUMENTS           #
      ARGINDEX = 0; 
      FOR ARGINDEX = ARGINDEX WHILE ARGINDEX LS NUMARGS 
      DO
        BEGIN                          # SCAN RA+2 THRU RA+22          #
        ARGINDEX = ARGINDEX + 1;
        FOUND = FALSE;
        FOR KEYINDEX = 1 STEP 1 WHILE 
            KEYINDEX LQ NUMPARMS AND NOT FOUND
        DO
          BEGIN 
          IF ARGSYM[ARGINDEX] EQ PARM$NAME[KEYINDEX]
          THEN
            BEGIN                      # VALID KEYWORD FOUND           #
            KEYI=KEYINDEX;
            FOUND = TRUE; 
            END 
          END 
  
        IF FOUND                       # VALID PARAMETER               #
        THEN
          BEGIN 
          EQUALSIGN = (ARGSEP[ARGINDEX] EQ EQUAL) OR
                      (ARGSEP[ARGINDEX] EQ SCOPEQUAL);
          SYNTAX = FALSE;              # RESET SYNTAX CORRECT          #
          IF PARM$NARGS[KEYI] NQ 2     # POSSIBLE KEYWORD PARAMETER    #
          THEN
            BEGIN 
            SYNTAX = (ARGSEP[ARGINDEX] EQ 0) OR 
                     (ARGSEP[ARGINDEX] EQ SCOPECOMMA) OR
                     (ARGSEP[ARGINDEX] EQ SCOPETERM); 
            END;
          IF PARM$NARGS[KEYI] NQ 1 AND   # PARAMETER = VALUE TYPE OR   #
             NOT SYNTAX                  # KEYWORD NOT DETECTED        #
          THEN
            BEGIN 
            SYNTAX = (ARGINDEX+1 LQ NUMARGS) AND
                      EQUALSIGN;
            END;
          IF SYNTAX 
          THEN
            BEGIN                      # PARAMETER SYNTAX OK           #
            KEYEQVAL = FALSE; 
            IF PARM$NARGS[KEYI] NQ 1 AND EQUALSIGN
            THEN
              BEGIN                    # KEYWORD=VALUE TYPE PARAMETER  #
              KEYEQVAL = TRUE;         # KEYWORD=VALUE SUPPLIED        #
              ARGINDEX = ARGINDEX + 1; # UPDATE ARGUMENT POINTER       #
              PARM$NUMARG[KEYI] = 1;   # INDICATE USER SUPPLIED A VALUE#
              END 
            IF NOT PARM$USED[KEYI]
            THEN
              BEGIN                    # PARAMETER NOT USED BEFORE     #
              IF KEYEQVAL  THEN        # KEYWORD=VALUE TYPE PARAMETER  #
                PARM$CVALUE[KEYI] = ARGSYM[ARGINDEX]; 
              ELSE                     # DEFAULT SUPPLIED              #
                PARM$IVALUE[KEYI] = PARM$DFALT[KEYI]; 
              PARM$USED[KEYI] = TRUE;  # INDICATE PARAMETER SPECIFIED  #
              END 
            ELSE
              BEGIN 
              C<39,7>DUPLPARM = BLANKFILL(PARM$NAME[KEYI]); 
              MESSAGEX(DUPLPARM,45);   # DUPLICATE PARAMETER           #
              ERROR = TRUE; 
              END 
            END 
          ELSE
            BEGIN                      # ILLEGAL SYNTAX DETECTED       #
            ERROR = TRUE; 
            IF PARM$NARGS[KEYI] EQ 2             # *PARM=VALUE* ERROR  #
            THEN
              BEGIN 
              IF NOT EQUALSIGN
                 OR (ARGINDEX+1) GR NUMARGS 
              THEN
                BEGIN 
                IF ARGSEP[ARGINDEX] EQ 0
                   OR (ARGINDEX+1) GR NUMARGS 
                THEN
                  BEGIN                          # MISSING VALUE       #
                  C<35,7>MISSINGVAL = BLANKFILL(ARGSYM[ARGINDEX]);
                  MESSAGEX(MISSINGVAL,41);
                  END 
                ELSE
                  BEGIN                          # ILLEGAL SEPARATOR   #
                  C<20,1>ILLEGALSEP = ARGSEPVL[ARGINDEX]; 
                  MESSAGEX(ILLEGALSEP,24);
                  END 
                END 
              END 
            ELSE
              BEGIN 
              IF (PARM$NARGS[KEYI] EQ 1 AND      # *PARM* ERROR        #
                 ARGSEP[ARGINDEX] NQ 0) 
              THEN
                BEGIN                            # KEYWORD ERROR       #
                C<28,7>KEYWORDERR = BLANKFILL(PARM$NAME[KEYI]); 
                MESSAGEX(KEYWORDERR,34);
                END 
              ELSE
                BEGIN 
                # PARM$NARGS[KEYI] EQ 3 # 
                IF (NOT EQUALSIGN AND 
                   ARGSEP[ARGINDEX] NQ 0) 
                THEN
                  BEGIN                          # ILLEGAL SEPARATOR   #
                  C<20,1>ILLEGALSEP = ARGSEPVL[ARGINDEX]; 
                  MESSAGEX(ILLEGALSEP,24);
                  END 
                END 
              END 
            IF EQUALSIGN
            THEN
              ARGINDEX = ARGINDEX + 1;
            END 
          END 
        ELSE                           # PARAMETER NOT FOUND           #
          BEGIN 
          C<42,7>UNRECPARM = BLANKFILL(ARGSYM[ARGINDEX]); 
          MESSAGEX(UNRECPARM,47);      # UNRECOGNIZED PARAMETER        #
          ERROR = TRUE; 
          END 
        END 
  
# 
*     NOW FILL IN DEFAULT PARAMETERS, VERIFY USER VALUES, AND CHECK FOR 
*     MISSING REQUIRED PARAMETERS.
# 
  
      FOR I=1 STEP 1 WHILE I LQ NUMPARMS
      DO
        BEGIN 
        IF NOT PARM$USED[I] 
        THEN
          BEGIN                        # PARAMETER NOT USED            #
          IF PARM$REQRD[I]
          THEN
            BEGIN                      # MISSING PARAMETER             #
            C<28,7>MISSINGPARM = BLANKFILL(PARM$NAME[I]); 
            MESSAGEX(MISSINGPARM,34); 
            ERROR = TRUE; 
            END 
          ELSE                         # SUPPLY THE DEFAULT            #
            PARM$IVALUE[I] = PARM$DFALT[I]; 
          END 
        ELSE
          BEGIN                        # PARAMETER SUPPLIED. CHECK IT  #
          IF (SIZE(PARM$IVALUE[I]) GR PARM$MXLEN[I])
             AND (PARM$TYPE[I] NQ TYPE$INTEGER) 
          THEN
            BEGIN                      # PARAMETER SIZE ERROR          #
            C<7,7>TOOBIG = BLANKFILL(PARM$CVALUE[I]); 
            C<39,7>TOOBIG = BLANKFILL(PARM$NAME[I]);
            MESSAGEX(TOOBIG,46);
            ERROR = TRUE; 
            END 
          IF PARM$TYPE[I] EQ TYPE$FILE
          THEN
            BEGIN                      # FILE NAME PARAMETER           #
            IF PARM$IVALUE[I] EQ O"33000000000000000000"
            THEN
              BEGIN                    # NO FILE, CLEAR FILE NAME      #
              PARM$IVALUE[I] = 0; 
              END 
            ELSE
              BEGIN 
              IF NOT FFSUVFN(PARM$CVALUE[I])
              THEN
                BEGIN                  # INVALID FILE NAME             #
                C<19,7>ILLEGALFN = BLANKFILL(PARM$CVALUE[I]); 
                C<41,7>ILLEGALFN = BLANKFILL(PARM$NAME[I]); 
                MESSAGEX(ILLEGALFN,25); 
                ERROR = TRUE; 
                END 
              END 
  
            FOR K=I+1 STEP 1 WHILE K LQ NUMPARMS
            DO                        # CHECK FOR DUPLICATE FILE NAMES #
              BEGIN 
              IF PARM$TYPE[K] EQ TYPE$FILE
                AND PARM$CVALUE[K] EQ PARM$CVALUE[I]
                AND PARM$IVALUE[K] NQ O"33000000000000000000" 
                AND PARM$IVALUE[K] NQ 0 
              THEN
                BEGIN 
                C<21,7>DUPLFNAME = BLANKFILL(PARM$CVALUE[K]); 
                MESSAGEX(DUPLFNAME,27); 
                ERROR = TRUE; 
                END 
              END 
            END 
          IF PARM$TYPE[I] EQ TYPE$USER
          THEN
            BEGIN                      # USER NAME PARAMETER           #
            IF PARM$IVALUE[I] EQ O"33000000000000000000"
            THEN
              BEGIN                    # NO USER, CLEAR USER NAME      #
              PARM$IVALUE[I] = 0; 
              END 
            ELSE
              BEGIN 
              IF NOT FFSUVUN(PARM$CVALUE[I])
              THEN
                BEGIN                  # INVALID USER NAME             #
                C<19,7>ILLEGALUN = BLANKFILL(PARM$CVALUE[I]); 
                C<41,7>ILLEGALUN = BLANKFILL(PARM$NAME[I]); 
                MESSAGEX(ILLEGALUN,25); 
                ERROR = TRUE; 
                END;
              END;
            END;
          IF PARM$TYPE[I] EQ TYPE$INTEGER 
          THEN
            BEGIN                      # INTEGER VALUE PARAMETER       #
            PVALUE = 0; 
            B<0,42>PVALUE = PARM$CVALUE[I]; 
            PARM$IVALUE[I] = 0; 
            ERROR1 = FALSE; 
            FOR K = 0 STEP 1 WHILE K LS 7 
            AND C<K,7-K>PVALUE NQ 0 AND NOT ERROR1
            DO
              BEGIN                    # VALIDATE EACH CHARACTER       #
              CHAR = C<K,1>PVALUE;
              IF CHAR LS CHARZERO OR CHAR GR CHARNINE 
              THEN
                BEGIN                  # ILLEGAL VALUE                 #
                C<15,7>ILLEGALVALUE = BLANKFILL(C<0,7>PVALUE);
                C<37,7>ILLEGALVALUE = BLANKFILL(PARM$NAME[I]);
                MESSAGEX(ILLEGALVALUE,49);
                ERROR = TRUE; 
                ERROR1 = TRUE;
                END 
              ELSE
                PARM$IVALUE[I]=PARM$IVALUE[I]*10+(C<K,1>PVALUE-O"33");
              END 
            IF NOT ERROR1 
            THEN
              IF PARM$IVALUE[I] GR PARM$MAX[I] OR 
                 PARM$IVALUE[I] LS PARM$MIN[I]
              THEN
                BEGIN                            # IF NOT IN RANGE     #
                C<38,7>NOTINRANGE = BLANKFILL(PARM$NAME[I]);
                MESSAGEX(NOTINRANGE,45);
                ERROR = TRUE; 
                END 
            END 
          END 
        END 
  
# 
*     GET COMMENTS FIELD FROM CONTROL CARD
# 
      FOUND = FALSE;
      COMMENT = " ";
      FOR I=1 STEP 1 WHILE I LQ 8 AND NOT FOUND 
      DO
        BEGIN 
        L = I;
        B<0,60>PVALUE = COMMANDIMAGE[I];
        FOR K=0 STEP 1 WHILE K LQ 9 AND NOT FOUND 
        DO
          BEGIN 
          CHAR = C<K,1>PVALUE;
          IF (CHAR EQ PERIOD) OR (CHAR EQ RPAREN)  THEN 
            BEGIN 
            FOUND = TRUE; 
            J = K+1;
            END 
          END 
        END 
  
      I = (L-1)*10+J; 
      J = 80 - I; 
      C<0,J>COMMENT = C<I,J>COMMANDLINE[1]; 
  
# 
*     IF ERROR IN CONTROL CARD, ABORT JOB 
# 
  
      IF ERROR
      THEN
        BEGIN                          # ERROR IN CRACKING CONTROL CARD#
        MESSAGEX(PARM$ERROR,38);       # ISSUE DAYFILE MESSAGE         #
        ABORT;                         # ABORT PROGRAM                 #
        END 
  
      RETURN; 
  
      END          # FFSICCC #
  
      TERM
