SECART
*NOSEQ
      PROGRAM SECART
***       SECART -  SECURITY AUDIT REDUCTION TOOL.
* 
*         COPYRIGHT CONTROL DATA SYSTEMS INC.  1992.
* 
*         T. A. CURETON.      86/06/30. 
  
***       OVERVIEW. 
* 
*         *SECART* IS A STAND-ALONE SECURITY ADMINISTRATOR UTILITY WHICH
*         DIGESTS BOTH *ACCOUNT* AND *DAYFILE* LOG MESSAGES, REDUCING 
*         THE VOLUME OF DATA WHICH MUST BE REVIEWED AND PRODUCES
*         PRINTOUTS AND FILES USEFUL FOR SECURITY AUDITING PURPOSES.
  
***       FUNCTIONS.
* 
*         - MERGE BY TIME SEQUENCE MESSAGES FROM RAW *DAYFILE* AND
*           *ACCOUNT* LOGS TO PRODUCE A NEAR-NORMAL CAUSE-AND-EFFECT
*           SERIAL SEQUENCE AND ESTABLISH EVENT CONTEXT.
* 
*         - SELECT MESSAGES FROM RAW LOGS FOR SERIAL PRINTOUT BASED ON
*           CRITERIA SPECIFIED IN DIRECTIVES. 
* 
*         - EXTRACT JSN-S, USER NAMES, AND OTHER ATTRIBUTES OF EACH JOB 
*           ENCOUNTERED IN THE RAW LOG INPUT(S).
* 
*         - RECOGNIZE MESSAGES INDICATING LEVEL 0 DEADSTARTS WHICH RESET
*           JSN GENERATION SEQUENCE AND AUGMENT JSN IDENTIFIERS TO
*           UNIQUELY IDENTIFY EACH JOB. 
* 
*         - RECOGNIZE JOB RECOVERY EVENTS AND, WHERE POSSIBLE, RECOVER
*           JOB ATTRIBUTES FROM PREVIOUS JSN TRACE TABLE ENTRIES. 
* 
*         - COLLECT AND PRINTOUT STATISTICS ON USAGE OF *ACCOUNT* LOG 
*           MESSAGE IDENTIFIERS.
* 
*         - SORT AND PRINTOUT JSN TRACE TABLE PER DIRECTIVES. 
* 
*         - SORT COMPOSITE (MERGED) LOG TO GROUP MESSAGES BY UNIQUE JSN.
* 
*         - SELECT AND PRINTOUT UNIT JOBS PER DIRECTIVES.  APPLY SAMPLE 
*           LIMIT TO NUMBER OF MESSAGES PRINTED FOR EACH JOB TO REDUCE
*           RISK OF MASSIVE PRINTOUT OR EXCEEDING RESOURCE LIMITS.
  
***       COMMAND FORMAT. 
* 
*         SECART(P1,P2,...PN) 
* 
*         EACH PARAMETER SPECIFIES THE LFN OF A FILE PROVIDED AS INPUT
*         OR TO BE PRODUCED AS AN OUTPUT OF THE PROGRAM.  PARAMETERS
*         MUST BE IN KEYWORD=VALUE FORMAT AND MAY BE IN ANY ORDER.  A 
*         VALUE OF *0* (ZERO) SPECIFIES NO FILE IS PROVIDED OR PRODUCED.
*         A PARAMETER OMITTED OR SPECIFIED WITHOUT A VALUE FIELD WILL 
*         ASSUME A DEFAULT VALUE AS DEFINED IN THE FOLLOWING TABLE: 
* 
*           PARAM OMIT NO_VALUE DESCRIPTION 
* 
*           *D*   0    DFLOG    RAW DAYFILE LOG INPUT.
*           *A*   0    ACLOG    RAW ACCOUNT LOG INPUT.
*           *C*   0    COMBO    COMPOSITE LOG OUTPUT/INPUT. 
*           *J*   0    JOBS     UNIT JOBS COMPOSITE LOG OUTPUT/INPUT. 
*           *M*   0    MSGID    ACCOUNT MSG ID REFERENCE INPUT FILE.
*           *T*   0    TRACE    JSN TRACE TABLE INPUT AND OUTPUT. 
*           *I* INPUT  INPUT    DIRECTIVES INPUT FILE.
*           *L* OUTPUT OUTPUT   PRINTOUTS FILE.  REQUIRED OUTPUT. 
* 
*         AT LEAST ONE OF THE FILES IDENTIFIED BY PARAMETERS *D*,*A*, 
*         C*,*J*,*T* MUST BE SPECIFIED TO PROVIDE INPUT(S) FOR *SECART* 
*         PROCESSING.  SPECIFYING EITHER (OR BOTH) RAW LOGS (*D*,*A*) 
*         DEFINES AN INITIAL RUN WITH COMPOSITE (*C*) AND UNIT JOB (*J*)
*         LOGS AND JSN TRACE TABLE (*T*) PRODUCED AS OUTPUT FILES.
* 
*         IF NO RAW LOG FILE IS SPECIFIED, *SECART* WILL ASSUME RERUN 
*         MODE AND LOOK FOR 1) A COMPOSITE LOG OR 2) UNIT JOBS LOG AS 
*         INPUT.  IF A COMPOSITE LOG (*C*) IS PROVIDED, THE UNIT JOBS 
*         LOG (*J*) WILL BE AN OUTPUT FILE.  IF A UNIT JOBS LOG (*J*) IS
*         THE LOG INPUT FILE, ONLY PRINTOUTS WILL BE PRODUCED.
* 
*         THE JSN TRACE TABLE FILE (*T*) IS PRODUCED ONLY DURING AN 
*         INITIAL RUN.  IT CONTAINS AN ENTRY FOR EACH JOB FOUND IN THE
*         RAW LOG(S) AND SHOULD BE SAVED TO FACILLITATE RERUNS.  ANY
*         *SECART* RERUN USING A PRE-PROCESSED LOG FILE REQUIRES
*         PROVIDING THE TRACE TABLE FILE WHICH CORRESPONDS TO THE INPUT 
*         LOG.  PROVIDING A JSN TRACE TABLE FILE AS THE ONLY INPUT IS 
*         USEFUL FOR RE-SORTING AND/OR PRINTOUT OF THE JSN TRACE TABLE. 
*         TO AID RECOVERY OF JOB ATTRIBUTES FROM A PREVIOUS SET OF RAW
*         LOGS, THE TRACE TABLE (OR A SUBSET) FROM THE PREVIOUS RUN MAY 
*         BE PROVIDED FOR AN INITIAL RAW LOGS *SECART* RUN.  SINCE THIS 
*         FILE WILL BE FIRST READ, THEN REWRITTEN, AN EXPENDABLE COPY OF
*         THE TRACE TABLE FILE (OR SUBSET) SHOULD BE PROVIDED.
* 
*         THE INPUT FILE (*I*) MAY CONTAIN *SECART* DIRECTIVES WHICH
*         SPECIFY CRITERIA FOR SELECTING MESSAGES AND/OR UNIT JOBS FOR
*         PRINTOUT, SORTING JSN TRACE TABLE ENTRIES, AND LIMITING UNIT
*         JOB PRINTOUTS.  SEE DIRECTIVES SECTION BELOW FOR DESCRIPTIONS.
* 
*         A LIST FILE (*L*) IS ALWAYS PRODUCED AND THE *L* PARAMETER MAY
*         BE USED TO DIRECT PRINTOUTS TO A FILENAME.  THE SEQUENCE OF 
*         PRINTOUTS MAY INCLUDE:  
* 
*             - *SECART* DIRECTIVES AND ANY DIRECTIVE ERROR MESSAGES. 
* 
*             - TIME SEQUENCED SERIAL PRINTOUT OF SELECTED MESSAGES.
* 
*             - *ACCOUNT* MESSAGE ID STATISTICS.
* 
*             - SORTED JSN TRACE TABLE. 
* 
*             - SELECTED UNIT JOBS. 
  
***       DIRECTIVES. 
* 
*         *SECART* DIRECTIVES MAY BE USED TO SPECIFY OPTIONS AND TO 
*         SELECT MESSAGES, TIME WINDOWS, AND JOBS FOR PRINTOUT.  ALL
*         SELECTIONS ARE ON AN INCLUSIVE OR BASIS.  SELECTED *ACCOUNT*
*         MESSAGE ID-S ARE FLAGGED AND OCCURRENCES TABULATED IN THE 
*         STATISTICS PRINTOUT.  SELECTED JOBS ARE ANNOTATED TO SHOW 
*         SELECTION BASIS IN THE JSN TRACE TABLE PRINTOUT.
* 
*         EACH DIRECTIVE MUST BEGIN IN COLUMN 1 ON A SEPARATE INPUT 
*         LINE.  THE *=* AFTER THE DIRECTIVE NAME IS REQUIRED.  SYNTAX
*         IS GENERALLY FREEFORM USING A COMMA AND/OR BLANKS TO SEPARATE 
*         ARGUMENTS.  ITEMS SHOWN BELOW IN [BRACKETS] ARE OPTIONAL. 
*         REPETITIVE ARGUMENTS ARE INDICATED BY TRIPLE PERIODS AND MAY
*         MAY BE ENTERED VIA MULTIPLE DIRECTIVES TO A MAXIMUM DEFINED 
*         BY TABLE SPACE (50 EACH TYPE).
* 
*         AMSG=MSID,MSID,...
* 
*                  SELECTS FOR SERIAL PRINTOUT ALL MESSAGES CONTAINING
*                  ANY OF THE SPECIFIED ACCOUNT MESSAGE IDENTIFIERS.
* 
*         DMSG=[NN:]TEXTSTRING
* 
*                  SELECTS FOR SERIAL PRINTOUT OF ALL DAYFILE 
*                  MESSAGES CONTAINING SPECIFIED TEXT STRING.  NN IS
*                  OPTIONAL AND SPECIFIES A START CHARACTER POSITION
*                  [1-80] RELATIVE TO MESSAGE PORTION OF DAYFILE.  TEXT 
*                  STRING IS UNDELIMITED, BEGINS IMMEDIATELY AFTER THE
*                  EQUAL OR COLON, AND ENDS WITH LAST NON-BLANK.
* 
*         TIME=HHMMSS[-HHMMSS]      (OR)
*         TIME=HH.MM.SS.[-HH.MM.SS] 
* 
*                  SPECIFIES TIME WINDOW FOR SERIAL PRINTOUT. 
*                  SECONDS PORTION IS OPTIONAL.  END TIME IS OPTIONAL 
*                  BUT REQUIRES '-' SEPARATOR.  DEFAULTS TO SAME AS 
*                  START TIME FOR ONE SECOND WINDOW.
* 
*         TRACE=KEY,KEY,... 
* 
*                  SPECIFIES SORT KEYS FOR TRACE TABLE PRINTOUT.  VALID 
*                  KEYS:  UJN,JSN,JC,SDT,EDT,FM,UN,TRM.  DEFAULT IS SDT 
*                  WHICH IS SEQUENCE OF ENCOUNTERING UNIQUE JSN-S.
* 
*         USER=FAMILY,USER
* 
*                  SELECTS UNIT JOBS FOR PRINTOUT BY USER/FAMILY
*                  IDENTIFICATION.  FAMILY MAY BE BLANK OR OMITTED TO 
*                  SELECT DEFAULT FAMILY.  ASTERISK MAY BE SPECIFIED
*                  FOR WILDCARD MATCH ON FAMILY OR USER.   NOTE THAT
*                  USER=*,* SELECTS ALL JOBS.  SINCE *SECART* RECOGNIZES
*                  THE USER INDEX IN A *SUI* COMMAND AS A USER ID, A
*                  USER INDEX MAY BE SPECIFIED IN PLACE OF THE USERNAME 
*                  AND WILL BE RECOGNIZED WHEN A *SUI* WITH THAT UI IS
*                  ENCOUNTERED IN THE DAYFILE LOG.
* 
*         UJN=JOBNAME,... 
* 
*                  SELECTS UNIT JOBS FOR PRINTOUT BY JOBNAME FOUND IN 
*                  FIRST DAYFILE MESSAGE (USUALLY). 
* 
*         JSN=[D.]AAAA,...
* 
*                  SELECTS UNIT JOBS FOR PRINTOUT BY JSN.  'D.' IS
*                  OPTIONAL AND SPECIFIES AN *SECART*-ASSIGNED PREFIX 
*                  CODE USED TO RESOLVE JSN AMBIGUITY ACROSS LEVEL 0
*                  DEADSTARTS.
* 
*         TRM=TERMID,...
* 
*                  SELECTS UNIT JOBS PRINTOUT BY TERMINAL ID. 
* 
*         LIMIT=NNNN
* 
*                  LIMITS UNIT JOB PRINTOUTS TO NNNN LINES EACH.  HELPS 
*                  REDUCE/AVOID MASSSIVE PRINTOUTS. 
  
***       CALLS.
* 
*         SORT/MERGE V5 - TO GROUP COMPOSITE LOG INTO UNIT JOBS AND 
*                       - TO SORT TRACE TABLE (OPTIONAL). 
  
***       DAYFILE MESSAGES. 
* 
*         *SECART* ISSUES TWO CLASSES OF DAYFILE MESSAGES - STATUS AND
*         ERROR MESSAGES. 
* 
*         STATUS MESSAGES MERELY INDICATE PROCESSING PHASES AND ARE 
*         SELF-EXPLANATORY.  ALL STATUS MESSAGES BEGIN WITH ONE LEADING 
*         BLANK AND OCCUR IN THE FOLLOWING SEQUENCE:  
* 
*             READING DIRECTIVES... 
* 
*             LOADING TRACE TABLE...
* 
*             DIGESTING RAW LOG(S)... 
* 
*             ACCOUNT MSG STATISTICS... 
* 
*             TRACE TABLE PRINTOUT... 
* 
*             SORTING OUT JOBS... 
* 
*             EXTRACTING SELECTED JOBS... 
* 
*             SECART COMPLETED. 
* 
*         ALL ERROR MESSAGES ARE OFFSET WITH THREE LEADING BLANKS AND 
*         FLAGGED WITH ASTERISKS TO STAND OUT IN THE DAYFILE SEQUENCE.
*         ERROR MESSAGES LEADING TO TERMINATION ALSO HAVE TRAILING
*         ASTERISKS.  ERROR MESSAGES AND EXPLANATIONS ARE:  
* 
*         *** SECART TERMINATED.
* 
*                  ABNORMAL *SECART* TERMINATION.  PRECEEDING MESSAGE 
*                  IDENTIFIES CAUSE.
* 
*         *** DIRECTIVE ERROR(S). 
* 
*                  SEE PRINTOUT FOR ERRORS. 
* 
*         *** [LFN] NOT RAW ACCOUNT LOG.
* 
*                  FIRST AND/OR SECOND LINES NOT IN DATE/TIME FORMAT. 
* 
*         *** [LFN] NOT RAW DAYFILE LOG.
* 
*                  FIRST AND/OR SECOND LINES NOT IN DATE/TIME FORMAT. 
* 
*         *** LIST FILE REQUIRED. 
* 
*                  *L=0* PARAMETER IGNORED. 
* 
*         *** LOG DATES MISMATCH. 
* 
*                  *ACCOUNT* VS *DAYFILE* SYSTEM DATE MISMATCH.  LOG
*                  TIME PERIODS MAY NOT OVERLAP.
* 
*         *** MSGID SEQUENCE ERROR(S).
* 
*                  *ACCOUNT* MESSAGE ID TABLE (*M*) OUT OF SEQUENCE.
* 
*         *** MSGID TABLE FULL ***
* 
*                  *ACCOUNT* MESSAGE ID FILE EXCEEDS TABLE SIZE.
* 
*         *** SYSTEM ID MISMATCH ***
* 
*                  *ACCOUNT* VS *DAYFILE* SYSTEM TITLE/VERSION
*                  MISMATCH.  LOGS NOT FROM SAME SYSTEM.
* 
*         *** TRACE TABLE FULL ***
* 
*                  JSN TRACE TABLE OVERFLOW.  MAY BE DUE TO COMBINING 
*                  TABLE FROM PREVIOUS LOGS.
* 
*         *** TRACE TABLE SEQUENCE ERROR(S).
* 
*                  LOADED TRACE TABLE (*T*) NOT IN ASCENDING D.JSN
*                  SEQUENCE.
* 
*         *** UNRECOGNIZED PARAMETER: [PARAM] 
* 
*                  PROGRAM CALL PARAMETER NOT RECOGNIZED. 
  
***       PRINTOUT MESSAGES.
* 
*         INFORMATIVE AND ERROR MESSAGES INSERTED IN THE PRINTOUT ARE 
*         FLAGGED WITH === AND *** RESPECTIVELY.  ALL ARE INDENTED THREE
*         SPACES.  A FEW INFORMATIVE MESSAGES ARE ALSO   E X P A N D E D
*         SO AS TO STAND OUT WHEN EMBEDDED IN LENGTHY SERIAL PRINTOUT.
* 
*         === EOF ACCOUNT LOG [LFN], NNNN MESSAGES     (OR) 
*         === EOF DAYFILE LOG [LFN], NNNN MESSAGES
* 
*                  MARKS LOG END-OF-FILE POINT AND NUMBER OF MESSAGES.
* 
*         === JSN NOT FOUND: [JSN] YY/MM/DD. HH.MM.SS.
* 
*                  ORIGINAL JSN NOT IN TRACE TABLE.  JOB ATTRIBUTES 
*                  NOT RECOVERED. 
* 
*         === JSN RECOVERED [D.JSN] 
* 
*                  JOB RECOVERY LINKED TO ORIGINAL JSN IN TRACE TABLE.
*                  JOB ATTRIBUTES RECOVERED VIA TRACE TABLE.
* 
*         ========= L E V E L   0   D / S   ( X ) ========= 
* 
*                  INITIAL LEVEL 0 D/S RESETS JSN SEQUENCE.  X IS NEW 
*                  *SECART*-GENERATED PREFIX FOR SUBSEQUENT JOBS. 
* 
*         ========= S A M P L E   L I M I T ========= 
* 
*                  UNIT JOB PRINTOUT TRUNCATED PER *LIMIT* DIRECTIVE. 
* 
*         *** TIME ARGUMENT ERROR.
* 
*                  ERROR IN VALUE OR SYNTAX FOR *TIME* DIRECTIVE. 
* 
*         ====== TIME WINDOW START ====== 
*         ====== TIME WINDOW END ====== 
* 
*                  INDICATES START/END OF SPECIFIED TIME WINDOW.
* 
*         *** TOO MANY ARGUMENTS, EXCESS IGNORED. 
* 
*                  REPETITIVE ARGUMENT LIST EXCEEDS TABLE SIZE. 
* 
*         *** UNRECOGNIZED DIRECTIVE ***
* 
*                  DIRECTIVE NOT RECOGNIZED - MISPELLED, ETC. 
  
**        INTERNAL OVERVIEW.
* 
*         *SECART* IS WRITTEN IN FORTRAN FOR COMPILATION VIA FTN5.  IT
*         CONSISTS OF A MAIN PROGRAM, PRIMARY SUBROUTINES, AND SUPPORT
*         SUBROUTINES ORGANIZED IN A TOP-DOWN STRUCTURE.  THE MAIN
*         PROGRAM ESTABLISHES OVERALL PROCESSING SEQUENCE AND CONTROL.
*         EACH PRIMARY SUBROUTINE ISOLATES RESPONSIBILITY FOR A MAJOR 
*         PROGRAM OBJECTIVE TO A SINGLE CODE MODULE AND SUPPORTS
*         SEVERAL RELATED FUNCTIONS VIA MULTIPLE ENTRY POINTS.  LOW 
*         LEVEL SUPPORT SUBROUTINES PROVIDE COMMON/REDUNDANT FUNCTIONS
*         USED BY ONE OR MORE SUBROUTINES AND/OR THE MAIN PROGRAM.
*         THE LIST OF MODULES AND [ENTRY POINTS] , INDENTED TO SHOW 
*         STRUCTURE, INCLUDES:  
* 
*         SECART - MAIN PROGRAM.
* 
*             DIRECT - DIRECTIVES AND SELECTION FUNCTIONS.
*             [TMCHECK] - TIME WINDOW CHECKING. 
*             [MSCHECK] - DAYFILE MESSAGE CHECK.
*             [PICKJSN] - PICK JOBS BY JSN. 
*             [PICKUJN] - PICK JOBS BY UJN. 
*             [PICKUSR] - PICK JOBS BY USER, FAMILY NAME. 
*             [PICKTRM] - PICK JOBS BY TERMINAL NAME. 
* 
*                  TMARG - REDUNDANT TIME ARGUMENT DIRECTIVE CRACKING.
* 
*             DFSCAN - *DAYFILE* LOG I/O AND MESSAGE PROCESSING.
*             [DFMSG] - ROUTINE MESSAGE PROCESSING. 
* 
*             ACSCAN - *ACCOUNT* LOG I/O AND MESSAGE PROCESSING.
*             [ACMSG] - ROUTINE MESSAGE PROCESSING. 
* 
*                  LOGTEST - CHECK FORMAT, EXTRACT START DATE/TIME. 
* 
*             JSNLOAD - JSN TRACE TABLE MANAGEMENT. 
*             [JSNTRAK] - MATCH/COLLECT JSN-S, JOB ATTRIBUTES.
*             [JSNLOOK] - JSN MATCH ONLY. 
*             [JSNLVL0] - HANDLE LEVEL 0 D/S EVENTS W/O DUPLICATION.
*             [JSNLIST] - TRACE TABLE SORT (OPTIONAL) AND PRINTOUT. 
* 
*             AMSLOAD - *ACCOUNT* MESSAGE ID TABLE AND STATISTICS.
*             [AMSMARK] - FLAG ID-S FOR SELECTION.
*             [AMSTEST] - ID MATCH, SELECTION TEST, TABULATION. 
*             [AMSLIST] - MESSAGE ID STATISTICS PRINTOUT. 
* 
*                  PARSE - COMMON TEXT PARSER.
  
**        COMMON BLOCKS.
* 
*         COMMON BLOCKS PROVIDE THE PRIMARY MEANS OF SHARING
*         INFORMATION BETWEEN MODULES.  AS WITH CODE MODULES, THEY ARE
*         ORGANIZED BY FUNCTIONAL AREA AND EACH IS DEFINED ONLY IN
*         THOSE MODULES WHICH NEED ACCESS TO ONE OR MORE VARIABLES IN 
*         THAT BLOCK.  OF NECESSITY, EACH BLOCK CONTAINS EXCLUSIVELY
*         EITHER NUMERIC OR TEXT STRING VARIABLES WHICH SIGNIFICANTLY 
*         INFLUENCES ORGANIZATION.  DEFINED COMMON BLOCKS ARE:  
* 
*         /ACL/  STRINGS, *ACCOUNT* LOG SPECIFIC VARIABLES. 
* 
*         /CTL/  NUMERIC, PROGRAM-WIDE VARIABLES & PARAMETERS.
* 
*         /DFL/  STRINGS, *DAYFILE* LOG SPECIFIC VARIABLES. 
* 
*         /SRT/  STRINGS, TRACE TABLE SORT KEY IDENTIFIERS. 
* 
*         /SYS/  STRINGS, PROGRAM-WIDE VARIABLES. 
* 
*         /TRC/  STRINGS, JSN TRACE TABLE.
  
**        SPECIAL TECHNIQUES. 
* 
*         THE PROGRAM INITIALIZATION SEQUENCE IS DESIGNED TO AVOID
*         CONFLICTS BETWEEN DIRECTIVES AND INFORMATION CONTAINED IN 
*         DATA TABLE FILES, AND TO AUTOMATICALLY ACCOMMODATE OMMISSION
*         OF INPUT FILES WHICH INDICATE RERUNS VERSUS INITIAL RAW LOGS
*         PROCESSING RUNS.
* 
*         THE USE OF TWO INDEPENDENT SUBROUTINES TO ENCAPSULATE I/O AND 
*         MESSAGE ANALYSIS FOR EACH RAW LOG ALLOWS THE MAIN PROGRAM TO
*         FOCUS ON SYNCHRONIZATION OF MESSAGES FROM BOTH LOGS INTO A
*         NEAR CAUSE-AND-EFFECT SEQUENCE FOR SUBSEQUENT PROCESSING. 
  
**        KNOWN LIMITATIONS.
* 
*         THE PROGRAM-S CAPACITY FOR DIRECTIVE ARGUMENTS, MESSAGE ID-S, 
*         UNIQUE JSN-S, AND JSN TRACE TABLE SORT KEYS ARE LIMITED BY
*         THEIR RESPECTIVE TABLE SIZES AND ULTIMATELY BY OVERALL
*         PROGRAM SIZE.  FOR PERFORMANCE REASONS, NO ATTEMPT HAS BEEN 
*         MADE TO ACCOMMODATE DYNAMIC TABLE MANAGEMENT OR OVERFLOW TO 
*         MASS STORAGE. 
  
  
      IMPLICIT INTEGER(A-Z) 
  
      PARAMETER (MXJ=1000)
*                            SIZE OF JSN TRACE TABLE. 
  
      PARAMETER (NK=8)
*                            NUMBER OF COMMAND KEYWORD PARAMETERS.
  
      EQUIVALENCE (ACSDTG,ACSDATE)
*                            /ACL/ ACSDTG*20 = ACSDATE*10 // ACSTIME*10.
  
      EQUIVALENCE (ACEDTG,ACEDATE)
*                            /ACL/ ACEDTG*20 = ACEDATE*10 // ACETIME*10.
  
      EQUIVALENCE (ACSYSID,ACTITLE) 
*                            /ACL/ ACSYSID*60 = ACTITLE*40//ACVERSN*20. 
  
      EQUIVALENCE (DFSDTG,DFSDATE)
*                            /DFL/ DFSDTG*20 = DFSDATE*10 // DFSTIME*10.
  
      EQUIVALENCE (DFEDTG,DFEDATE)
*                            /DFL/ DFEDTG*20 = DFEDATE*10 // DFETIME*10.
  
      EQUIVALENCE (DFSYSID,DFTITLE) 
*                            /DFL/ DFSYSID*60 = DFTITLE*40//DFVERSN*20. 
  
      CHARACTER*10  ACEDATE 
*                            /ACL/ (EQV) ACCOUNT LOG END DATE.
  
      CHARACTER*10  ACETIME 
*                            /ACL/ (EQV) ACCOUNT LOG END TIME.
  
      CHARACTER*20  ACEDTG
*                            /ACL/ ACCOUNT LOG END DATE/TIME GROUP. 
  
      LOGICAL       ACEOF 
*                            /CTL/ ACCOUNT LOG EOF FLAG.
  
      INTEGER       ACIN
*                            /CTL/ ACCOUNT LOG MESSAGE COUNTER. 
  
      CHARACTER*10  ACSDATE 
*                            /ACL/ (EQV) ACCOUNT LOG START DATE.
  
      CHARACTER*20  ACSDTG
*                            /ACL/ ACCOUNT LOG START DATE/TIME GROUP. 
  
      CHARACTER*10  ACSTIME 
*                            /ACL/ (EQV) ACCOUNT LOG START TIME.
  
      CHARACTER*60  ACSYSID 
*                            /ACL/ ACCOUNT LOG SYSTEM TITLE/VERSION.
  
      CHARACTER*40  ACTITLE 
*                            /ACL/ ACCOUNT LOG SYSTEM TITLE.
  
      CHARACTER*100 ACTXT 
*                            /ACL/ ACCOUNT LOG CURRENT MESSAGE TEXT.
  
      CHARACTER*20  ACVERSN 
*                            /ACL/ ACCOUNT LOG SYSTEM VERSION.
  
      CHARACTER*10  DATE
*                            TYPING FOR FTN5 FUNCTION.
  
      CHARACTER*7   DEF(NK) 
*                            *SECART* COMMAND KEYWORD DEFAULTS. 
  
      CHARACTER*10  DFEDATE 
*                            /DFL/ (EQV) DAYFILE LOG END DATE.
  
      CHARACTER*20  DFEDTG
*                            /DFL/ DAYFILE LOG END DATE/TIME GROUP. 
  
      CHARACTER*10  DFETIME 
*                            /DFL/ (EQV) DAYFILE LOG END TIME.
  
      LOGICAL       DFEOF 
*                            /CTL/ DAYFILE LOG EOF FLAG.
  
      INTEGER       DFIN
*                            /CTL/ DAYFILE LOG MESSAGE COUNTER. 
  
      CHARACTER*10  DFSDATE 
*                            /DFL/ (EQV) DAYFILE LOG START DATE.
  
      CHARACTER*20  DFSDTG
*                            /DFL/ DAYFILE LOG START DATE/TIME GROUP. 
  
      CHARACTER*10  DFSTIME 
*                            /DFL/ (EQV) DAYFILE LOG START TIME.
  
      CHARACTER*60  DFSYSID 
*                            /DFL/ DAYFILE LOG SYSTEM TITLE/VERSION.
  
      CHARACTER*40  DFTITLE 
*                            /DFL/ DAYFILE LOG SYSTEM TITLE.
  
      CHARACTER*20  DFVERSN 
*                            /DFL/ DAYFILE LOG SYSTEM VERSION.
  
      CHARACTER*100 DFTXT 
*                            /DFL/ DAYFILE LOG CURRENT MESSAGE TEXT.
  
      CHARACTER*1   DSU 
*                            /TRC/ DEADSTART UNIQUE PREFIX CODE.
  
      CHARACTER*7   FN(MXJ) 
*                            /TRC/ FAMILY NAME COLUMN IN TRACE TABLE. 
  
      CHARACTER*40  HDR 
*                            /SYS/ PRINTOUT HEADER TEXT.
  
      INTEGER       IPAGE 
*                            LOCAL PRINTOUT PAGE COUNTER. 
  
      INTEGER       JBLIMIT 
*                            /CTL/ UNIT JOB PRINTOUT MESSAGE LIMIT. 
  
      CHARACTER*1   JC(MXJ) 
*                            /TRC/ JOB CLASS COLUMN IN TRACE TABLE. 
  
      CHARACTER*7   JN(MXJ) 
*                            /TRC/ UJN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JS(MXJ) 
*                            /TRC/ D.JSN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JSN 
*                            TEMP - D.JSN VARIABLE. 
  
      CHARACTER*7   KWD(NK) 
*                            *SECART* COMMAND KEYWORD LIST. 
  
      CHARACTER*7   LFN(NK) 
*                            LFN LIST BUILT FROM *SECART* COMMAND.
  
      CHARACTER*5   MK(MXJ) 
*                            /TRC/ JOB SELECTION MARKS IN TRACE TABLE.
  
      INTEGER       ML(2,MXJ) 
*                            /CTL/ DFL/AFL MSG COUNTS FOR TRACE TABLE.
  
      INTEGER       NJ
*                            /CTL/ CURRENT NUMBER JOBS IN TRACE TABLE.
  
      CHARACTER*7   P 
*                            TEMP USED IN *SECART* COMMAND PROCESSING.
  
      CHARACTER*10  PGM 
*                            /SYS/ *SECART* VERSION ID FOR PRINTOUTS. 
  
      LOGICAL       PICKED
*                            TEMP FLAG USED IN UNIT JOB PRINTOUT. 
  
      CHARACTER*10  RUNDT 
*                            /SYS/ *SECART* RUN DATE FOR PRINTOUTS. 
  
      CHARACTER*10  RUNTM 
*                            /SYS/ *SECART* RUN TIME FOR PRINTOUTS. 
  
      CHARACTER*3   SKY(12) 
*                            /SRT/ TRACE TABLE SORT KEYS. 
  
      CHARACTER*20  TE(MXJ) 
*                            /TRC/ JOB DATE/TIME END IN TRACE TABLE.
  
      CHARACTER*10  TIME
*                            TYPING FOR FTN5 FUNCTION.
  
      CHARACTER*7   TN(MXJ) 
*                            /TRC/ JOB TERMINAL NAME IN TRACE TABLE.
  
      CHARACTER*20  TS(MXJ) 
*                            /TRC/ JOB DATE/TIME START IN TRACE TABLE.
  
      CHARACTER*6   UJSN
*                            TEMP - D.JSN VARIABLE. 
  
      CHARACTER*7   UN(MXJ) 
*                            /TRC/ JOB USERNAME IN TRACE TABLE. 
  
      CHARACTER*7   V 
*                            TEMP - VALUE USED IN COMMAND PROCESSING. 
  
* ACCOUNT LOG SPECIFIC VARIABLES. 
  
      COMMON /ACL/  ACSDATE 
      COMMON /ACL/  ACSTIME 
      COMMON /ACL/  ACEDATE 
      COMMON /ACL/  ACETIME 
      COMMON /ACL/  ACTITLE 
      COMMON /ACL/  ACVERSN 
      COMMON /ACL/  ACTXT 
  
* GLOBAL NUMERIC/LOGICAL VARIABLES AND PARAMETERS.
  
      COMMON /CTL/  NJ
      COMMON /CTL/  ACIN
      COMMON /CTL/  DFIN
      COMMON /CTL/  ACEOF 
      COMMON /CTL/  DFEOF 
      COMMON /CTL/  ML
      COMMON /CTL/  JBLIMIT 
  
* DAYFILE LOG SPECIFIC VARIABLES. 
  
      COMMON /DFL/  DFSDATE 
      COMMON /DFL/  DFSTIME 
      COMMON /DFL/  DFEDATE 
      COMMON /DFL/  DFETIME 
      COMMON /DFL/  DFTITLE 
      COMMON /DFL/  DFVERSN 
      COMMON /DFL/  DFTXT 
  
* JSN TRACE TABLE SORT PARAMETERS.
  
      COMMON /SRT/  SKY 
  
* GLOBAL STRING VARIABLES.
  
      COMMON /SYS/  HDR 
      COMMON /SYS/  PGM 
      COMMON /SYS/  RUNDT 
      COMMON /SYS/  RUNTM 
  
* JSN TRACE TABLE STORAGE.
  
      COMMON /TRC/  DSU 
      COMMON /TRC/  MK
      COMMON /TRC/  JN
      COMMON /TRC/  JS
      COMMON /TRC/  JC
      COMMON /TRC/  TS
      COMMON /TRC/  TE
      COMMON /TRC/  FN
      COMMON /TRC/  UN
      COMMON /TRC/  TN
  
      DATA ACEDTG  /' '/
      DATA ACEOF   /.FALSE./
      DATA ACIN    /0/
      DATA ACSDTG  /' '/
      DATA ACSYSID  /' '/ 
      DATA DFEDTG  /' '/
      DATA DFEOF   /.FALSE./
      DATA DFIN    /0/
      DATA DFSDTG  /' '/
      DATA DFSYSID  /' '/ 
      DATA DSU     /'A'/
      DATA FN      /MXJ*' '/
      DATA IPAGE   /1/
      DATA JBLIMIT /99999/
      DATA JC      /MXJ*' '/
      DATA JN      /MXJ*' '/
      DATA JS      /MXJ*' '/
      DATA MK      /MXJ*' '/
      DATA NJ      /0/
      DATA PGM     /' SECART V1'/ 
      DATA SKY     /12*'   '/ 
      DATA TE      /MXJ*' '/
      DATA TN      /MXJ*' '/
      DATA TS      /MXJ*' '/
      DATA UN      /MXJ*' '/
      DATA (KWD(I) ,LFN(I)   ,DEF(I),I=1,NK)/ 
     .      'D',   '0',      'DFLOG', 
     .      'A',   '0',      'ACLOG', 
     .      'C',   '0',      'COMBO', 
     .      'J',   '0',      'JOBS',
     .      'M',   '0',      'MSGID', 
     .      'T',   '0',      'TRACE', 
     .      'I',   'INPUT',  'INPUT', 
     .      'L',   'OUTPUT', 'OUTPUT'/
  
* ----------------------------------------------------------------------
* INITIALIZATION PHASE
* ----------------------------------------------------------------------
  
      RUNDT=DATE()
      RUNTM=TIME()
  
* PROCESS EXECUTION PARAMETERS. 
  
  100 CALL GETPARM(P,V,J) 
      IF (J.LT.0) GOTO 130
      DO 110 I=1,NK 
        IF (P.EQ.KWD(I)) GOTO 120 
  110 CONTINUE
      CALL REMARK('   *** UNRECOGNIZED PARAMETER: '//P) 
      GOTO 100
  
* SET TO VALUE OR DEFAULT.
  
  120 IF (J.EQ.1) THEN
        LFN(I)=DEF(I) 
      ELSE
        IF (I.EQ.8 .AND. V.EQ.'0') THEN 
          CALL REMARK('   *** LIST FILE REQUIRED.') 
        ELSE
          LFN(I)=V
        ENDIF 
      ENDIF 
      GOTO 100
  
* FIRST, OPEN LIST OUTPUT FILE. 
  
  130 OPEN (8,FILE=LFN(8))
  
* SECOND, LOAD ACCOUNT LOG MESSAGE IDENTIFIERS, IF ANY, 
* BEFORE DIRECTIVES TO AVOID AMNESIA PROBLEM. 
  
      IF (LFN(5).NE.'0') THEN 
        OPEN (5,FILE=LFN(5))
        CALL AMSLOAD
        CLOSE (5) 
      ENDIF 
  
* THIRD, PROCESS DIRECTIVES, IF ANY.
  
      IF (LFN(7).NE.'0') THEN 
        CALL REMARK(' READING DIRECTIVES...') 
        HDR='S E C A R T   D I R E C T I V E S '
        WRITE (8,10) HDR,PGM,RUNDT,RUNTM,IPAGE
  10    FORMAT('1',A40,3A10,' PG',I3) 
        OPEN (7,FILE=LFN(7))
        CALL DIRECT 
        CLOSE (7) 
      ENDIF 
  
* FOURTH, LOAD PREVIOUS JSN TRACE TABLE, IF ANY.
  
      IF (LFN(6).NE.'0') THEN 
        CALL REMARK(' LOADING TRACE TABLE...')
        OPEN (6,FILE=LFN(6))
        CALL JSNLOAD
        CLOSE (6) 
      ENDIF 
  
* ----------------------------------------------------------------------
* PHASE 1:  MERGE AND SCREEN RAW LOGS, BUILD TRACE TABLE AND PICK JOBS. 
* ----------------------------------------------------------------------
  
  
* PREVIEW EACH LOG TO OBTAIN SYSID, START DATE/TIME GROUP.
  
      IF (LFN(1).NE.'0') THEN 
        OPEN (1,FILE=LFN(1))
        CALL DFSCAN(LFN(1),*140)
      ELSE
        DFEOF=.TRUE.
      ENDIF 
  
* NOW, RAW ACCOUNT LOG. 
  
  140 IF (LFN(2).NE.'0') THEN 
        OPEN (2,FILE=LFN(2))
        CALL ACSCAN(LFN(2),*150)
      ELSE
        ACEOF=.TRUE.
      ENDIF 
  
* CHECK FOR NO RAW LOG INPUT. 
  
  150 IF (ACIN+DFIN.EQ.0) GOTO 210
      IPAGE=IPAGE+1 
      HDR='S C R E E N E D   M E S S A G E S' 
      WRITE (8,10) HDR,PGM,RUNDT,RUNTM,IPAGE
      IF (.NOT.DFEOF) WRITE (8,11) 'DAYFILE',DFSDTG,DFSYSID 
      IF (.NOT.ACEOF) WRITE (8,11) 'ACCOUNT',ACSDTG,ACSYSID 
  11  FORMAT(5X,A7,' FROM',A20 /5X,'SYSTEM ID:   ',A60) 
  
* IF BOTH LOGS, CHECK FOR SYSTEM ID OR DATE MISMATCHES. 
  
      IF (ACIN*DFIN.NE.0) THEN
        IF (ACSYSID.NE.DFSYSID) THEN
          CALL REMARK('   *** SYSTEM ID MISMATCH ***')
          STOP '   *** SECART TERMINATED.'
        ENDIF 
        IF (ACSDATE.NE.DFSDATE) THEN
          CALL REMARK('   *** LOG DATES MISMATCH.') 
        ENDIF 
      ENDIF 
  
* ANNOTATED LOG DATA MUST BE WRITTEN TO COMBO LOG FILE. 
  
      IF (LFN(3).EQ.'0') LFN(3)='TAPE3' 
      OPEN (3,FILE=LFN(3))
  
* RECORD SOURCE LOG IDENTIFICATIONS IN COMPOSITE LOG. 
  
      IF (DFSDATE.NE.' ') 
     .  WRITE (3,13) DFSTIME,'- DAYFILE   ',DFSDATE,DFSYSID 
      IF (ACSDATE.NE.' ') 
     .  WRITE (3,13) ACSTIME,' +ACCOUNT   ',ACSDATE,ACSYSID 
  13  FORMAT(A10,8X,A12,A10,A60)
  
      CALL REMARK(' DIGESTING RAW LOG(S)...') 
      IF (DFEOF) GOTO 170 
  
* SYNCHRONIZE PROCESSING AND MERGE LOGS.
  
  160 CALL DFMSG(*180)
      IF (.NOT.ACEOF .AND. ACEDTG.LT.DFEDTG) GOTO 170 
      GOTO 160
  
* BIAS TO CLUMP DFL MSGS BEFORE ACL MSGS IN SAME SECOND.
* SOME ACCOUNT LOG MSID-S TWEAK DTG TO PRECEDE DAYFILE MSG. 
  
  170 CALL ACMSG(*190)
      IF (.NOT.DFEOF .AND. DFEDTG.LE.ACEDTG) GOTO 160 
      GOTO 170
  
* END-OF-FILE DECISIONS.
  
  180 CLOSE (1) 
      IF (.NOT.ACEOF) GOTO 170
      GOTO 200
  
  190 CLOSE (2) 
      IF (.NOT.DFEOF) GOTO 160
  
* COMPLETED MERGE PASS (BURP!). 
  
  200 CLOSE (3) 
  
* ----------------------------------------------------------------------
* PHASE 2:  INTERMEDIATE PRINTOUTS. 
* ----------------------------------------------------------------------
  
* PRINTOUT ACCOUNT MESSAGE STATISTICS.
  
      IF (ACIN.GT.0) THEN 
        CALL REMARK(' ACCOUNT MSG STATISTICS...') 
        CALL AMSLIST
      ENDIF 
  
* PRINTOUT JSN/USER/TERMINAL TRACE TABLE (SORT OPTIONAL). 
  
  210 IF (NJ.GT.0) THEN 
        CALL REMARK(' TRACE TABLE PRINTOUT...') 
  
* UNIT 6 FILE REQUIRED FOR TRACE TABLE OUTPUT.
  
        IF (LFN(6).EQ.'0') LFN(6)='TAPE6' 
        OPEN (6,FILE=LFN(6))
        OPEN (9,STATUS='SCRATCH') 
        CALL JSNLIST(LFN(6))
        CLOSE (6) 
        CLOSE (9) 
      ENDIF 
  
* ----------------------------------------------------------------------
* PHASE 3:  SORT COMPOSITE LOG BY UNIQUE JSN TO GROUP INTO UNIT JOBS. 
* ----------------------------------------------------------------------
  
* SORT UNIT 3 COMPOSITE LOG, IF PRODUCED/PROVIDED, TO UNIT 4 JOBS FILE, 
* REQUIRED FOR OUTPUT.
  
      IF (LFN(3).EQ.'0') GOTO 220 
      OPEN (3,FILE=LFN(3))
      REWIND 3
      IF (LFN(4).EQ.'0') LFN(4)='TAPE4' 
      OPEN (4,FILE=LFN(4))
      CALL REMARK(' SORTING OUT JOBS...') 
      CALL SM5SORT(0) 
      CALL SM5ENR(ACIN+DFIN)
      CALL SM5FROM(LFN(3))
      CALL SM5TO(LFN(4))
      CALL SM5KEY(11,6,'DISPLAY','A') 
      CALL SM5RETA('YES') 
      CALL SM5END 
      CLOSE (3) 
      CLOSE (4) 
  
* ----------------------------------------------------------------------
* PHASE 4:  EXTRACT UNIT JOBS FROM JOBS LOG FOR PRINTOUT. 
* ----------------------------------------------------------------------
  
  220 IF (LFN(4).EQ.'0') GOTO 250 
      OPEN (4,FILE=LFN(4))
      REWIND 4
      CALL REMARK(' EXTRACTING SELECTED JOBS...') 
      IPAGE=IPAGE+1 
      HDR='S E L E C T E D   J O B S' 
      WRITE (8,10) HDR,PGM,RUNDT,RUNTM,IPAGE
      UJSN=' '
  
  230 READ (4,14,END=240) DFTXT 
  14  FORMAT(A100)
      JSN=DFTXT(11:16)
      IF (JSN.NE.UJSN) THEN 
        UJSN=JSN
        CALL JSNLOOK(JSN,N) 
        PICKED=MK(N).NE.'     ' 
        IF (PICKED) THEN
          WRITE (8,18)
  18      FORMAT('0') 
          J=JBLIMIT 
        ENDIF 
      ENDIF 
  
* PRINTOUT JOB TILL SAMPLE LIMIT. 
  
      IF (PICKED) THEN
        IF (J.GT.0) THEN
          WRITE (8,14) DFTXT
          J=J-1 
          IF (J.EQ.0) WRITE (8,*) 
     .      '  ========= S A M P L E   L I M I T =========' 
        ENDIF 
      ENDIF 
      GOTO 230
  
  240 CLOSE (4) 
  
* FINISHED. 
  
  250 CALL REMARK(' SECART COMPLETED.') 
      CLOSE (8) 
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE DIRECT 
**        DIRECT - SECART DIRECTIVES PROCESSING.
* 
*         THIS MODULE HANDLES ALL ASPECTS OF DIRECTIVES PROCESSING AND
*         PROVIDES MULTIPLE ENTRY POINT FOR PURPOSES SUCH AS: ACCEPTING 
*         *SECART* DIRECTIVES DURING INITIALIZATION PHASE AND STORING 
*         SELECTION ARGUMENTS IN INTERNAL ARRAYS, MARKING ACCOUNT LOG 
*         MESSAGE ID-S FOR PRINTOUT SELECTION, AND CHECKING LOG DATA
*         AGAINST SELECTION ARGUMENTS DURING RAW LOGS PROCESSING. 
  
  
      IMPLICIT INTEGER(A-Z) 
      PARAMETER (MXJ=1000)
*                            SIZE OF JSN TRACE TABLE. 
  
      PARAMETER (MXP=50)
*                            SIZE OF DIRECTIVE ARGUMENT TABLES. 
  
      LOGICAL       ACEOF 
*                            /CTL/ ACCOUNT LOG EOF FLAG.
  
      INTEGER       ACIN
*                            /CTL/ ACCOUNT LOG MESSAGE COUNTER. 
  
      LOGICAL       DFEOF 
*                            /CTL/ DAYFILE LOG EOF FLAG.
  
      INTEGER       DFIN
*                            /CTL/ DAYFILE LOG MESSAGE COUNTER. 
  
      CHARACTER*80  DIR 
*                            *SECART* DIRECTIVE TEXT STRING.
  
      LOGICAL       ERR 
*                            DIRECTIVE ERROR(S) FLAG. 
  
      CHARACTER*10  ETM 
*                            ARG - MESSAGE TIMESTAMP. 
  
      CHARACTER*7   FAM(MXP)
*                            USER= DIRECTIVE FAMILYNAME ARGUMENTS.
  
      CHARACTER*7   FAMILY
*                            TEMP - FAMILYNAME VARIABLE.
  
      CHARACTER*7   FN
*                            ARG - FAMILYNAME TO CHECK. 
  
      LOGICAL       HIT 
*                            ARG - FLAG RETURNED TO SHOW SELECTION. 
  
      INTEGER       ITX(MXP)
*                            DMSG= DIRECTIVE CHARACTER START POSITIONS. 
  
      INTEGER       IW
*                            LOCAL - CURRENT TIME WINDOW INDEX. 
  
      INTEGER       JBLIMIT 
*                            /CTL/ UNIT JOB PRINTOUT MESSAGE LIMIT. 
  
      CHARACTER*7   JN
*                            ARG - JOBNAME TO CHECK.
  
      CHARACTER*7   JOBNAME 
*                            TEMP - JOBNAME VARIABLE. 
  
      CHARACTER*6   JS
*                            ARG - JSN TO CHECK.
  
      CHARACTER*6   JSN(MXP)
*                            JSN= DIRECTIVE ARGUMENTS.
  
      INTEGER       LTX(MXP)
*                            DMSG= DIRECTIVE LAST CHARACTER POSITIONS.
  
      CHARACTER*4   MID 
*                            TEMP - FOR AMSG= DIRECTIVE MSG ID. 
  
      CHARACTER*5   MK
*                            ARG - TRACE TABLE MARKS TO BE UPDATED. 
  
      INTEGER       ML(2,MXJ) 
*                            /CTL/ DFL/AFL MSG COUNTS FOR TRACE TABLE.
  
      CHARACTER*40  MTX(MXP)
*                            DMSG= DIRECTIVE MESSAGE STRINGS. 
  
      INTEGER       NJ
*                            /CTL/ CURRENT NUMBER JOBS IN TRACE TABLE.
  
      INTEGER       NM
*                            NUMBER OF DMSG= ARGUMENTS STORED.
  
      INTEGER       NN
*                            NUMBER OF UJN= ARGUMENTS STORED. 
  
      INTEGER       NP
*                            NUMBER OF UJN= ARGUMENTS STORED. 
  
      INTEGER       NS
*                            NUMBER OF JSN= ARGUMENTS STORED. 
  
      INTEGER       NT
*                            NUMBER OF TRM= ARGUMENTS STORED. 
  
      INTEGER       NU
*                            NUMBER OF USER= ARGUMENTS STORED.
  
      CHARACTER*3   SKY(12) 
*                            /SRT/ TRACE TABLE SORT KEYS. 
  
      CHARACTER*7   TERMINL 
*                            TEMP - TRM= VARIABLE.
  
      CHARACTER*10  TME(MXP)
*                            TIME= DIRECTIVE TIME END ARGUMENTS.
  
      CHARACTER*10  TMS(MXP)
*                            TIME= DIRECTIVE TIME START ARGUMENTS.
  
      CHARACTER*7   TN
*                            ARG - TERMINAL ID TO CHECK.
  
      CHARACTER*7   TRM(MXP)
*                            TRM= DIRECTIVE ARGUMENTS.
  
      CHARACTER*80  TXT 
*                            ARG - MESSAGE TEXT TO CHECK. 
  
      CHARACTER*7   UJN(MXP)
*                            UJN= DIRECTIVE ARGUMENTS.
  
      CHARACTER*7   UN
*                            ARG - USERNAME TO CHECK. 
  
      CHARACTER*7   USER
*                            TEMP - USERNAME VARIABLE.
  
      CHARACTER*7   USR(MXP)
*                            USER= DIRECTIVE ARGUMENTS. 
  
      LOGICAL       WINDOW
*                            FLAG TO REMEMBER TIME WINDOW IS OPEN.
  
  
* GLOBAL NUMERIC/LOGICAL VARIABLES AND PARAMETERS.
  
      COMMON /CTL/  NJ
      COMMON /CTL/  ACIN
      COMMON /CTL/  DFIN
      COMMON /CTL/  ACEOF 
      COMMON /CTL/  DFEOF 
      COMMON /CTL/  ML
      COMMON /CTL/  JBLIMIT 
  
* JSN TRACE TABLE SORT PARAMETERS.
  
      COMMON /SRT/  SKY 
  
      DATA FAM      /MXP*' '/ 
      DATA ITX      /MXP*0/ 
      DATA JSN      /MXP*' '/ 
      DATA LTX      /MXP*0/ 
      DATA MTX      /MXP*' '/ 
      DATA NM       /0/ 
      DATA NN       /0/ 
      DATA NP       /0/ 
      DATA NS       /0/ 
      DATA NT       /0/ 
      DATA NU       /0/ 
      DATA TME      /MXP*' '/ 
      DATA TMS      /MXP*' '/ 
      DATA TRM      /MXP*' '/ 
      DATA UJN      /MXP*' '/ 
      DATA USR      /MXP*' '/ 
  
  
**        ENTRY -  CALL DIRECT  [NO ARGUMENTS]. 
*                  UNIT 7 FILE CONTAINS DIRECTIVES INPUT. 
* 
*         EXIT -   UNIT 8 FILE CONTAINS PRINTOUT OF DIRECTIVES. 
*                  ARRAYS WITHIN MODULE CONTAIN SELECTION ARGUMENTS.
* 
*         ERROR -  MESSAGES IN PRINTOUT AND DAYFILE:  
*                  *** UNRECOGNIZED DIRECTIVE *** 
*                  *** TOO MANY ARGUMENTS, EXCESS IGNORED.
*                  *** DIRECTIVE ERROR(S).  [DAYFILE] 
* 
*         USES -   /CTL/ TO SET JBLIMIT.
*                  /SRT/ TO STORE JSN TRACE TABLE SORT KEYS IN SKY(I).
* 
*         CALLS -  *PARSE* TO EXTRACT WORDS FROM DIRECTIVES.
*                  *TMARG* TO EXTRACT TIME ARGUMENTS FROM DIRECTIVES. 
*                  *AMSMARK* TO MARK ACCOUNT MESSAGE ID-S FOR SELECTION.
* 
*         NOTES -  ARRAYS FOR STORAGE OF SELECTION ARGUMENTS ARE ALL
*                  SAME SIZE, DEFINED VIA PARAMETER FOR CODE SIMPLICITY.
* 
* 
*         DIRECTIVES -
* 
*         AMSG=MSID,...        SCAN ACCOUNT MSG IDENTIFIERS FOR PRINT.
* 
*         DMSG=[NN:]TEXT_STR   SCAN DAYFILE TEXT STRING FOR PRINTOUT. 
*                              NN IS START CHR [1-80] W/IN TEXT FIELD.
* 
*         TIME=HHMMSS[-HHMMSS] SCAN TIME PERIOD FOR PRINTOUT.  EITHER 
*          (OR) HH.MM.SS.      FORMAT ACCEPTED, SECONDS OPTIONAL, END 
*                              TIME OPTIONAL BUT REQUIRES '-' SEPARATOR.
* 
*         TRACE=KEY,...        SORT KEYS FOR TRACE TABLE PRINTOUT.
*                              VALID KEYS: UJN,JSN,JC,SDT,EDT,FM,UN,TRM.
* 
*         USER=FAMILY,USER     SELECT JOBS FOR PRINTOUT BY USER NAME/ 
*                              INDEX (VIA *SUI* COMMANDS).
*                              USE BLANK OR OMIT FOR DEFAULT FAMILY.
*                              USE * FOR WILDCARD MATCH.  (NOTE THAT
*                              USER=*,* SELECTS EVERY JOB!!)
* 
*         UJN=JOBNAME,...      SELECT JOBS FOR PRINTOUT BY JOBNAME. 
* 
*         JSN=[D.]AAAA,...     SELECT UNIT JOBS FOR PRINTOUT BY JSN.
*                              OPTIONAL PREFIX IS D/S UNIQUE CODE USED
*                              TO RESOLVE JSN AMBIGUITIES ACROSS LEVEL
*                              ZERO DEADSTARTS. 
* 
*         TRM=TERMID,...       SELECT JOBS FOR PRINTOUT BY TERMINAL ID. 
* 
*         LIMIT=NNNN           LIMIT JOB PRINTOUTS TO NNNN LINES EACH.
  
* EACH DIRECTIVE LINE.
  
  100 READ (7,10,END=190) DIR 
  10  FORMAT(A80) 
      WRITE (8,*) '  //// ',DIR 
  
* DIRECTIVE:  AMSG=MSID,MSID... 
* ACCOUNT LOG MSG ID-S FOR SERIAL PRINTOUT. 
  
      IF (DIR(1:5).EQ.'AMSG=') THEN 
        I=6 
  
  110   CALL PARSE(DIR,I,MID) 
        IF (MID.NE.' ') THEN
          CALL AMSMARK(MID,'*') 
          GOTO 110
        ENDIF 
  
* DIRECTIVE:  DMSG=NN:TEXT STRING...[40]. 
* DAYFILE LOG TEXT STRING FOR SERIAL PRINTOUT.
  
      ELSE IF (DIR(1:5).EQ.'DMSG=') THEN
        NM=NM+1 
        I=6 
        N=INDEX('0123456789',DIR(I:I))
        IF (N.GT.0) THEN
          ITX(NM)=N-1 
          I=I+1 
          N=INDEX('0123456789',DIR(I:I))
          IF (N.GT.0) THEN
            ITX(NM)=10*ITX(NM)+(N-1)
            I=I+1 
          ENDIF 
  
* COLON REQUIRED WITH CHAR POSITION.
  
          IF (DIR(I:I).EQ.':') THEN 
            I=I+1 
  
* OTHERWISE USE AS TEXT STRING. 
  
          ELSE
            I=6 
            ITX(NM)=0 
          ENDIF 
        ENDIF 
        MTX(NM)=DIR(I:I+39) 
        LTX(NM)=1 
        DO 120 I=1,40 
          IF (MTX(NM)(I:I).NE.' ') LTX(NM)=I
  120   CONTINUE
  
* DIRECTIVE:  TIME=START[,END]
* TIME PERIOD FOR SERIAL PRINTOUT.
  
      ELSE IF (DIR(1:5).EQ.'TIME=') THEN
        I=6 
        IF (NP.GE.MXP) GOTO 180 
        CALL TMARG(DIR,I,TMS(NP+1)) 
        TME(NP)=TMS(NP) 
        IF (DIR(I-1:I-1).EQ.'-') CALL TMARG(DIR,I,TME(NP+1))
        IF (TMS(NP+1).NE.' '.AND.TME(NP+1).NE.' ') NP=NP+1
        WINDOW=.FALSE.
  
* DIRECTIVE:  TRACE=KEY,KEY,... 
* SORT KEYS FOR TRACE TABLE PRINTOUT. 
* VALID KEYS: UJN,JSN,JC,SDT,EDT,FM,UN,TRM. 
  
      ELSE IF (DIR(1:6).EQ.'TRACE=') THEN 
        I=7 
        DO 130 N=1,12 
        CALL PARSE(DIR,I,SKY(N))
  130   CONTINUE
  
* DIRECTIVE:  USER=FAMILY,USER. 
* FAMILY & USERNAME PAIR W/WILDCARDS. 
  
      ELSE IF (DIR(1:5).EQ.'USER=') THEN
        I=6 
        CALL PARSE(DIR,I,FAMILY)
        CALL PARSE(DIR,I,USER)
        IF (NU.GE.MXP) GOTO 180 
        NU=NU+1 
        FAM(NU)=FAMILY
        USR(NU)=USER
  
* DIRECTIVE:  UJN=JOBNAME,... 
* USER JOB NAME FOR JOB SELECTION.
  
      ELSE IF (DIR(1:4).EQ.'UJN=') THEN 
        I=5 
  140   CALL PARSE(DIR,I,JOBNAME) 
        IF (JOBNAME.NE.' ') THEN
          IF (NN.GE.MXP) GOTO 180 
          NN=NN+1 
          UJN(NN)=JOBNAME 
          GOTO 140
        ENDIF 
  
* DIRECTIVE:  JSN=[D.]AAAA,...
* JOB SEQUENCE NAME (AAAA) W/ OPTIONAL D/S UNIQUE CODE (D.).
  
      ELSE IF (DIR(1:4).EQ.'JSN=') THEN 
        I=5 
  150   IF(NS.GE.MXP) GOTO 180
        JSN(NS+1)=' ' 
        CALL PARSE(DIR,I,JSN(NS+1)(3:6))
        IF (JSN(NS+1).NE.' ') THEN
          NS=NS+1 
          IF (JSN(NS)(2:2).EQ.' ' .AND. DIR(I-1:I-1).EQ.'.') THEN 
            JSN(NS)(1:1)=JSN(NS)(3:3) 
            JSN(NS)(2:2)='.'
            CALL PARSE(DIR,I,JSN(NS)(3:6))
          ELSE
            JSN(NS)(1:2)='*.' 
          ENDIF 
          GOTO 150
        ENDIF 
  
* DIRECTIVE:  TRM=TERMID,...
* TERMINAL NAMES SELECTION DIRECTIVE. 
  
      ELSE IF (DIR(1:4).EQ.'TRM=') THEN 
        I=5 
  
  160   CALL PARSE(DIR,I,TERMINL) 
        IF (TERMINL.NE.' ') THEN
          IF (NT.GE.MXP) GOTO 180 
          NT=NT+1 
          TRM(NT)=TERMINL 
          GOTO 160
        ENDIF 
  
* DIRECTIVE:  LIMIT=NNNN
* SAMPLE LIMIT FOR PRINTOUTS. 
  
      ELSE IF (DIR(1:6).EQ.'LIMIT=') THEN 
        I=7 
        JBLIMIT=0 
  
  170   N=ICHAR(DIR(I:I))-16
        IF(N.GE.0.AND.N.LE.9.AND.I.LE.12) THEN
          JBLIMIT=JBLIMIT*10+N
          I=I+1 
          GOTO 170
        ENDIF 
  
* UNRECOGNIZED DIRECTIVE VERB.
  
      ELSE
        WRITE (8,*) '  *** UNRECOGNIZED DIRECTIVE ***'
        ERR=.TRUE.
      ENDIF 
      GOTO 100
  
* ARGUMENT TABLE FULL, IGNORE ADDITIONAL ARGUMENTS. 
  
  180 WRITE (8,*) '  *** TOO MANY ARGUMENTS, EXCESS IGNORED.' 
      ERR=.TRUE.
      GOTO 100
  
* FINISHED WITH DIRECTIVES, REPORT IF ERRORS. 
  
  190 IF (ERR) CALL REMARK('   *** DIRECTIVE ERROR(S).')
      RETURN
  
  
* --------------------------------------------------------------------- 
* SERIAL PRINTOUT SELECTIONS. 
* --------------------------------------------------------------------- 
  
**        ENTRY -  CALL TMCHECK(ETM,HIT)
*                  *ETM* CONTAINS TIMESTAMP FROM LOG MESSAGE. 
* 
*         EXIT -   *HIT* SET TO .TRUE. IF *ETM* FALLS WITHIN ANY TIME 
*                  WINDOW, OTHERWISE UNCHANGED (AVOID CONFLICT WITH 
*                  OTHER SELECTION IN CALLING ROUTINE). 
* 
*         PRINTOUT (UNIT 8) MESSAGES: 
*                  ====== TIME WINDOW START ======
*                  ====== TIME WINDOW END ======
* 
*         NOTES -  THIS ROUTINE REMEMBERS INDEX OF OPEN TIME WINDOW IN
*                  *IW* TO SHORTCUT SEARCH AND TEST.
  
  
      ENTRY TMCHECK(ETM,HIT)
  
      IF (NP.LE.0) RETURN 
  
* CHECK FOR END OF CURRENT WINDOW, IF ANY.
  
      IF (WINDOW) THEN
        IF (ETM.LE.TME(IW)) THEN
          HIT=.TRUE.
          RETURN
        ELSE
          WINDOW=.FALSE.
          WRITE (8,*) '  ====== TIME WINDOW END ======' 
        ENDIF 
      ENDIF 
  
* CHECK FOR START OF ANY TIME WINDOW. 
  
      DO 200 I=1,NP 
        IF (ETM.LT.TMS(I) .OR. ETM.GT.TME(I)) GOTO 200
        IW=I
        WINDOW=.TRUE. 
        WRITE (8,*) '  ====== TIME WINDOW START ======' 
  200 CONTINUE
      RETURN
  
  
**        ENTRY -  CALL MSCHECK(TXT,HIT)
*                  *TXT* IS MESSAGE FIELD FROM DAYFILE MESSAGE. 
* 
*         EXIT -   *HIT* SET TO .TRUE. IF *TXT* CONTAINS SELECTED TEXT
*                  STRING, .FALSE. OTHERWISE. 
  
      ENTRY MSCHECK(TXT,HIT)
  
      IF (NM.EQ.0) RETURN 
      DO 210 N=1,NM 
        IF (ITX(N).EQ.0) THEN 
          IF (INDEX(TXT,MTX(N)(1:LTX(N))).NE.0) HIT=.TRUE.
        ELSE
          IF (TXT(ITX(N):ITX(N)+LTX(N)-1).EQ.MTX(N)(1:LTX(N)))
     .      HIT=.TRUE.
        ENDIF 
        IF (HIT) RETURN 
  210 CONTINUE
      RETURN
  
  
* --------------------------------------------------------------------- 
* JOB SELECTION ENTRY POINTS. 
* CALLED DURING 1ST PASS TO TAG PICKS IN TRACE TABLE. 
* --------------------------------------------------------------------- 
  
  
**        ENTRY -  CALL PICKJSN(JS,MK)
*                  *JS*  IS JSN FROM LOG MESSAGE. 
*                  *MK*  IS MARKS FIELD FOR JOB IN JSN TRACE TABLE. 
* 
*         EXIT -   *MK(1:1)* SET TO 'J' IF JSN WAS SELECTED.
  
      ENTRY PICKJSN(JS,MK)
  
* CHECK NEW JSN AGAINST EACH SELECTED JSN, IF ANY.
  
      IF (NS.EQ.0) RETURN 
      DO 220 I=1,NS 
        IF ( (JS(3:6).EQ.JSN(I)(3:6)) .AND. 
     .    (JS(1:1).EQ.JSN(I)(1:1) .OR. JSN(I)(1:1).EQ.'*') )MK(1:1)='J' 
  220 CONTINUE
      RETURN
  
  
**        ENTRY -  CALL PICKUJN(JN,MK)
*                  *JN*  IS UJN FROM LOG MESSAGE. 
*                  *MK*  IS MARKS FIELD FOR JOB IN JSN TRACE TABLE. 
* 
*         EXIT -   *MK(2:2)* SET TO 'N' IF UJN WAS SELECTED.
  
      ENTRY PICKUJN(JN,MK)
  
* CHECK EACH NEW UJN AGAINST EACH SELECTED UJN-S, IF ANY. 
  
      IF (NN.EQ.0) RETURN 
      DO 230 I=1,NN 
        IF (JN.EQ.UJN(I)) MK(2:2)='N' 
  230 CONTINUE
      RETURN
  
  
**        ENTRY -  CALL PICKUSR(FN,UN,MK) 
*                  *FN*  IS FAMILYNAME FROM LOG MESSAGE.
*                  *UN*  IS USERNAME FROM LOG MESSAGE.
*                  *MK*  IS MARKS FIELD FOR JOB IN JSN TRACE TABLE. 
* 
*         EXIT -   *MK(3:3)* SET TO 'U' IF FAMILY/USER WAS SELECTED.
  
      ENTRY PICKUSR(FN,UN,MK) 
  
* CHECK NEW USERID AGAINST EACH SELECTED FAMILY AND USER PAIR.
* WILDCARD (*) MATCHES ANYTHING.  BLANK FAMILY MATCHES DEFAULT FAMILY.
  
      IF (NU.EQ.0) RETURN 
      DO 240 I=1,NU 
        IF ( (FAM(I).EQ.'*'.OR.FN.EQ.FAM(I)) .AND.
     .    (USR(I).EQ.'*'.OR.USR(I).EQ.UN) ) MK(3:3)='U' 
  240 CONTINUE
      RETURN
  
  
**        ENTRY -  CALL PICKTRM(TN,MK)
*                  *TN*  IS TERMINAL ID FROM LOG MESSAGE. 
*                  *MK*  IS MARKS FIELD FOR JOB IN JSN TRACE TABLE. 
* 
*         EXIT -   *MK(4:4)* SET TO 'T' IF TERMINAL ID WAS SELECTED.
  
      ENTRY PICKTRM(TN,MK)
  
* CHECK NEW TERMINAL ID AGAINST EACH SELECTED TERMINAL ID, IF ANY.
  
      IF (NT.EQ.0) RETURN 
      DO 250 I=1,NT 
        IF (TN.EQ.TRM(I)) MK(4:4)='T' 
  250 CONTINUE
      RETURN
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE TMARG(DIR,IS,TIMEX)
**        TMARG -  EXPANDS TIME= DIRECTIVE ARGUMENTS TO FIXED FORMAT. 
* 
*         *TMARG* ACCEPTS TIME ARGUMENTS IN A VARIETY OF FORMATS AND
*         EXPANDS INTO A CANONICAL FIXED FORMAT FOR USE IN TIME WINDOW
*         SELECTION OF MESSAGES FOR SERIAL PRINTOUT.
* 
*         ENTRY -  CALL TMARG(DIR,IS,TIMEX) 
*                  *DIR*   IS DIRECTIVE CONTAINING TIME= ARGS.
*                  *IS*    IS STRING POSITION OF TIME ARGUMENT. 
* 
*         EXIT -   *TIMEX* WILL CONTAIN FIXED FORMAT TIME ARGUMENT. 
* 
*         ERROR -  PRINTOUT (UNIT 8): 
*                  *** TIME ARGUMENT ERROR. 
* 
*         NOTES -  FTN5 INDEX FUNCTION IS USED TO TEST FOR DIGITS AND 
*                  NUMERIC RANGE AT SAME TIME.  ACCEPTED FORMS ARE: 
*                    HOURS -    HH-    HH.        REQUIRED. 
*                    MINUTES -    MM-     MM.     OPTIONAL. 
*                    SECONDS -      SS-      SS.  OPTIONAL W/MINUTES. 
*                    ---------------------------- 
*                    EXPANDED TO =>  ' HH.MM.SS.' CANONICAL FORM. 
  
      IMPLICIT INTEGER(A-Z) 
  
      CHARACTER*80  DIR 
*                            ARG - DIRECTIVE TEXT STRING. 
  
      INTEGER       IS
*                            ARG - START POSITION FOR TIME ARGUMENT.
  
      CHARACTER*10  TIMEX 
*                            ARG - FIXED FORMAT TIME RETURNED.
  
* SET DEFAULT RESULT. 
  
      TIMEX=' 00.00.00.'
  
* HOURS PORTION OF TIMESTAMP. 
  
      IF (INDEX('012',DIR(IS:IS)).NE.0) THEN
        TIMEX(2:2)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
  
      IF (INDEX('0123456789',DIR(IS:IS)).NE.0) THEN 
        TIMEX(3:3)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
      IF (DIR(IS:IS).EQ.'.') IS=IS+1
      IF (DIR(IS:IS).EQ.'-') GOTO 100 
  
* MINUTES PORTION OF TIMESTAMP. 
  
      IF (INDEX('012345',DIR(IS:IS)).NE.0) THEN 
        TIMEX(5:5)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
  
      IF (INDEX('0123456789',DIR(IS:IS)).NE.0) THEN 
        TIMEX(6:6)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
      IF (DIR(IS:IS).EQ.'.') IS=IS+1
      IF (DIR(IS:IS).EQ.'-') GOTO 100 
  
* SECONDS PORTION OF TIMESTAMP. 
  
      IF (INDEX('012345',DIR(IS:IS)).NE.0) THEN 
        TIMEX(8:8)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
  
      IF (INDEX('0123456789',DIR(IS:IS)).NE.0) THEN 
        TIMEX(9:9)=DIR(IS:IS) 
        IS=IS+1 
      ELSE
        GOTO 110
      ENDIF 
      IF (DIR(IS:IS).EQ.'.') IS=IS+1
      IF (DIR(IS:IS).NE.'-') RETURN 
  
  100 IS=IS+1 
      RETURN
  
* TIMESTAMP ARGUMENT ERROR. 
  
  110 WRITE (8,*) '  *** TIME ARGUMENT ERROR.'
      TIMEX=' ' 
      RETURN
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE DFSCAN(LFN,*)
**        DFSCAN - DAYFILE LOG MESSAGE PROCESSING.
* 
*         *DFSCAN* PROVIDES THE PRIMARY ROUTINES FOR PROCESSING DAYFILE 
*         LOG MESSAGES.  IT PROVIDES AN ENTRY POINT TO PRE-SCAN THE LOG 
*         FILE TO VALIDATE FORMAT AND EXTRACT CRITICAL SYSTEM ID AND
*         DATE/TIME DATA, AND ANOTHER FOR ROUTINE PROCESSING OF EACH
*         LOG MESSAGE IN THE SEQUENCE CONTROLLED BY *SECART*. ANNOTATED 
*         MESSAGES ARE WRITTEN TO COMPOSITE LOG FILE ON UNIT 3. 
  
  
      IMPLICIT INTEGER(A-Z) 
  
      PARAMETER     (MXJ=1000)
*                            SIZE OF JSN TRACE TABLE. 
  
      EQUIVALENCE   (DFEDTG,DFEDATE)
*                            /DFL/ DFEDTG*20 = DFEDATE*10//DFETIME*10.
  
  
      LOGICAL       ACEOF 
*                            /CTL/ ACCOUNT LOG EOF FLAG.
  
      INTEGER       ACIN
*                            /CTL/ ACCOUNT LOG MESSAGE COUNTER. 
  
      LOGICAL       DFEOF 
*                            /CTL/ DAYFILE LOG EOF FLAG.
  
      CHARACTER*10  DFEDATE 
*                            /DFL/ (EQV) DAYFILE LOG END DATE.
  
      CHARACTER*20  DFEDTG
*                            /DFL/ (EQV) DAYFILE LOG END DATE/TIME. 
  
      CHARACTER*10  DFETIME 
*                            /DFL/ (EQV) DAYFILE LOG END TIME.
  
      INTEGER       DFIN
*                            /CTL/ DAYFILE LOG MESSAGE COUNTER. 
  
      CHARACTER*10  DFSDATE 
*                            /DFL/ (EQV) DAYFILE LOG START DATE.
  
      CHARACTER*10  DFSTIME 
*                            /DFL/ (EQV) DAYFILE LOG START TIME.
  
      CHARACTER*40  DFTITLE 
*                            /DFL/ DAYFILE SYSTEM TITLE.
  
      CHARACTER*100 DFTXT 
*                            /DFL/ CURRENT DAYFILE MESSAGE TEXT.
  
      CHARACTER*20  DFVERSN 
*                            /DFL/ SYSTEM VERSION (PART OF SYID). 
  
      CHARACTER*1   DSU 
*                            /TRC/ DEADSTART UNIQUE PREFIX CODE.
  
      CHARACTER*7   FAM 
*                            TEMP - FAMILYNAME VARIABLE.
  
      CHARACTER*7   FN(MXJ) 
*                            /TRC/ FAMILY NAME COLUMN IN TRACE TABLE. 
  
      INTEGER       JBLIMIT 
*                            /CTL/ UNIT JOB PRINTOUT MESSAGE LIMIT. 
  
      CHARACTER*1   JC(MXJ) 
*                            /TRC/ JOB CLASS COLUMN IN TRACE TABLE. 
  
      CHARACTER*1   JCL 
*                            TEMP - JOB CLASS VARIABLE. 
  
      CHARACTER*7   JN(MXJ) 
*                            /TRC/ UJN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JS(MXJ) 
*                            /TRC/ D.JSN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JSN 
*                            TEMP - JSN VARIABLE. 
  
      CHARACTER*7   LFN 
*                            ARG - LFN OF DAYFILE LOG FILE. 
  
      CHARACTER*5   MK(MXJ) 
*                            /TRC/ JOB SELECTION MARKS IN TRACE TABLE.
  
      INTEGER       ML(2,MXJ) 
*                            /CTL/ DFL/AFL MSG COUNTS FOR TRACE TABLE.
  
      INTEGER       NJ
*                            /CTL/ CURRENT NUMBER JOBS IN TRACE TABLE.
  
      CHARACTER*7   NUL 
*                            TEMP - FOR IGNORED WORD FROM *PARSE*.
  
      LOGICAL       PRT 
*                            FLAG SET TO PRINTOUT DAYFILE MESSAGE.
  
      INTEGER       SM
*                            LOCAL COUNTER  FOR DFL SYSTEM MESSAGES.
  
      CHARACTER*20  TE(MXJ) 
*                            /TRC/ JOB DATE/TIME END IN TRACE TABLE.
  
      CHARACTER*7   TN(MXJ) 
*                            /TRC/ JOB TERMINAL NAME IN TRACE TABLE.
  
      CHARACTER*20  TS(MXJ) 
*                            /TRC/ JOB DATE/TIME START IN TRACE TABLE.
  
      CHARACTER*7   UN(MXJ) 
*                            /TRC/ JOB USERNAME IN TRACE TABLE. 
  
      CHARACTER*7   USR 
*                            TEMP - USERNAME VARIABLE.
  
      CHARACTER*7   VERB
*                            TEMP - COMMAND CRACKING VARIABLE.
  
  
* GLOBAL NUMERIC/LOGICAL VARIABLES AND PARAMETERS.
  
      COMMON /CTL/  NJ
      COMMON /CTL/  ACIN
      COMMON /CTL/  DFIN
      COMMON /CTL/  ACEOF 
      COMMON /CTL/  DFEOF 
      COMMON /CTL/  ML
      COMMON /CTL/  JBLIMIT 
  
* DAYFILE LOG SPECIFIC VARIABLES. 
  
      COMMON /DFL/  DFSDATE 
      COMMON /DFL/  DFSTIME 
      COMMON /DFL/  DFEDATE 
      COMMON /DFL/  DFETIME 
      COMMON /DFL/  DFTITLE 
      COMMON /DFL/  DFVERSN 
      COMMON /DFL/  DFTXT 
  
* JSN TRACE TABLE STORAGE.
  
      COMMON /TRC/  DSU 
      COMMON /TRC/  MK
      COMMON /TRC/  JN
      COMMON /TRC/  JS
      COMMON /TRC/  JC
      COMMON /TRC/  TS
      COMMON /TRC/  TE
      COMMON /TRC/  FN
      COMMON /TRC/  UN
      COMMON /TRC/  TN
  
      DATA SM/0/
  
  
**        ENTRY -  CALL DFSCAN(LFN,*NNN)
*                  *LFN* IS LFN OF DAYFILE LOG FILE.
*                  *NNN  IS ALTERNATE EXIT STATEMENT NUMBER.
* 
*         EXIT -   FILE REWOUND AND FIRST RECORD READ FOR PROCESSING. 
* 
*         ERROR -  ALTERNATE EXIT TAKEN IF FILE FAILS FORMAT TEST OR
*                  EOF FOUND BEFORE FIRST 3 SYSJOB MESSAGES FOUND.
* 
*         USES -   COMMON /CTL/ FOR GLOBAL VARIABLES DFEOF, DFIN. 
*                  COMMON /DFL/ FOR DAYFILE-SPECIFIC VARIABLES. 
* 
*         CALLS -  *LOGTEST* TO TEST LOG FORMAT, EXTRACT DATE/TIME. 
* 
*         NOTES -  DAYFILE LOG PRE-SCAN ROUTINE REQUIRES: 
*                  1) THAT FILE BE FORMATTED AS A RAW DAYFILE LOG.
*                  2) FINDING A START DATE VIA -
*                     A) 1ST RECORD DATE STAMP -OR- 
*                     B) DATE IN 1ST SYSJOB MESSAGE -OR-
*                     C) A DEAD START MSG -OR-
*                     D) AN HOURLY DATE STAMP MSG.
*                  3) ESTABLISHING SYSTEM ID VIA -
*                     A) TITLE IN 2ND SYSJOB MSG -AND-
*                     B) VERSION IN 3RD SYSJOB MSG. 
*                  IF SUCCESSFUL, FILE WILL BE REWOUND AND FIRST RECORD 
*                  WILL BE READ IN ADVANCE TO START PROCESSING. 
  
      SM=0
      DFEOF=.FALSE. 
  
* CHECK LOG FORMAT AND EXTRACT START [DATE]/TIME STAMPS.
  
      CALL LOGTEST(1,DFTXT,DFEDATE,DFETIME,*130)
      IF (DFETIME.EQ.' ') THEN
        CALL REMARK('   *** '//LFN//' NOT RAW DAYFILE LOG.')
        DFEOF=.TRUE.
        RETURN 1
      ENDIF 
  
* ACCEPT TIME, COUNT DATE STAMP RECORD AND REMEMBER TO SKIP OVER. 
  
      DFSTIME=DFETIME 
      IF (DFEDATE.NE.' ') DFIN=1
      GOTO 110
  
* READ NEXT DAYFILE LOG RECORD. 
  
  100 READ (1,10,END=130) DFTXT 
  10  FORMAT(A100)
  
* SCAN FOR SYSJOB MESSAGES ONLY.
  
  110 DFETIME=DFTXT(1:10) 
      IF (DFTXT(13:17).NE.'SYS S') GOTO 100 
  
* FIRST THREE SYSJOB MESSAGES HAVE SYSTEM DATE, TITLE, & VERSION. 
  
      SM=SM+1 
      IF (SM.EQ.1) THEN 
        L=INDEX(DFTXT,'/')
        IF (L.GT.3 .AND. DFTXT(L+3:L+3).EQ.'/') THEN
          DFEDATE=DFTXT(L-3:L+6)
        ENDIF 
  
      ELSE IF (SM.EQ.2) THEN
        DFTITLE=DFTXT(21:60)
  
      ELSE IF (SM.EQ.3) THEN
        DFVERSN=DFTXT(21:40)
  
* OTHER SYSJOB MSG-S INCLUDE DEAD START DATE MESSAGE WITH DATE. 
  
      ELSE IF (DFTXT(32:41).EQ.'DEAD START') THEN 
        DFEDATE=DFTXT(21:30)
  
* HOURLY LOG DATE MESSAGE.
  
      ELSE IF (DFTXT(5:9).EQ.'00.00' .AND.
     .         DFTXT(21:31).EQ.'SYSTEM DATE') THEN
        DFEDATE=DFTXT(35:44)
      ENDIF 
  
* ACCEPT START DATE, IF FOUND.
  
      IF (DFSDATE.EQ.' ' .AND. DFEDATE.NE.' ') DFSDATE=DFEDATE
  
* NEED DATE, SYSTEM TITLE AND VERSION TO PROCESS LOG. 
  
      IF (DFSDATE.EQ.' '.OR.DFTITLE.EQ.' '.OR.DFVERSN.EQ.' ') GOTO 100
  
* REWIND FOR ROUTINE PROCESSING AND SKIP OVER DATE STAMP. 
  
      REWIND 1
      IF (DFIN.EQ.1) READ (1,10,END=130) DFTXT
      PRT=.FALSE. 
  
* DROP THROUGH TO READ FIRST USABLE MESSAGE.
  
* --------------------------------------------------------------------- 
* ROUTINE DAYFILE MESSAGE PROCESSING. 
* --------------------------------------------------------------------- 
  
* GET MSG, COUNT & MARK AS TO SOURCE ('-' IN COL 19 = DAYFILE). 
  
  120 READ (1,10,END=130) DFTXT 
      DFIN=DFIN+1 
      DFTXT(19:19)='-'
      DFETIME=DFTXT(1:10) 
      RETURN
  
* EOF ALTERNATE EXIT. 
  
  130 DFEOF=.TRUE.
      WRITE (8,*) '  === EOF DAYFILE LOG ',LFN,', ',DFIN,' MESSAGES'
      RETURN 1
  
**        ENTRY -  CALL DFMSG(*NNN) 
*                  *NNN IS ALTERNATE EXIT TAKEN WHEN DFEOF = .TRUE. AT
*                       TIME OF CALL. 
* 
*         EXIT -   ANNOTATED DAYFILE MESSAGE IS WRITTEN TO COMPOSITE
*                  LOG FILE ON UNIT 3 AND NEXT RECORD IS READ, OR 
*                  *DFEOF* IS SET .TRUE.
* 
*         ERROR -  NONE.
* 
*         PRINTOUT -
*                  ANNOTATED COPIES OF CERTAIN DAYFILE LOG MESSAGES:  
*                  - LEVEL ZERO DEADSTART MESSAGES, 
*                  - ALL WITH TIMESTAMP WITHIN TIME WINDOW, 
*                  - ALL *SUI* MESSAGES,
*                  - ALL CONSOLE OPERATOR COMMAND MESSAGES, 
*                  - ANY CONTAINING SELECTED TEXT STRING. 
* 
*         CALLS -  *JSNLVL0* TO UPDATE D/S UNIQUE JSN PREFIX CODE.
*                  *TMCHECK* TO CHECK FOR TIME WINDOWS. 
*                  *JSNTRAK* TO COLLECT ATTRIBUTES IN JSN TRACE TABLE.
*                  *PARSE* TO EXTRACT DATA ITEMS FROM LOG MESSAGES. 
*                  *PICKUSR* TO CHECK NEW USERIDS FOR SELECTION.
*                  *MSCHECK* TO CHECK FOR SELECTED TEXT STRINGS.
* 
*         USES -   COMMON /CTL/ FOR GLOBAL VARIABLES. 
*                  COMMON /DFL/ FOR DAYFILE-SPECIFIC VARIABLES. 
*                  COMMON /TRC/ FOR JSN TRACE TABLE DATA. 
* 
*         NOTES -  THIS ROUTINE PROCESSES MESSAGE READ DURING PREVIOUS
*                  CALL AND THEN READS NEXT RECORD BEFORE RETURNING.
*                  THIS ALLOWS *SECART* TO SEE TIMESTAMP OF NEXT RECORD 
*                  AND DECIDE WHEN TO PROCESS VIS A VIS ACCOUNT LOG.
  
      ENTRY DFMSG(*)
  
* WATCH FOR SYSJOB MSGS W/ DATE.
  
      IF (DFTXT(13:17).EQ.'SYS S') THEN 
  
* SYSJOB HOURLY DATE MESSAGES.
  
        IF (DFTXT(5:9).EQ.'00.00' .AND. 
     .      DFTXT(21:31).EQ.'SYSTEM DATE') THEN 
          DFEDATE=DFTXT(35:44)
  
* SYSJOB DEAD START MESSAGE W/ DATE.
  
        ELSE IF (DFTXT(32:41).EQ.'DEAD START') THEN 
          DFEDATE=DFTXT(21:30)
  
* LEVEL 0 REQUIRES UPDATE D/S UNIQUE CODE.
  
          IF (DFTXT(43:51).EQ.'LEVEL  0.') CALL JSNLVL0 
        ENDIF 
  
* DETECT SPECIAL JSN FOR LEVEL 0 DEADSTART TOO. 
  
      ELSE IF (DFTXT(13:17).EQ.'AAAAA') THEN
        PRT=.TRUE.
        CALL JSNLVL0
      ENDIF 
  
* INSERT D/S UNIQUE CODE LETTER AS JSN PREFIX.
  
      DFTXT(11:12)=DSU//'.' 
  
* CHECK FOR TIME WINDOW PRINTOUT. 
  
      CALL TMCHECK(DFETIME,PRT) 
  
* MATCH/COLLECT JSN AND DATE/TIME GROUP (DTG).
  
      JSN=DFTXT(11:16)
      JCL=DFTXT(17:17)
      CALL JSNTRAK(JSN,JCL,DFEDTG,N,1)
  
* CRACK 1ST WORD TO PICK OUT UJN OR USER, SUI, OPERATOR COMMANDS. 
* SHORTSTOP COMMENT LINES.
  
      I=21
      CALL PARSE(DFTXT,I,VERB)
      IF (VERB.EQ.'*') GOTO 140 
  
* ACCOMMODATE USE OF $ AND / COMMAND PREFIXES ONLY. 
  
      IF (VERB.EQ.' ') THEN 
        IF (INDEX('$/',DFTXT(I-1:I-1)).NE.0) THEN 
          CALL PARSE(DFTXT,I,VERB)
        ELSE
          GOTO 140
        ENDIF 
      ENDIF 
  
* TRY TO EXTRACT UJN FROM FIRST DAYFILE MESSAGE FOR EACH JOB. 
  
      IF ((ML(1,N).EQ.1) .AND. JN(N).EQ.' ') THEN 
        JN(N)=VERB
        CALL PICKUJN(JN(N),MK(N)) 
      ENDIF 
  
* WATCH FOR USER COMMAND TO EXTRACT FM,UN & CHECK FOR SELECTION.
  
      IF (VERB.EQ.'USER') THEN
        CALL PARSE(DFTXT,I,USR) 
        CALL PARSE(DFTXT,I,NUL) 
        CALL PARSE(DFTXT,I,FAM) 
        IF (UN(N).EQ.' ' .AND .FN(N).EQ.' ') THEN 
          UN(N) = USR 
          FN(N) = FAM 
        ENDIF 
        CALL PICKUSR(FAM,USR,MK(N)) 
  
* SPECIAL CASE 'SUI' COMMAND AS USERNAME. 
  
      ELSE IF (VERB.EQ.'SUI') THEN
        CALL PARSE(DFTXT,I,USR) 
        IF (UN(N).EQ.' ') UN(N) = USR 
        CALL PICKUSR(FN(N),USR,MK(N)) 
  
* SPECIAL CASE PRINTOUT OF OPERATOR COMMANDS. 
  
      ELSE IF (VERB.EQ.'DS'.AND.DFTXT(I-1:I).EQ.', ') THEN
        PRT=.TRUE.
      ENDIF 
  
* FINAL CHECK FOR DIRECTIVE SELECTED TEXT STRING(S).
  
  140 CALL MSCHECK(DFTXT(21:100),PRT) 
  
* PRINTOUT MESSAGE FOR ANY REASON.
  
      IF (PRT) THEN 
        WRITE (8,10) DFTXT
        PRT=.FALSE. 
      ENDIF 
  
* PUT ANNOTATED MESSAGE INTO MERGED LOG FILE. 
  
      WRITE (3,10) DFTXT
      GOTO 120
  
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE ACSCAN(LFN,*)
**        ACSCAN - ACCOUNT LOG MESSAGE PROCESSING.
* 
*         *ACSCAN* PROVIDES THE PRIMARY ROUTINES FOR PROCESSING ACCOUNT 
*         LOG MESSAGES.  IT PROVIDES AN ENTRY POINT TO PRE-SCAN THE LOG 
*         FILE TO VALIDATE FORMAT AND EXTRACT CRITICAL SYSTEM ID AND
*         DATE/TIME DATA, AND ANOTHER FOR ROUTINE PROCESSING OF EACH
*         LOG MESSAGE IN THE SEQUENCE CONTROLLED BY *SECART*. ANNOTATED 
*         ACCOUNT LOG MESSAGES ARE WRITTEN TO COMPOSITE LOG ON UNIT 3.
  
      IMPLICIT INTEGER(A-Z) 
  
      PARAMETER     (MXJ=1000)
*                            SIZE OF JSN TRACE TABLE. 
  
      EQUIVALENCE   (ACEDTG,ACEDATE)
*                            /ACL/ ACEDTG*20 = ACEDATE*10 // ACETIME*10.
  
  
      CHARACTER*10  ACEDATE 
*                            /ACL/ (EQV) ACCOUNT LOG END DATE.
  
      CHARACTER*20  ACEDTG
*                            /ACL/ (EQV) ACCOUNT LOG END DATE/TIME. 
  
      LOGICAL       ACEOF 
*                            /CTL/ ACCOUNT LOG EOF FLAG.
  
      CHARACTER*10  ACETIME 
*                            /ACL/ (EQV) ACCOUNT LOG END TIME.
  
      INTEGER       ACIN
*                            /CTL/ ACCOUNT LOG MESSAGE COUNTER. 
  
      CHARACTER*10  ACSDATE 
*                            /ACL/ (EQV) ACCOUNT LOG START DATE.
  
      CHARACTER*10  ACSTIME 
*                            /ACL/ (EQV) ACCOUNT LOG START TIME.
  
      CHARACTER*40  ACTITLE 
*                            /ACL/ ACCOUNT LOG SYSTEM TITLE.
  
      CHARACTER*100 ACTXT 
*                            /ACL/ CURRENT ACCOUNT LOG MESSAGE TEXT.
  
      CHARACTER*20  ACVERSN 
*                            /ACL/ ACCOUNT LOG SYSTEM VERSION.
  
      LOGICAL       DFEOF 
*                            /CTL/ DAYFILE LOG EOF FLAG.
  
      INTEGER       DFIN
*                            /CTL/ DAYFILE LOG MESSAGE COUNTER. 
  
      CHARACTER*1   DSU 
*                            /TRC/ DEADSTART UNIQUE PREFIX CODE.
  
      CHARACTER*7   FAM 
*                            TEMP - FAMILYNAME VARIABLE.
  
      CHARACTER*7   FN(MXJ) 
*                            /TRC/ FAMILY NAME COLUMN IN TRACE TABLE. 
  
      INTEGER       JBLIMIT 
*                            /CTL/ UNIT JOB PRINTOUT MESSAGE LIMIT. 
  
      CHARACTER*1   JC(MXJ) 
*                            /TRC/ JOB CLASS COLUMN IN TRACE TABLE. 
  
      CHARACTER*1   JCL 
*                            TEMP - JOB CLASS VARIABLE. 
  
      CHARACTER*7   JN(MXJ) 
*                            /TRC/ UJN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JS(MXJ) 
*                            /TRC/ D.JSN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JSN 
*                            TEMP   JSN VARIABLE. 
  
      CHARACTER*7   LFN 
*                            ARG - LFN FOR ACCOUNT LOG FILE.
  
      CHARACTER*4   MID 
*                            TEMP - ACCOUNT MESSAGE ID. 
  
      CHARACTER*5   MK(MXJ) 
*                            /TRC/ JOB SELECTION MARKS IN TRACE TABLE.
  
      INTEGER       ML(2,MXJ) 
*                            /CTL/ DFL/AFL MSG COUNTS FOR TRACE TABLE.
  
      INTEGER       NJ
*                            /CTL/ CURRENT NUMBER JOBS IN TRACE TABLE.
  
      CHARACTER*20  NUDTG 
*                            TEMP - NEW DATE/TIME GROUP VARIABLE. 
  
      CHARACTER*6   NUJSN 
*                            TEMP - NEW JSN VARIABLE. 
  
      LOGICAL       PRT 
*                            FLAG TO PRINTOUT ACCOUNT LOG MESSAGE.
  
      CHARACTER*2   SC
*                            TEMP - IGNORED WORD FROM *PARSE*.
  
      CHARACTER*20  TE(MXJ) 
*                            /TRC/ JOB DATE/TIME END IN TRACE TABLE.
  
      CHARACTER*7   TN(MXJ) 
*                            /TRC/ JOB TERMINAL NAME IN TRACE TABLE.
  
      CHARACTER*7   TRM 
*                            TEMP - TERMINAL ID VARIABLE. 
  
      CHARACTER*20  TS(MXJ) 
*                            /TRC/ JOB DATE/TIME START IN TRACE TABLE.
  
      CHARACTER*7   UN(MXJ) 
*                            /TRC/ JOB USERNAME IN TRACE TABLE. 
  
      CHARACTER*7   USR 
*                            TEMP - USERNAME VARIABLE.
  
      CHARACTER*1   X 
*                            TEMP - USED IN D.JSN ATTRIBUTES RECOVERY.
  
  
* ACCOUNT LOG SPECIFIC VARIABLES. 
  
      COMMON /ACL/  ACSDATE 
      COMMON /ACL/  ACSTIME 
      COMMON /ACL/  ACEDATE 
      COMMON /ACL/  ACETIME 
      COMMON /ACL/  ACTITLE 
      COMMON /ACL/  ACVERSN 
      COMMON /ACL/  ACTXT 
  
* GLOBAL NUMERIC/LOGICAL VARIABLES AND PARAMETERS.
  
      COMMON /CTL/  NJ
      COMMON /CTL/  ACIN
      COMMON /CTL/  DFIN
      COMMON /CTL/  ACEOF 
      COMMON /CTL/  DFEOF 
      COMMON /CTL/  ML
      COMMON /CTL/  JBLIMIT 
  
* JSN TRACE TABLE STORAGE.
  
      COMMON /TRC/  DSU 
      COMMON /TRC/  MK
      COMMON /TRC/  JN
      COMMON /TRC/  JS
      COMMON /TRC/  JC
      COMMON /TRC/  TS
      COMMON /TRC/  TE
      COMMON /TRC/  FN
      COMMON /TRC/  UN
      COMMON /TRC/  TN
  
  
**        ENTRY -  CALL ACSCAN(LFN,*NNN)
*                  *LFN* IS LFN OF ACCOUNT LOG FILE.
*                  *NNN  IS ALTERNATE EXIT STATEMENT NUMBER.
* 
*         EXIT -   FILE REWOUND AND FIRST RECORD READ FOR PROCESSING. 
* 
*         ERROR -  ALTERNATE EXIT TAKEN IF FILE FAILS FORMAT TEST OR
*                  EOF FOUND BEFORE LOG DATE AND SYSTEM ID ARE FOUND. 
* 
*         USES -   COMMON /CTL/ FOR GLOBAL VARIABLES DFEOF, DFIN. 
*                  COMMON /ACL/ FOR ACCOUNT-SPECIFIC VARIABLES. 
* 
*         CALLS -  *LOGTEST* TO CHECK FORMAT, EXTRACT START DATE/TIME.
* 
*         NOTES -  ACCOUNT LOG PRE-SCAN ROUTINE REQUIRES: 
*                  1) THAT FILE BE FORMATTED AS A RAW ACCOUNT LOG.
*                  2) FINDING A START DATE VIA SYSJOB MESSAGE - 
*                     A) 'ABSY' OR 'SIDT' MESSAGE,  -OR-
*                     B) 'ACDT' MESSAGE.
*                  3) ESTABLISHING SYSTEM ID VIA SYSJOB MESSAGES, 
*                     A) 'ABST' MESSAGE FOR TITLE, -AND-
*                     B) 'ABSV' MESSAGE FOR VERSION.
*                  IF SUCCESSFUL, FILE WILL BE REWOUND AND FIRST RECORD 
*                  WILL BE READ IN ADVANCE TO START PROCESSING. 
  
      ACEOF=.FALSE. 
  
* CHECK LOG FORMAT AND EXTRACT START [DATE]/TIME STAMPS.
  
      CALL LOGTEST(2,ACTXT,ACEDATE,ACETIME,*130)
      IF (ACETIME.EQ.' ' .OR. ACTXT(25:26).NE.', ') THEN
        CALL REMARK('   *** '//LFN//' NOT RAW ACCOUNT LOG.')
        ACEOF=.TRUE.
        RETURN 1
      ENDIF 
  
* ACCEPT TIME, COUNT DATE STAMP RECORD AND REMEMBER TO SKIP OVER. 
  
      ACSTIME=ACETIME 
      IF (ACEDATE.NE.' ') ACIN=1
      GOTO 110
  
* READ NEXT ACCOUNT LOG RECORD. 
  
  100 READ (2,10,END=130) ACTXT 
  10  FORMAT(A100)
  
  110 ACETIME=ACTXT(1:10) 
      MID=ACTXT(21:24)
  
* SCAN FOR SYSJOB MESSAGES ONLY.
  
      IF (ACTXT(13:17).NE.'SYS S') GOTO 100 
  
* WATCH FOR SYSJOB MSGS W/ DATE, TITLE AND VERSION. 
  
      IF (MID.EQ.'ABST') THEN 
        ACTITLE=ACTXT(27:66)
      ELSE IF (MID.EQ.'ABSV') THEN
        ACVERSN=ACTXT(27:46)
      ELSE IF (MID.EQ.'ABSY' .OR. MID.EQ.'SIDT')THEN
        ACEDATE=ACTXT(27:36)
      ELSE IF (MID.EQ.'ACDT' .AND. ACTXT(27:36).EQ.'DS, DATE.  ') THEN
        ACEDATE=ACTXT(37:46)
      ENDIF 
  
* ACCEPT START DATE, IF FOUND.
  
      IF (ACSDATE.EQ.' ' .AND. ACEDATE.NE.' ') ACSDATE=ACEDATE
  
* NEED DATE, SYSTEM TITLE AND VERSION TO PROCESS LOG. 
  
      IF (ACSDATE.EQ.' '.OR.ACTITLE.EQ.' '.OR.ACVERSN.EQ.' ') GOTO 100
  
* REWIND FOR ROUTINE PROCESSING AND SKIP OVER DATE STAMP. 
  
      REWIND 2
      IF (ACIN.EQ.1) READ (2,10,END=130) ACTXT
      PRT=.FALSE. 
  
* DROP THROUGH TO READ FIRST USABLE MESSAGE.
  
* --------------------------------------------------------------------- 
* ROUTINE ACCOUNT LOG MESSAGE PROCESSING. 
* --------------------------------------------------------------------- 
  
* GET MSG, COUNT & MARK AS TO SOURCE ('+' IN COL 20 = ACCOUNT). 
  
  120 READ (2,10,END=130) ACTXT 
      ACIN=ACIN+1 
      ACETIME=ACTXT(1:10) 
      MID=ACTXT(21:24)
      ACTXT(20:20)='+'
  
* SPECIAL CASE BIAS SOME MSG ID-S TO PRECEDE DFL MSGS.
  
      IF (INDEX('AB AC AR AS',MID(1:2)).NE.0
     .  .OR. MID.EQ.'SIDT')            ACETIME(10:10)=' ' 
      RETURN
  
  
* EOF ALTERNATE EXIT. 
  
  130 ACEOF=.TRUE.
      WRITE (8,*) '  === EOF ACCOUNT LOG ',LFN,', ',ACIN,' MESSAGES'
      RETURN 1
  
  
**        ENTRY -  CALL ACMSG(*NNN) 
*                  *NNN  IS ALTERNATE EXIT TAKEN WHEN ACEOF = .TRUE. AT 
*                        TIME OF CALL.
* 
*         EXIT -   ANNOTATED ACCOUNT LOG MESSAGE WRITTEN TO COMPOSITE 
*                  LOG FILE ON UNIT 3 AND NEXT RECORD IS READ, OR 
*                  *ACEOF* IS SET TO .TRUE. 
* 
*         ERROR -  NONE.
* 
*         PRINTOUT -
*                  ANNOTATED COPIES OF CERTAIN ACCOUNT LOG MESSAGES:  
*                  - ALL WITH TIMESTAMP WITHIN TIME WINDOW. 
*                  - JOB RECOVERY MESSAGES. 
*                  - CHANGES TO USERNAME ASSOCIATED WITH A JOB. 
*                  - CHANGES TO JOB'S JSN.
* 
*         CALLS -  *JSNLVL0* TO UPDATE D/S UNIQUE JSN PREFIX CODE.
*                  *TMCHECK* TO CHECK FOR TIME WINDOWS. 
*                  *JSNTRAK* TO COLLECT ATTRIBUTES IN JSN TRACE TABLE.
*                  *AMSTEST* TO COLLECT ACCOUNT MSG ID STATISTICS AND 
*                            DETECT FLAGGED ID-S. 
*                  *JSNLOOK* TO FIND RECOVERED JOB ATTRIBUTES.
*                  *PICKUSR* TO CHECK NEW USERID-S FOR SELECTION. 
*                  *PICKTRM* TO CHECK NEW TERMINAL ID-S FOR SELECTION.
*                  *PARSE*   TO EXTRACT DATA ITEMS FROM LOG MESSAGES. 
* 
*         NOTES -  THIS ROUTINE PROCESSES MESSAGE READ DURING PREVIOUS
*                  CALL AND THEN READS NEXT RECORD BEFORE RETURNING.
*                  THIS ALLOWS *SECART* TO SEE TIMESTAMP OF NEXT RECORD 
*                  AND DECIDE WHEN TO PROCESS VIS A VIS DAYFILE LOG.
*                  TO INSURE THAT MESSAGE ID-S BEGINNING WITH 'AB', 
*                  'AC', 'AR', AND 'AS' PRECEEDE DAYFILE MESSAGES IN
*                  SAME SECOND, A SPECIAL CASE BIAS IS APPLIED BY 
*                  BLANKING FINAL PERIOD IN TIMESTAMP.
  
      ENTRY ACMSG(*)
  
* RESET SPECIAL CASE BIAS, IF ANY.
  
      ACETIME(10:10)='.'
  
* WATCH FOR NEW DATE AND LEVEL 0 DEADSTART MSGS.
  
      IF (INDEX('ABSY AESY SIDT',MID).NE.0) THEN
        ACEDATE=ACTXT(27:36)
      ELSE IF (MID.EQ.'ACDT') THEN
        IF (ACTXT(27:36).EQ.'DS, DATE. ') ACEDATE=ACTXT(37:46)
      ELSE IF (MID.EQ.'ARSY') THEN
        ACEDATE=ACTXT(29:38)
        IF (ACTXT(27:28).EQ.'0,') CALL JSNLVL0
      ENDIF 
  
* INSERT D/S UNIQUE CODE LETTER AS JSN PREFIX.
  
      ACTXT(11:12)=DSU//'.' 
  
* CHECK FOR TIME WINDOW START OR END. 
  
      CALL TMCHECK(ACETIME,PRT) 
  
* COLLECT/MATCH JSN-S.
  
      JSN=ACTXT(11:16)
      JCL=ACTXT(17:17)
      CALL JSNTRAK(JSN,JCL,ACEDTG,N,2)
  
* COLLECT/MATCH MESSAGE IDS & DETECT FLAGGED MSG ID-S.
  
      CALL AMSTEST(MID,JCL,PRT) 
  
* WATCH FOR RECOVERED JOBS.  TRY TO RETRIEVE ATTRIBUTES.
  
      IF (MID.EQ.'ARRQ' .AND. ACTXT(27:28).EQ.'C1'
     .  .AND. ACTXT(53:54).EQ.'IN' )             THEN 
        NUDTG=' 00/00/00. 00.00.00.'
        NUDTG(2:3)=ACTXT(37:38) 
        NUDTG(5:6)=ACTXT(39:40) 
        NUDTG(8:9)=ACTXT(41:42) 
        NUDTG(12:13)=ACTXT(45:46) 
        NUDTG(15:16)=ACTXT(47:48) 
        NUDTG(18:19)=ACTXT(49:50) 
        X=DSU 
  
  165   NUJSN=X//'.'//ACTXT(31:34)
        CALL JSNLOOK(NUJSN,L) 
        IF (L.NE.0.AND.TS(L).EQ.NUDTG) THEN 
          FN(N)=FN(L) 
          UN(N)=UN(L) 
          JN(N)=JN(L) 
          WRITE (8,*) '  === JSN RECOVERED ',JS(L)
          PRT=.TRUE.
        ELSE
          X=CHAR(ICHAR(X)-1)
          IF (X.GE.'A') GOTO 165
          WRITE (8,*) '  === JSN NOT FOUND: ',NUJSN(3:6),NUDTG
          PRT=.TRUE.
        ENDIF 
      ENDIF 
  
* COLLECT/CHANGE ATTRIBUTES IN TRACE TABLE. 
* GET USER ID & TERMINAL AND CHECK FOR SELECTION. 
  
      IF (MID.EQ.'ABUN') THEN 
        I=27
        CALL PARSE(ACTXT,I,USR) 
        CALL PARSE(ACTXT,I,FAM) 
        CALL PARSE(ACTXT,I,TRM) 
        TN(N)=TRM 
        IF (FN(N).EQ.' '  .AND. UN(N).EQ.' '  ) THEN
          UN(N)=USR 
          FN(N)=FAM 
        ENDIF 
        CALL PICKUSR(FAM,USR,MK(N)) 
        CALL PICKTRM(TRM,MK(N)) 
  
      ELSE IF (MID.EQ.'ACUN') THEN
        I=27
        CALL PARSE(ACTXT,I,USR) 
        CALL PARSE(ACTXT,I,FAM) 
        CALL PICKUSR(FAM,USR,MK(N)) 
        PRT=.TRUE.
  
      ELSE IF (MID.EQ.'ARUN') THEN
        I=27
        CALL PARSE(ACTXT,I,USR) 
        CALL PARSE(ACTXT,I,FAM) 
        IF (UN(N).EQ.' ') UN(N)=USR 
        IF (FN(N).EQ.' ') FN(N)=FAM 
        CALL PICKUSR(FAM,USR,MK(N)) 
        CALL PARSE(ACTXT,I,TRM) 
        IF (TRM.NE.'TERMNAM') TN(N)=TRM 
        CALL PICKTRM(TRM,MK(N)) 
  
* CHANGE SC/JSN  W/ LINK-BACK IF NEW JSN SELECTED.
* RECORDS NEW JSN W/ INHERITED ATTRIBUTES.
  
      ELSE IF (MID.EQ.'ACSC') THEN
        I=27
        CALL PARSE(ACTXT,I,SC)
        NUJSN=DSU//'.    '
        CALL PARSE(ACTXT,I,NUJSN(3:6))
        IF (NUJSN(3:6).NE.'   ' .AND. NUJSN(3:6).NE.JSN) THEN 
          L=N 
          CALL JSNTRAK(NUJSN,JCL,ACEDTG,N,2)
          MK(N)=MK(L) 
          JN(N)=JN(L) 
          FN(N)=FN(L) 
          UN(N)=UN(L) 
          TN(N)=TN(L) 
          PRT=.TRUE.
        ENDIF 
      ENDIF 
  
* PRINTOUT MESSAGE FOR ANY REASON.
  
      IF (PRT) THEN 
        WRITE (8,10) ACTXT
        PRT=.FALSE. 
      ENDIF 
  
* PUT ANNOTATED MESSAGE INTO MERGED LOG FILE. 
  
      WRITE (3,10) ACTXT
      GOTO 120
  
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE LOGTEST(LF,TXT,DT,TM,*)
**        LOGTEST - TEST RAW LOG FORMAT & EXTRACT DATE/TIME STAMPS. 
* 
*         *LOGTEST* READS FIRST LINE OF LOG FILE, TESTS FOR SYNTAX OF 
*         OPTIONAL DATESTAMP AND, IF CORRECT, EXTRACTS LOG START DATE.
*         (DATE STAMP IS OPTIONAL TO PERMIT PROCESSING LOG FRAGMENTS.)
*         IF DATE STAMP IS MISSING, FIRST LINE IS CHECKED FOR PROPER
*         SYNTAX AND LOG START TIME EXTRACTED.  IF DATE STAMP IS
*         PRESENT, 2ND LINE WILL BE READ, CHECKED AND TIME EXTRACTED. 
* 
*         ENTRY -  CALL LOGTEST(LFN,TXT,OK) 
*                  *LF*  IS UNIT NUMBER OF FILE BEING TESTED. 
* 
*         EXIT -   *TXT*  WILL CONTAIN FIRST USABLE RECORD FROM FILE. 
*                  *DT*   WILL CONTAIN DATE STAMP OR BLANKS.
*                  *TM*   WILL CONTAIN TIMESTAMP OF USABLE RECORD.
* 
*         ERROR -  ALTERNATE RETURN 1 IF EOF OR LOG FAILS FORMAT TESTS. 
* 
*         NOTES -  USES CHARACTER STRING CATENATION TO SIMPLIFY SYNTAX
*                  CHECK AND INDEX FUNCTION TO CHECK FOR NON-NUMERIC
*                  CHARACTERS EFFICIENTLY.  SPECIFIC TESTS ARE: 
*                    -------------------------------------------- 
*                    CHAR POSITION:  1234567890123456789012345
*                    TARGET FORMAT: ' NN.NN.NN.  XXXXX.  XXXX...' 
*                    TEST SYNTAX  :  =  =  =  ===     === 
*                    TEST NUMERIC :   == == ==
*                    -------------------------------------------- 
  
      IMPLICIT INTEGER(A-Z) 
  
      INTEGER       LF
*                            ARG - UNIT # LOG FILE TO TEST FORMAT.
  
      CHARACTER*10  DT
*                            ARG - LOG START DATE RETURNED. 
  
      LOGICAL       OK
*                            TEMP - USED IN SYNTAX CHECKING.
  
      CHARACTER*10  TM
*                            ARG - LOG START TIME RETURNED
  
      CHARACTER*6   TST 
*                            TEMP - USED IN SYNTAX CHECK. 
  
      CHARACTER*100 TXT 
*                            ARG - FIRST RECORD TEXT STRING.
  
      DT=' '
      TM=' '
      OK=.TRUE. 
  
* READ FIRST LINE OF LOG, CHECK FOR OPTIONAL DATE STAMP.
  
      READ (LF,10,END=130) TXT
  10  FORMAT(A100)
      IF (TXT(1:1).EQ.' ') GOTO 100 
  
*                              1    6 
* CHECK FOR DATE STAMP SYNTAX: YYMMDD.
  
      IF (INDEX('8901',TXT(1:1)).EQ.0) OK=.FALSE. 
      IF (INDEX('0123456789',TXT(2:2)).EQ.0) OK=.FALSE. 
      IF (INDEX('01',TXT(3:3)).EQ.0) OK=.FALSE. 
      IF (INDEX('0123456789',TXT(4:4)).EQ.0) OK=.FALSE. 
      IF (INDEX('0123',TXT(5:5)).EQ.0) OK=.FALSE. 
      IF (INDEX('0123456789',TXT(6:6)).EQ.0) OK=.FALSE. 
      IF (.NOT.OK) GOTO 130 
  
* ACCEPT DATE STAMP, READ SECOND LINE FOR TIME STAMP. 
  
      DT=' '//TXT(1:2)//'/'//TXT(3:4)//'/'//TXT(5:6)//'.' 
      READ (LF,10,END=130) TXT
  
  
* COLLECT AND TEST TIME STAMP SYNTAX CHARACTERS.
  
  100 IF (TXT(1:1)//TXT(4:4)//TXT(7:7)//TXT(10:12)//TXT(18:20)
     .  .NE. ' ...  .  ') GOTO 130
  
* COLLECT AND TEST NUMERIC CHARACTERS.
  
      TST=TXT(2:3)//TXT(5:6)//TXT(8:9)
      DO 110 I=1,6
        IF(INDEX('0123456789',TST(I:I)).EQ.0) OK=.FALSE.
  110 CONTINUE
      IF (OK) TM=TXT(1:10)
      RETURN
  
* ALTERNATE EXIT ON EOF OR FAILED SYNTAX CHECK. 
  
  130 RETURN 1
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE JSNLOAD
**        JSNLOAD - JSN TRACE TABLE MANAGER.
* 
*         THIS PROGRAM UNIT MANAGES THE JSN TRACE TABLE WHICH RECORDS 
*         JOB ATTRIBUTES DATA EXTRACTED FROM BOTH DAYFILE AND ACCOUNT 
*         LOGS.  MULTIPLE ENTRY POINTS ARE PROVIDED FOR PURPOSES OF:  
*         PRE-LOADING TRACE TABLE DATA FROM PREVIOUS *SECART* RUNS, 
*         MAINTAINING A JSN PREFIX CODE TO AVOID AMBIGUITIES ACROSS 
*         LEVEL ZERO DEADSTARTS, AUTOMATICALLY CREATING NEW TABLE 
*         ENTRIES FOR EACH UNIQUE JSN, THEN MATCHING JSN-S ON 
*         SUBSEQUENT CALLS AND COLLECTING JOB ATTRIBUTES, OPTIONALLY
*         SORTING TRACE TABLE ENTRIES ON A SPECIFIED SET OF DATA ITEMS, 
*         AND FINALLY PRINTING THE TRACE TABLE.  IT ALSO PRODUCES THE 
*         TRACE TABLE FILE WHICH MAY BE LOADED ON A SUBSEQUENT RUN. 
  
  
      IMPLICIT INTEGER(A-Z) 
  
      PARAMETER     (MXJ=1000)
*                            SIZE OF JSN TRACE TABLE. 
  
  
      CHARACTER*20  ACEDTG
*                            /ACL/ ACCOUNT LOG END DATE/TIME GROUP. 
  
      LOGICAL       ACEOF 
*                            /CTL/ ACCOUNT LOG EOF FLAG.
  
      INTEGER       ACIN
*                            /CTL/ ACCOUNT LOG MESSAGE COUNTER. 
  
      CHARACTER*20  ACSDTG
*                            /ACL/ ACCOUNT LOG START DATE/TIME GROUP. 
  
      CHARACTER*60  ACSYSID 
*                            /ACL/ ACCOUNT LOG SYSTEM TITLE/VERSION.
  
      CHARACTER*20  DFEDTG
*                            /DFL/ DAYFILE LOG END DATE/TIME GROUP. 
  
      LOGICAL       DFEOF 
*                            /CTL/ DAYFILE LOG EOF FLAG.
  
      INTEGER       DFIN
*                            /CTL/ DAYFILE LOG MESSAGE COUNTER. 
  
      CHARACTER*20  DFSDTG
*                            /DFL/ DAYFILE LOG START DATE/TIME GROUP. 
  
      CHARACTER*60  DFSYSID 
*                            /DFL/ DAYFILE LOG SYSTEM TITLE/VERSION.
  
      CHARACTER*1   DSU 
*                            /TRC/ DEADSTART UNIQUE PREFIX CODE.
  
      CHARACTER*20  DTG 
*                            ARG - DATE/TIME GROUP. 
  
      LOGICAL       ERR 
*                            FLAG FOR MSGID SEQUENCE ERROR(S).
  
      CHARACTER*7   FN(MXJ) 
*                            /TRC/ FAMILY NAME COLUMN IN TRACE TABLE. 
  
      CHARACTER*40  HDR 
*                            /SYS/ PRINTOUT HEADER TEXT.
  
      INTEGER       IPAGE 
*                            LOCAL PRINTOUT PAGE COUNTER. 
  
      INTEGER       JBLIMIT 
*                            /CTL/ UNIT JOB PRINTOUT MESSAGE LIMIT. 
  
      CHARACTER*1   JC(MXJ) 
*                            /TRC/ JOB CLASS COLUMN IN TRACE TABLE. 
  
      CHARACTER*1   JCL 
*                            ARG - JOB CLASS. 
  
      CHARACTER*7   JN(MXJ) 
*                            /TRC/ UJN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JS(MXJ) 
*                            /TRC/ D.JSN COLUMN IN TRACE TABLE. 
  
      CHARACTER*6   JSN 
*                            ARG - D.JSN ARGUMENT.
  
      INTEGER       LF
*                            TEMP - FILE NUMBER FOR TRACE TABLE SORT. 
  
      CHARACTER*7   LFN 
*                            ARG - LFN FOR TRACE TABLE SORT LISTING.
  
      INTEGER       LOG 
*                            ARG - INDEX FOR DFL/AFL MESSAGE COUNTS.
  
      LOGICAL       LOOK
*                            FLAG FOR *JSNTRAK* VERSUS *JSNLOOK*. 
  
      INTEGER       LST 
*                            TEMP - HOLDS INDEX OF LAST JOB MATCHED.
  
      CHARACTER*5   MK(MXJ) 
*                            /TRC/ JOB SELECTION MARKS IN TRACE TABLE.
  
      INTEGER       ML(2,MXJ) 
*                            /CTL/ DFL/AFL MSG COUNTS FOR TRACE TABLE.
  
      INTEGER       N 
*                            ARG - INDEX TO JOB IN TRACE TABLE. 
  
      INTEGER       NJ
*                            /CTL/ CURRENT NUMBER JOBS IN TRACE TABLE.
  
      INTEGER       NS
*                            COUNT OF JOBS SELECTED.
  
      CHARACTER*10  PGM 
*                            /SYS/ *SECART* VERSION ID FOR PRINTOUTS. 
  
      CHARACTER*10  RUNDT 
*                            /SYS/ *SECART* RUN DATE FOR PRINTOUTS. 
  
      CHARACTER*10  RUNTM 
*                            /SYS/ *SECART* RUN TIME FOR PRINTOUTS. 
  
      CHARACTER*3   SKY(12) 
*                            /SRT/ TRACE TABLE SORT KEYS. 
  
      CHARACTER*20  TE(MXJ) 
*                            /TRC/ JOB DATE/TIME END IN TRACE TABLE.
  
      CHARACTER*7   TN(MXJ) 
*                            /TRC/ JOB TERMINAL NAME IN TRACE TABLE.
  
      CHARACTER*20  TS(MXJ) 
*                            /TRC/ JOB DATE/TIME START IN TRACE TABLE.
  
      CHARACTER*100 TXT 
*                            TEMP - BUFFER FOR TRACE SORT PRINTOUT. 
  
      CHARACTER*7   UN(MXJ) 
*                            /TRC/ JOB USERNAME IN TRACE TABLE. 
  
  
* ACCOUNT LOG SPECIFIC VARIABLES. 
  
      COMMON /ACL/  ACSDTG
      COMMON /ACL/  ACEDTG
      COMMON /ACL/  ACSYSID 
  
* GLOBAL NUMERIC/LOGICAL VARIABLES AND PARAMETERS.
  
      COMMON /CTL/  NJ
      COMMON /CTL/  ACIN
      COMMON /CTL/  DFIN
      COMMON /CTL/  ACEOF 
      COMMON /CTL/  DFEOF 
      COMMON /CTL/  ML
      COMMON /CTL/  JBLIMIT 
  
* DAYFILE LOG SPECIFIC VARIABLES. 
  
      COMMON /DFL/  DFSDTG
      COMMON /DFL/  DFEDTG
      COMMON /DFL/  DFSYSID 
  
* JSN TRACE TABLE SORT PARAMETERS.
  
      COMMON /SRT/  SKY 
  
* GLOBAL STRING VARIABLES.
  
      COMMON /SYS/  HDR 
      COMMON /SYS/  PGM 
      COMMON /SYS/  RUNDT 
      COMMON /SYS/  RUNTM 
  
* JSN TRACE TABLE STORAGE.
  
      COMMON /TRC/  DSU 
      COMMON /TRC/  MK
      COMMON /TRC/  JN
      COMMON /TRC/  JS
      COMMON /TRC/  JC
      COMMON /TRC/  TS
      COMMON /TRC/  TE
      COMMON /TRC/  FN
      COMMON /TRC/  UN
      COMMON /TRC/  TN
  
      DATA LST      /1/ 
  
  
**        ENTRY -  CALL JSNLOAD    [NO ARGUMENTS].
*                  THIS ENTRY PERFORMS OPTIONAL LOAD OF TRACE TABLE 
*                  DATA PRODUCED BY PREVIOUS RUN, WHICH ALLOWS *SECART* 
*                  TO RECOVER ATTRIBUTES OF JOBS RECOVERED ACROSS A 
*                  LEVEL ZERO DEADSTART WITH A NEW JSN.  SINCE IT CLEARS
*                  ANY JOB SELECTION MARKS AND CHECKS FOR SELECTIONS
*                  BASED ON CURRENT SELECTION DIRECTIVES, IN RERUN MODE 
*                  THIS ALSO PERMITS NEW UNIT JOB SELECTIONS TO BE MADE 
*                  WITHOUT REPROCESSING FROM RAW LOGS DATA.  THE TRACE
*                  TABLE DATA MUST BE ON FILE NUMBER 6. 
* 
*         EXIT -   NORMAL IF LOADED JSN-S IN ASCENDING ORDER. 
* 
*         ERROR -  JOB DAYFILE MESSAGE: 
*                  *** TRACE TABLE SEQUENCE ERROR(S). 
* 
*         USES -   COMMON /TRC/ FOR TRACE TABLE STRING DATA.
*                  COMMON /CTL/ FOR TRACE TABLE NUMERIC DATA. 
* 
*         CALLS -  *PICKUJN* FOR NEW UJN SELECTIONS.
*                  *PICKJSN* FOR NEW JSN SELECTIONS.
*                  *PICKUSR* FOR NEW USERNAME SELECTIONS. 
*                  *PICKTRM* FOR NEW TERMINAL SELECTIONS. 
* 
*         NOTES -  FILE 6, WHICH IS INITIALLY READ TO OBTAIN OLD TRACE
*                  TABLE DATA, WILL SUBSEQUENTLY BE WRITTEN WITH THE
*                  NEW DATA PRODUCED IN THE CURRENT *SECART* RUN.  THUS 
*                  IT MUST BE A READ/WRITE FILE AND, IF PREVIOUS DATA 
*                  IS TO BE PRESERVED, SHOULD BE AN EXPENDABLE COPY.
  
      L=1 
      ERR=.FALSE. 
  
  60  READ (6,62,END=69) MK(L),JN(L),JS(L),JC(L),TS(L),TE(L)
     .  ,ML(1,L),ML(2,L),FN(L),UN(L),TN(L)
      MK(L)='     ' 
      DSU=JS(L)(1:1)
      IF ((L.GT.1).AND.JS(L).LE.JS(L-1)) ERR=.TRUE. 
      CALL PICKUJN(JN(L),MK(L)) 
      CALL PICKJSN(JS(L),MK(L)) 
      CALL PICKUSR(FN(L),UN(L),MK(L)) 
      CALL PICKTRM(TN(L),MK(L)) 
      NJ=L
      L=L+1 
      GOTO 60 
  
  69  IF (ERR) CALL REMARK('   *** TRACE TABLE SEQUENCE ERROR(S).') 
      RETURN
  
  
**        ENTRY -  CALL JSNTRAK(JSN,JCL,DTG,N,LOG)
*                  *JSN* IS JSN FIELD FROM LOG MESSAGE. 
*                  *JCL* IS JOB CLASS CODE FROM LOG MESSAGE.
*                  *DTG* IS DATE/TIME FOR MESSAGE.
*                  *LOG* IS SOURCE LOG INDEX (1=DAYFILE, 2=ACCOUNT).
* 
*         EXIT -   *N*   WILL BE SET TO INDEX OF JOB IN TRACE TABLE.
* 
*         ERROR -  JOB DAYFILE MESSAGES:  
*                  *** TRACE TABLE FULL *** 
*                  STOP    *** SECART TERMINATED. 
* 
*         USES -   COMMON /TRC/ FOR TRACE TABLE STRING DATA.
*                  COMMON /CTL/ FOR TRACE TABLE NUMERIC DATA. 
* 
*         CALLS -  *PICKJSN* FOR NEW JSN SELECTION TEST.
* 
*         NOTES -  BOTH *JSNTRAK* AND *JSNLOOK* USE SAME BINARY SEARCH
*                  CODE TO FIND JSN MATCH AND REMEMBER INDEX OF LAST
*                  MATCH TO ALLOW SHORTCUT FOR CONSECUTIVE MESSAGES BY
*                  SAME JOB WHICH OCCURS ABOUT 2 OUT OF 3 TIMES.
  
      ENTRY JSNTRAK(JSN,JCL,DTG,N,LOG)
  
      LOOK=.FALSE.
      GOTO 100
  
  
**        ENTRY -  CALL JSNLOOK(JSN,N)
*                  *JSN* IS JSN FIELD FROM LOG MESSAGE. 
* 
*         EXIT -   *N*   WILL BE SET TO TRACE TABLE JOB INDEX.
* 
*         ERROR -  NONE.
* 
*         USES -   COMMON /TRC/ FOR TRACE TABLE STRING DATA.
*                  COMMON /CTL/ FOR TRACE TABLE NUMERIC DATA. 
* 
*         CALLS -  *PICKJSN* FOR NEW JSN SELECTION TEST.
* 
*         NOTES -  BOTH *JSNLOOK* AND *JSNTRAK* USE SAME BINARY SEARCH
*                  CODE TO FIND JSN MATCH AND REMEMBER INDEX OF LAST
*                  MATCH TO ALLOW SHORTCUT FOR CONSECUTIVE MESSAGES BY
*                  SAME JOB WHICH OCCURS ABOUT 2 OUT OF 3 TIMES.
  
      ENTRY JSNLOOK(JSN,N)
  
      LOOK=.TRUE. 
      GOTO 100
  
* SHORTCUT FOR REDUNDANT JSN SAME AS LAST CALL [2/3 TIMES]. 
  
  100 IF (JSN.EQ.JS(LST)) THEN
        N=LST 
        GOTO 120
      ENDIF 
  
* BINARY SEARCH FOR MATCH W/ UNIQUE JSN.
  
      L=1 
      H=NJ
  
  105 IF (L.LE.H) THEN
        N=(L+H)/2 
        IF (JSN.LT.JS(N)) THEN
          H=N-1 
        ELSE IF (JSN.GT.JS(N)) THEN 
          L=N+1 
        ELSE
          IF (LOOK) RETURN
          GOTO 120
        ENDIF 
      GOTO 105
      ENDIF 
  
      IF (LOOK) THEN
        N=0 
        RETURN
      ELSE
        N=L 
      ENDIF 
  
* CREATE NEW ROW IN TABLE.
  
  110 IF (NJ.GE.MXJ) GOTO 190 
      NJ=NJ+1 
      IF (N.EQ.NJ) GOTO 113 
  
* OPEN UP ROW IN TABLE. 
  
      DO 112 L=NJ,N,-1
        MK(L)=MK(L-1) 
        JN(L)=JN(L-1) 
        JS(L)=JS(L-1) 
        JC(L)=JC(L-1) 
        TS(L)=TS(L-1) 
        TE(L)=TE(L-1) 
        ML(1,L)=ML(1,L-1) 
        ML(2,L)=ML(2,L-1) 
        FN(L)=FN(L-1) 
        UN(L)=UN(L-1) 
        TN(L)=TN(L-1) 
  112 CONTINUE
  
* INITIALIZE NEW TABLE ROW. 
  
  113 MK(N)=' ' 
      JN(N)=' ' 
      JS(N)=JSN 
      JC(N)=JCL 
      TS(N)=DTG 
      ML(1,N)=0 
      ML(2,N)=0 
      FN(N)=' ' 
      UN(N)=' ' 
      TN(N)=' ' 
      CALL PICKJSN(JSN,MK(N)) 
  
* UPDATE DATE/TIME GROUP AND MESSAGE COUNT/LOG. 
  
  120 TE(N)=DTG 
      ML(LOG,N)=ML(LOG,N)+1 
      LST=N 
      RETURN
  
* JSN TRACE TABLE OVERFLOW. 
  
  190 CALL REMARK('   *** TRACE TABLE FULL ***')
      STOP '   *** SECART TERMINATED.'
  
  
**        ENTRY -  CALL JSNLVL0   [NO ARGUMENTS]. 
*                  MAINTAINS DEADSTART UNIQUE CODE FOR JSN PREFIX.
* 
*         EXIT -   DSU IN /TRC/ "INCREMENTED" TO NEXT LETTER UNLESS 
*                  REDUNDANT CALL.
* 
*         ERROR -  NONE.
* 
*         USES -   COMMON /TRC/ FOR TRACE TABLE STRING DATA.
*                  COMMON /CTL/ FOR TRACE TABLE NUMERIC DATA. 
* 
*         CALLS -  NONE.
* 
*         NOTES -  THIS CODE ALLOWS FOR REDUNDANT CALLS TRIGGERED BY
*                  MULTIPLE MESSAGES RELATING TO THE SAME DEADSTART 
*                  EVENT.  CHECKS FOR AT LEAST 2 JSN-S WITH SAME PREFIX.
  
      ENTRY JSNLVL0 
  
* ALLOW FOR MULTIPLE DFL & ACL MSGS ON DEADSTART. 
  
      IF (NJ.LE.2) RETURN 
      IF (JS(NJ-2)(1:1).NE.DSU) RETURN
      DSU=CHAR(ICHAR(DSU)+1)
      WRITE (8,11) DSU
  11  FORMAT(/'0  ========= L E V E L   0   D / S   ( ',A1, 
     .  ' ) =========') 
      RETURN
  
  
**        ENTRY -  CALL JSNLIST(LFN)
*                  *LFN* CONTAINS LFN OF FILE TO WRITE UNSORTED TRACE 
*                        TABLE DATA.
* 
*         EXIT -   FILE 8 WILL CONTAIN TRACE TABLE PRINTOUT, OPTIONALLY 
*                  SORTED PER DIRECTIVE.
* 
*         ERROR -  NONE.
* 
*         USES -   COMMON /TRC/ FOR TRACE TABLE STRING DATA.
*                  COMMON /CTL/ FOR TRACE TABLE NUMERIC DATA. 
*                  COMMON /SYS/ FOR PRINTOUT HEADER TEXT. 
*                  COMMON /ACL/ FOR ACCOUNT LOG IDENTIFICATION. 
*                  COMMON /DFL/ FOR DAYFILE LOG IDENTIFICATION. 
*                  COMMON /SRT/ FOR TRACE TABLE SORT KEYS.
* 
*         CALLS -  *SM5SORT* ET AL FOR SORT PROCESSING. 
* 
*         NOTES -  THIS ROUTINE WRITES TRACE TABLE DATA ONTO FILE 6,
*                  CALLS SORT/MERGE TO SORT ONTO *TAPE9*, READS DATA
*                  FROM *TAPE9* AND PRINTS TO FILE 8 WITH HEADER TEXT,
*                  PAGINATION, AND SUMMARY DATA.  IF NO SORT KEYS ARE 
*                  SPECIFIED, THE SORT IS BYPASSED AND FILE 6 IS USED 
*                  AS INPUT FOR THE PRINTOUT. 
  
      ENTRY JSNLIST(LFN)
  
      IF (NJ.LE.1) RETURN 
  
* OUTPUT JSN TRACE TABLE FILE & COUNT SELECTIONS. 
  
      NS=0
      DO 605 I=1,NJ 
        WRITE (6,62) MK(I),JN(I),JS(I),JC(I),TS(I),TE(I)
     .    ,ML(1,I),ML(2,I),FN(I),UN(I),TN(I)
  62    FORMAT(1X,A5,1X,A7,1X,A6,1X,A1,2A20,2I5,3A8)
        IF (MK(I).NE.' ') NS=NS+1 
  605 CONTINUE
      LF=6
  
* SORT JSN TRACE TABLE FILE, IF DIRECTED. 
  
      IF (SKY(1).EQ.' ') GOTO 900 
      CALL SM5SORT(0) 
      CALL SM5ENR(NJ) 
      CALL SM5FROM(LFN) 
      CALL SM5TO('TAPE9') 
      DO 850 I=1,12 
  
*               PICKS                     2, 5      NOT SORT KEY. 
  
        IF (SKY(I).EQ.'UJN') CALL SM5KEY( 8, 7,'DISPLAY','A') 
        IF (SKY(I).EQ.'JSN') CALL SM5KEY(16, 6,'DISPLAY','A') 
        IF (SKY(I).EQ.'JC' ) CALL SM5KEY(23, 1,'DISPLAY','A') 
        IF (SKY(I).EQ.'SDT') CALL SM5KEY(24,20,'DISPLAY','A') 
        IF (SKY(I).EQ.'EDT') CALL SM5KEY(44,20,'DISPLAY','A') 
  
*               MSG COUNTS               64,10      NOT SORT KEYS.
  
        IF (SKY(I).EQ.'FM' ) CALL SM5KEY(74, 7,'DISPLAY','A') 
        IF (SKY(I).EQ.'UN' ) CALL SM5KEY(82, 7,'DISPLAY','A') 
        IF (SKY(I).EQ.'TRM') CALL SM5KEY(90, 7,'DISPLAY','A') 
  850 CONTINUE
      CALL SM5END 
      LF=9
  
* PRINTOUT (SORTED) JSN TRACE TABLE.
  
  900 REWIND LF 
      HDR='J S N   T R A C E   T A B L E' 
  
  910 IPAGE=IPAGE+1 
      WRITE (8,1) HDR,PGM,RUNDT,RUNTM,IPAGE 
  1   FORMAT('1',A40,3A10,' PG',I3) 
      L=59
      IF (DFSYSID.NE.' ') THEN
        WRITE (8,91) DFSYSID
        L=L-1 
      ELSE IF (ACSYSID.NE.' ') THEN 
        WRITE (8,91) ACSYSID
        L=L-1 
      ENDIF 
  
      IF (DFSDTG.NE.' ') THEN 
        WRITE (8,92) 'DAYFILE',DFSDTG,DFEDTG
        L=L-1 
      ENDIF 
  
      IF (ACSDTG.NE.' ') THEN 
        WRITE (8,92) 'ACCOUNT',ACSDTG,ACEDTG
        L=L-1 
      ENDIF 
  
      IF (SKY(1).NE.' ') THEN 
        WRITE (8,93) SKY
        L=L-1 
      ENDIF 
  
      WRITE (8,94)
  91  FORMAT('     SYSTEM ID:  ',A60) 
  92  FORMAT('     ',A7, ' LOG ',A20,'  THRU ',A20) 
  93  FORMAT('     SORT KEYS=',12A4)
  94  FORMAT(' PICKS UJN---- --JSN-JC ' 
     .  ,'SDT---------------  EDT----------------  DFL  ACL ' 
     .  ,'FM----- UN[/UI] TRM----') 
  
* COPY (SORTED) FILE TO PRINTOUT & COUNT FOR PAGINATION.
  
  920 READ (LF,95,END=930) TXT
      WRITE (8,95) TXT
  95  FORMAT(A100)
      L=L-1 
      IF (L.GT.0) GOTO 920
      GOTO 910
  
* FOOTNOTE AND SUMMARY TO FINISH PRINTOUT.
  
  930 WRITE (8,97) NJ,NS
  97  FORMAT(/' PICKS: N=UJN, J=JSN, U=USER, T=TERMINAL.' 
     .  /I5,' TRACE TABLE ENTRIES'/I5,' SELECTED JSN-S')
      RETURN
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE AMSLOAD
**        AMSLOAD - ACCOUNT LOG MESSAGE ID MANAGER. 
* 
*         THIS PROGRAM UNIT HANDLES ALL ASPECTS OF ACCOUNT LOG MSG ID 
*         PROCESSING INCLUDING: TABLE INITIALIZATION VIA REFERENCE FILE,
*         MARKING AND SELECTION FOR PRINTOUT, AND COLLECTION AND
*         PRINTOUT OF USAGE STATISTICS.  MULTIPLE ENTRY POINTS ARE
*         PROVIDED FOR THESE FUNCTIONS. 
  
      IMPLICIT INTEGER(A-Z) 
  
      PARAMETER     (MXI=200) 
*                            MAX NUMBER OF MSG ID-S.
  
      CHARACTER*15  CL(MXI) 
*                            JOB CLASS USAGE STRING FOR PRINTOUT. 
  
      LOGICAL       ERR 
*                            FLAG FOR MSG ID SEQUENCE ERROR(S). 
  
      CHARACTER*1   FLAG
*                            ARG - CHARACTER TO FLAG MSG ID FOR PRINT.
  
      INTEGER       H 
*                            TEMP - HIGH POINTER IN BINARY SEARCH.
  
      CHARACTER*40  HDR 
*                            /SYS/ PRINTOUT HEADER TEXT.
  
      LOGICAL       HIT 
*                            ARG - FLAG RETURNED FOR MSG PRINTOUT.
  
      INTEGER       HITS
*                            COUNT OF MSGS SELECTED FOR PRINTOUT. 
  
      CHARACTER*4   ID(MXI) 
*                            ACCOUNT MESSAGE IDENTIFIERS. 
  
      INTEGER       IPAGE 
*                            LOCAL PAGINATION COUNTER.
  
      CHARACTER*1   JCL 
*                            ARG - JOB CLASS CODE.
  
      CHARACTER*20  JCLASS
*                            CONSTANT - STRING OF JOB CLASS CODES.
  
      INTEGER       L 
*                            TEMP - LOW POINTER IN BINARY SEARCH. 
  
      INTEGER       MC(MXI) 
*                            OCCURRENCE COUNTERS FOR MSG ID-S.
  
      CHARACTER*4   MID 
*                            ARG - MESSAGE IDENTIFIER.
  
      CHARACTER*1   MK(MXI) 
*                            MSG ID SELECTION MARKS.
  
      INTEGER       MODE
*                            LOAD/MARK/TEST MODE SWITCH.
  
      INTEGER       N 
*                            TEMP - INDEX VARIABLE. 
  
      INTEGER       NI
*                            NUMBER OF MSG ID-S STORED IN TABLE.
  
      CHARACTER*10  PGM 
*                            /SYS/ *SECART* VERSION ID FOR PRINTOUTS. 
  
      INTEGER       PICKED
*                            COUNT OF MSG ID-S PICKED FOR PRINTOUT. 
  
      CHARACTER*10  RUNDT 
*                            /SYS/ *SECART* RUN DATE FOR PRINTOUTS. 
  
      CHARACTER*10  RUNTM 
*                            /SYS/ *SECART* RUN TIME FOR PRINTOUTS. 
  
      INTEGER       TOTAL 
*                            COUNT OF ALL ACCOUNT MSG ID-S. 
  
      CHARACTER*40  TX(MXI) 
*                            DESCRIPTIONS FOR ACCOUNT MSG ID-S. 
  
  
* GLOBAL STRING VARIABLES.
  
      COMMON /SYS/  HDR 
      COMMON /SYS/  PGM 
      COMMON /SYS/  RUNDT 
      COMMON /SYS/  RUNTM 
  
      DATA JCLASS   /'ABCDMNRSTX0123 '/ 
  
  
**        ENTRY -  CALL AMSLOAD   [NO ARGUMENTS]. 
*                  LOADS MSG ID TABLE FROM FILE 5 AND CHECKS FOR
*                  SEQUENCE ERRORS.  NON-BLANK MARK FIELDS MAY BE USED
*                  FOR DEFAULT SELECTION OF MSG ID-S. 
* 
*         EXIT -   PRINTOUT (FILE 8) MESSAGE: 
*                  NNN ACCOUNT MSG ID-S LOADED. 
* 
*         ERROR -  JOB DAYFILE MESSAGE: 
*                  *** MSGID SEQUENCE ERROR(S). 
* 
*         CALLS -  NONE.
  
      NI=0
      ERR=.FALSE. 
  50  READ (5,51,END=59) ID(NI+1),MK(NI+1),TX(NI+1) 
  51  FORMAT(1X,A4,A1,A40)
      NI=NI+1 
      MC(NI)=0
      CL(NI)='...............'
      IF (NI.LT.2) GOTO 50
      IF (ID(NI).LE.ID(NI-1)) ERR=.TRUE.
      IF (NI.LT.MXI) GOTO 50
      GOTO 190
  
  59  IF (ERR) CALL REMARK('   *** MSGID SEQUENCE ERROR(S).') 
      WRITE (8,*) NI,' ACCOUNT MSG ID-S LOADED.'
      RETURN
  
  
**        ENTRY -  CALL AMSMARK(MID,FLAG) 
*                  *MID*  CONTAINS MSG ID TO BE MARKED FOR PRINTOUT.
*                         WILL ADD TO TABLE IF NOT FOUND. 
*                  *FLAG* CONTAINS SINGLE FLAG CHARACTER: 
*                         NON-BLANK TRIGGERS PRINTOUT ON OCCURRENCE.
*                         BLANK SUPPRESSES PRINTOUT (OVERRIDE DEFAULT). 
* 
*         EXIT -   NO CHANGE TO INPUT ARGUMENTS.
* 
*         ERROR -  JOB DAYFILE MESSAGE: 
*                  *** MSGID TABLE FULL *** 
*                  STOP *** SECART TERMINATED.
* 
*         CALLS -  NONE.
  
      ENTRY AMSMARK(MID,FLAG) 
      MODE=2
      GOTO 100
  
  
**        ENTRY -  CALL AMSTEST(MID,JCL,HIT)
*                  *MID*  CONTAINS MSG ID TO TEST FOR SELECTION AND 
*                         RECORD USAGE STATISTICS.  UNKNOWN ID-S WILL BE
*                         AUTOMATICALLY ADDED TO TABLE W/O DEFINITION.
*                  *JCL*  CONTAINS 1-CHAR JOB CLASS OF SUBJECT JOB. 
*                  *HIT*  LOGICAL FLAG SET TO INDICATE SELECTION. 
* 
*         EXIT -   *HIT*  .TRUE. IF MSG ID MARK FIELD IS NON-BLANK. 
*                  *HIT*  .FALSE. IF MSG ID MARK FIELD IS BLANK.
* 
*         ERROR -  JOB DAYFILE MESSAGE: 
*                  *** MSGID TABLE FULL *** 
*                  STOP *** SECART TERMINATED.
* 
*         CALLS -  NONE.
  
      ENTRY AMSTEST(MID,JCL,HIT)
      MODE=3
  
* SAFETY CHECK FOR EMPTY TABLE. 
  
  100 IF (NI.EQ.0) THEN 
        N=NI+1
        GOTO 130
      ENDIF 
  
* BINARY SEARCH FOR MATCH/INSERT POINT. 
  
      L=1 
      H=NI
  110 N=(L+H)/2 
      IF (MID.GT.ID(N)) THEN
        L=N+1 
      ELSE IF (MID.LT.ID(N)) THEN 
        H=N-1 
      ELSE
        GOTO 140
      ENDIF 
  
      IF (L.LE.H) GOTO 110
      N=L 
  
* INSERT ID IN ALPHABETIC SEQUENCE. 
  
      IF (NI.GE.MXI) GOTO 190 
      NI=NI+1 
      IF (N.EQ.NI) GOTO 130 
  
* OPEN UP ROW IN TABLE. 
  
      DO 125 L=NI,N,-1
        ID(L)=ID(L-1) 
        CL(L)=CL(L-1) 
        MC(L)=MC(L-1) 
        MK(L)=MK(L-1) 
        TX(L)=TX(L-1) 
  125 CONTINUE
      GOTO 135
  
* ADD NEW ID ONTO BOTTOM. 
  
  130 IF (NI.GE.MXI) GOTO 190 
      NI=N
  
* CREATE NEW ENTRY. 
  
  135 ID(N)=MID 
      CL(N)='...............' 
      MC(N)=0 
      MK(N)=' ' 
      TX(N)=' ' 
  
* MARK MSG ID FOR PRINTOUT. 
  
  140 IF (MODE.EQ.2) THEN 
        MK(N)=FLAG
  
* COUNT, RECORD JCL DIST, & TEST FOR FLAGGED MID. 
  
      ELSE
        MC(N)=MC(N)+1 
        L=INDEX(JCLASS,JCL) 
        IF (L.GT.0) CL(N)(L:L)=JCL
        IF (L.EQ.0) CL(N)(15:15)='?'
        IF (MK(N).NE.' ') HIT=.TRUE.
      ENDIF 
      RETURN
  
* ERROR EXIT. 
  
  190 CALL REMARK('   *** MSGID TABLE FULL ***')
      STOP '   *** SECART TERMINATED.'
  
  
**        ENTRY -  CALL AMSLIST  [NO ARGUMENTS].
*                  PRODUCES LISTING CONTAINING ALL PRE-DEFINED AND
*                  ENCOUNTERED ACCOUNT LOG MESSAGE ID-S WITH COUNT OF 
*                  OCCURRENCES, USAGE BY JOB CLASS, PRINTOUT SELECTION
*                  FLAGS, AND DESCRIPTIONS.  BLANK DESCRIPTION FIELD
*                  TYPICALLY INDICATES NO MATCHING ID IN REFERENCE FILE.
* 
*         EXIT -   NORMAL RETURN ONLY.
* 
*         ERROR -  NONE.
* 
*         USES -   COMMON /SYS/ FOR PRINTOUT HEADER TEXT. 
* 
*         CALLS -  NONE.
  
      ENTRY AMSLIST 
      IPAGE=0 
      TOTAL=0 
      PICKED=0
      HITS=0
      N=0 
  
  150 IPAGE=IPAGE+1 
      HDR='A C C O U N T   M E S S A G E   I D - S' 
      WRITE (8,1) HDR,PGM,RUNDT,RUNTM,IPAGE 
  1   FORMAT('1',A40,3A10,' PG',I3) 
      WRITE (8,15)
  15  FORMAT(' MSID  COUNT JOB CLASSES     S DESCRIPTION' 
     .      /' ==== ====== =============== = =======================')
      L=58
  160 N=N+1 
      IF (N.GT.NI) GOTO 170 
      WRITE (8,16) ID(N),MC(N),CL(N),MK(N),TX(N)
  16  FORMAT(1X,A4,I7,1X,A15,1X,A1,1X,A40)
      TOTAL=TOTAL+MC(N) 
      IF (MK(N).NE.' ') THEN
        PICKED=PICKED+1 
        HITS=HITS+MC(N) 
      ENDIF 
      L=L-1 
      IF (L)150,150,160 
  
  170 WRITE (8,17) TOTAL,NI,HITS,PICKED 
  17  FORMAT('  ==========' 
     .  /I12,' MESSAGES ',I3,' TYPES TOTAL' 
     .  /I12,' FOUND OF ',I3,' TYPES SELECTED') 
      RETURN
      END 
  
* --------------------------------------------------------------------- 
      SUBROUTINE PARSE(TXT,IT,WORD) 
**        PARSE  - SIMPLE TEXT STRING PARSER. 
* 
*         *PARSE* SCANS STRING *TXT*, STARTING AT POSITION *IT*,
*         EXTRACTING NON-BLANKS TO BUILD *WORD*, STOPS AT DELIMITER,
*         AND SETS *IT* JUST PAST DELIMITER FOR NEXT TIME.
* 
*         ENTRY -  CALL PARSE(TXT,IT,WORD)
*                  *TXT*  CONTAINS TEXT STRING TO BE SCANNED. 
*                  *IT*   SPECIFIES STARTING POSITION (1-XX) IN *TXT* 
* 
*         EXIT -   *IT*   WILL BE SET TO POSITION AFTER DELIMITER.
*                  *WORD* WILL BE CONTAIN WORD FOUND OR BLANKS. 
* 
*         ERROR -  NONE.
* 
*         COMMON - NONE.
* 
*         CALLS -  NONE.
* 
*         NOTES -  *PARSE* PRECHECKS LENGTH OF *TXT* STRING AND CHECKS
*                  FOR *IT* PAST EOL.  RECOGNIZED DELIMITERS INCLUDE
*                  BOTH SEPARATORS AND TERMINATORS.  THE FTN5 *INDEX* 
*                  FUNCTION IS USED FOR FAST DELIMITER MATCHING.
  
      IMPLICIT INTEGER(A-Z) 
  
      CHARACTER*25  DELIM 
*                            CONSTANT - RECOGNIZED DELIMITERS.
  
      INTEGER       IT
*                            ARGUMENT - START/FINISH STRING POSITION. 
  
      CHARACTER*(*) TXT 
*                            ARGUMENT - TEXT STRING TO SCAN.
  
      CHARACTER*(*) WORD
*                            ARGUMENT - RETURNED TEXT STRING. 
  
      DATA DELIM    /'$/.)(,=+-#[]%"_!&''?<>@\^;'/
  
* SIMPLE TEXT PARSER ROUTINE. 
  
      L=LEN(TXT)
      M=LEN(WORD) 
      WORD=' '
      J=0 
  
* PRE-CHECK FOR EOL.
  
      IF (IT.GT.L) RETURN 
  
* WATCH FOR DELIMITER.
  
  100 IF (INDEX(DELIM,TXT(IT:IT)).EQ.0) THEN
  
* EXTRACT NON-BLANKS AND CATENATE INTO *WORD*.
  
        IF (TXT(IT:IT).NE.' '.AND.J.LT.M) THEN
          J=J+1 
          WORD(J:J)=TXT(IT:IT)
        ENDIF 
  
* ADVANCE AND CHECK FOR EOL.
  
        IT=IT+1 
        IF (IT.LE.L) GOTO 100 
        RETURN
      ELSE
  
* FOUND DELIMITER.
  
        IT=IT+1 
        RETURN
      ENDIF 
      END 
