2!		PROGRAM		: ERRINT
5!		VERSION		: V10.1
6!		EDIT		: A
7!		EDIT DATE	: 10-MAY-91
10	EXTEND
11	! &
	&
	&
	!		  C O P Y R I G H T &
	&
	&
  !		      Copyright (C) 1976, 1991 by &
  !	        Digital Equipment Corporation, Maynard, Mass. &
  !	&
  !	&
  !	This software is furnished under a license and may be used and &
  !	copied  only  in accordance with the terms of such license and &
  !	with the  inclusion  of  the  above  copyright  notice.   This &
  !	software  or  any  other copies thereof may not be provided or &
  !	otherwise made available to any other person.  No title to and &
  !	ownership of the software is hereby transferred. &
  !	&
  !	The information in this software is subject to change  without &
  !	notice  and should not be construed as a commitment by Digital &
  !	Equipment Corporation. &
  !	&
  !	DIGITAL assumes no responsibility for the use  or  reliability &
  !	of its software on equipment that is not supplied by DIGITAL. &
  !	&
  !******************************************************************* &
	&

20	! &
	&
	&
	!	M O D I F I C A T I O N    H I S T O R Y &
	&
	&

21	! VER/ED	EDIT DATE	REASON &
	! V9.0-12 VAM	10-Feb-85	Delete ERRLOG.TMP if already present &
	! V9.0-13 VAM	04-Mar-85	Don't allow Error Logger to be run &
	!				twice &
	! V9.0-13 VAM	15-Mar-85	Add privilege check &
	! 9.3		10-NOV-86	ADD UNDERSCORE TO NL:'S &
	! &
	&

100	! &
	&
	&
	!	G E N E R A L    D E S C R I P T I O N &
	&
	&

110!	&
   !	 ERRINT performs 4 functions: &
   !	        1. Generates and initializes the  error  logging  file &
   !	           (ERRLOG.FIL). &
   !	        2. Validates an existing error log file. &
   !	        3. Appends  ERRLOG  file  generated by ANALYS during a &
   !	           crash recovery to ERRLOG.FIL &
   !		4. Checks to insure that no attempt is made to start the &
   !		   Error Logger twice. &
   !	&
   !	 ERRINT is entered by typing RUN $ERRINT or is CHAINed  to  by &
   !	 the ERRCPY program. &
   !	&
   !	 If the program is 'RUN', ERRLOG.FIL is OPENed FOR INPUT. &
   !	 If the file does not exist: &
   !	         Function 1 is performed. &
   !	 If the file does exist and is found to be invalid: &
   !	         The old file is renamed ERRLOG.TMP, &
   !	         An informative message is output and &
   !	         Function 1 is performed. &
   !	&
   !	If ERRLOG.TMP already exists, then an error will occur when we try &
   !	to rename the old file to ERRLOG.TMP.  In this case, we simply &
   !	delete the old ERRLOG.TMP and try again. &
   !	&
   !	 Once  the  file  has  been  validated  or initialized, ERRINT &
   !	 calculates and prints the percentage of  the  file  currently &
   !	 used and the maximum size.  The user may then change the size &
   !	 if so desired.  Next ERRINT asks if the crash  file  contents &
   !	 should  be  used.  If the answer is yes, then ERRINT performs &
   !	 function 3. &
   !	&
   !	 If ERRCPY cannot find ERRLOG.FIL, it  CHAINs  to  ERRINT  and &
   !	 ERRINT  performs  function 1 and then immediately CHAINs back &
   !	 to ERRCPY.  If ERRINT was entered  from  a  run  command,  it &
   !	 detaches  just  before  CHAINing  to ERRCPY.  If entered from &
   !	 ERRCPY, it is already detached.  Note that all validation  is &
   !	 performed  on  the Header Control fields only and consists of &
   !	 range checks on each  field.   Initialization  of  number  of &
   !	 errors of each type is performed according to a table of DATA &
   !	 Statements.  The error file maximum length  is  set  at  file &
   !	 creation   time   according   to  the  last  DATA  Statement. &
   !	&

300	! &
	&
	&
	!	I / O    C H A N N E L S &
	&
	&

301!	CHANNEL #	USED FOR &
   !
310!	  2		ERRLOG.FIL  THE ERROR LOG FILE &
   !	  3		ERRCRS.FIL  THE ERROR LOG FILE FROM ANALYS &
   !      4		NULL DEVICE  STORES ERRCRS.FIL RECORD 1 &
   !			OR ERRLOG.FIL RECORD n (I.E., THE ERROR RECORD &
   !			BEING PROCESSED). &

400	! &
	&
	&
	!	V A R I A B L E    D E F I N I T I O N S &
	&
	&

401!	VARIABLE NAME	USE &
   !
450!	BYT.POS$		BYTE POSITION BLOCK TOT.USED$ WHERE NEXT &
   !				ERROR RECORD IS TO BE WRITTEN. &
   !	ENTRY.TYP%		ENTRY TYPE FLAG. &
   !	INIT.OR.VALID%		VALIDATE (0%) OR INITIALIZE(-1%) FLAG. &
   !	SWAP$			[NO]SWAP FLAG FOR ERRCPY &
   !	TOT.LOG$		TOTAL ERRORS LOGGED (INCLUDING REPEATS). &
   !	TOT.REC$		TOTAL ERRORS RECEIVED (INCLUDING REPEATS). &
   !	TOT.USED$		BLOCK NUMBER FOR START OF NEXT ERROR RECORD. &
   !	TOT.LIM$		LIMIT ON NUMBER OF ERROR BLOCKS IN FILE. &
   !	W%			UTILITY VARIABLE &
   !	W$			UTILITY STRING &
   !	W1%			UTILITY VARIABLE &
	&

800	! &
	&
	&
	!	F U N C T I O N / S U B R O U T I N E    D E S C . &
	&
	&

801!	FUNCTION/SUBROUTINE		USE &
   !	10000				PROCESS A MESSAGE STRING AND &
   !					ADD IT TO ERROR LOG FILE &
   !
900	! &
	&
	&
	!	D I M E N S I O N    S T A T E M E N T S &
	&
	&

910	DIM S%(30%) &
	! USED FOR PARAMETER PORTION OF MESSAGE AND &
	! EXTRACTING PACKAGE LOCATION &

999	! &
	&
	&
	!	M A I N    C O D I N G    A R E A &
	&
	&

1000	ON ERROR GOTO 19000 &
	\ ENTRY.TYP%=0% &
	\ PRINT IF CCPOS(0%)<>0% &
		! SET UP STANDARD ERROR TRAP. &
		! SET RUN TYPE FLAG TO 'RUN'. &
		! RETURN KB TO LEFT MARGIN. &

1010	I$="V10.1-A" &
		! SET UP VERSION/EDIT #. &

1020	PRINT "ERRINT";CHR$(9%);I$;CHR$(9%); &
	CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)+CHR$(0%)),3%),4%) &
		! PRINT HEADER IF RUN ENTRY. &

1030	PKG.LOC$="ERROR$:" &
	\ W$=SYS(CHR$(6%)+CHR$(-21%)+CHR$(255%)) &
	\ IF NOT FNPRIV%("SWCTL") THEN &
		PRINT "?SWCTL privilege required" &
		\ GOTO 32760 &
	! Set up our package location. &
	! Temporarily drop temporary privileges. &
	! If we don't have SWCTL priv, let 'em know and quit. &

1050	W$=SYS(CHR$(6%)+CHR$(-21%)+CHR$(0%)) &
	\ GOTO 3030 IF ENTRY.TYP%=2% &
	\ GOTO 1090 IF ENTRY.TYP% &
	\ X$=SYS(CHR$(6%)+CHR$(-12%)) &
	\ SNDLST%=PEEK(SWAP%(CVT$%(MID(X$,19%,2%)))) &
	\ ERLOG.JOB%=PEEK(SNDLST%+8%) AND 255% &
	\ IF ERLOG.JOB% THEN &
		IF ERLOG.JOB%<>(PEEK(518%) AND 255%) THEN &
			PRINT "?Error Logger is already running" &
			\ GOTO 32760 &
	! Get our privs back. &
	! Go re-create the file if we were asked to. &
	! Skip looking at the RIBs unless we were runded. &
	! Look at the first RIB, which is always for ERRLOG. &
	! If there's no job filled in, we're the first. &
	! If it's the same job number as ours, everything is cool. &
	! Otherwise, tell 'em to forget it and exit. &

1090	S%(I%)=0% FOR I%=0% TO 30% &
	\ OPEN PKG.LOC$+"ERRLOG.FIL" FOR INPUT AS FILE 2% &
	\ GET #2%,RECORD 1% &
	\ INIT.OR.VALID%=0% &
		! TRY TO OPEN THE ERROR FILE. &
		! GET THE HEADER RECORD. &
		! SET INIT/VALIDATE FILE SWITCH TO VALIDATE. &
	&

1100	! &
	&
	&
	!	V A L I D A T E    O R    I N I T I A L I Z E &
	!		E R R O R    F I L E &
	&

1120	ZR$=CVT%$(0%) &
	\ RESTORE &
	\ READ W1%,W2% &
		! INPUT THE ERROR CODE LIMIT AND THE ERROR CODE &
		! RECORD LIMIT. &

1130	FOR W%=0% TO 61% &
	\	FIELD #2%, W%*8% AS W$, 2% AS RECRD.LOG$, 2% AS ER.LOG$, &
		2% AS ER.RCV$, 2% AS RECRD.ALW$ &
	\	READ W1%,W2% IF W%>W1% &
	\	IF INIT.OR.VALID%=0% THEN &
			IF CVT$%(RECRD.LOG$)>CVT$%(RECRD.ALW$) OR &
			(CVT$%(RECRD.ALW$)<W2%) OR &
			(CVT$%(ER.RCV$)<CVT$%(ER.LOG$)) THEN &
				3000 &
			ELSE	1190 &
		! FIELD THE RECORD &
		! READ NEXT ENTRY IN LIMITS TABLE IF CURRENT ERROR TYPE &
		! #(W%) IS GREATER THAN CURRENT # IN TABLE (W1%) &
		! &
		! IF    V A L I D A T I N G    THEN &
		!	IF (FOR THIS ERROR TYPE) &
		!	# OF ERRORS LOGGED > # OF ERRORS ALLOWED OR &
		!	# OF ERRORS ALLOWED < DEFAULT OR &
		!	# OF ERRORS RECEIVED < # OF ERRORS LOGGED &
		!				  AND REPEATED &
		!		THEN	ERROR &

1180		LSET RECRD.LOG$=ZR$ &
	\	LSET ER.LOG$=ZR$ &
	\	LSET ER.RCV$=ZR$ &
	\	LSET RECRD.ALW$=CVT%$(W2%) &
		! &
		!	I N I T I A L I Z I N G &
		! &
		! SET COUNTERS TO 0 &
		! SET LIMIT RECRD.ALW$ TO VALUE FROM TABLE OF LIMITS &

1190	NEXT W% &

1200	FIELD #2%, 496% AS W$, 2% AS TOT.LOG$, 2% AS TOT.REC$, &
		2% AS TOT.USED$, 2% AS BYT.POS$, 2% AS TOT.LIM$ &
	\ IF INIT.OR.VALID%=0% THEN &
		IF CVT$%(TOT.LOG$)>CVT$%(TOT.REC$) OR &
		CVT$%(TOT.USED$)>CVT$%(TOT.LIM$) OR &
		CVT$%(BYT.POS$)>511% THEN &
			3000 &
		ELSE	1250 &
		! FIELD GENERAL CONTROL RECORD IN HEADER BLOCK. &
		! &
		! IF    V A L I D A T I N G    THEN &
		!	IF TOTAL ERRORS LOGGED > TOTAL RECEIVED &
		!	(INCLUDING REPEATS) OR &
		!	NEXT RECORDS BLOCK # > BLOCK # LIMIT OR &
		!	BYTE POSITION IN THAT BLOCK > 511 THEN &
		!		ERROR &

1230	LSET TOT.LOG$=ZR$ &
	\ LSET TOT.REC$=ZR$ &
	\ LSET TOT.USED$=CVT%$(2%) &
	\ LSET BYT.POS$=ZR$ &
	\ LSET TOT.LIM$=CVT%$(W2%) &
		! INITIALIZE GENERAL CONTROL RECORD &

1250	GOTO 2000 IF ENTRY.TYP%=0% &
	\ GOTO 2510 IF ENTRY.TYP%=6% &
		! GO TO USER INTERACTION IF RUN ENTRY. &
		! GO TO 'UTILIZE CRASH FILE' ROUTINE IF ATPK ENTRY &
		!  INDICATES THAT WE SHOULD. &

1260	PUT #2%, RECORD 1% &
	\ CLOSE 2%,3%,4% &
		! PUT THE HEADER AWAY. &

1265	IF ENTRY.TYP%=0% THEN &
		PRINT IF CCPOS(0%)<>0% &
	\	PRINT "Detaching . . ." &
	\	W$=SYS(CHR$(6%)+CHR$(7%)) &
		! DETACH IF WE ENTERED ERRINT FROM RUN COMMAND &

1270	SWAP$ = SYS(CHR$(8%)+SWAP$) &
\	CHAIN PKG.LOC$+"ERRCPY" LINE 31000 &
		! PUT SWAP/NOSWAP IN CORE COMMON &
		! CHAIN TO ERRCPY &
	&

1500	DATA 62,100 &
	&
	&
	&

2000	! &
	&
	&
	!	U S E R   I N T E R A C T I O N &
	&
	&

2010	TOT.LIM=CVT$%(TOT.LIM$) &
	\ TOT.USED=CVT$%(TOT.USED$) &
	\ PERC%=0% &
	\ PERC%=100%*(TOT.USED/TOT.LIM) IF TOT.LIM<>0. &
		! CALCULATE % OF ERROR FILE CURRENTLY OCCUPIED &

2020	PRINT IF CCPOS(0%)<>0% &
	\ PRINT "ERRLOG File is ";NUM1$(PERC%);"% Full" &
	\ PRINT "Change Size to <";TOT.LIM;">"; &
	\ INPUT W$ &
	\ W$=CVT$$(W$,-2%) &
	\ SWAP$="SWAP" &
	\ LOCK% = INSTR(1%,W$,"/L") &
	\ SWAP$="NOSWAP" IF LOCK%<>0% &
	\ W$=LEFT(W$,LOCK%-1%) IF LOCK%<>0% &
	\ GOTO 2020 IF LEN(W$)>4% &
	\ IF LEN(W$)<>0% THEN &
		W%=VAL(W$) &
	\	GOTO 2020 IF W%<0% OR W%<CVT$%(TOT.USED$) &
	\	LSET TOT.LIM$=CVT%$(W%) &
		! CHECK NEW FILE SIZE AND IF VALID INSERT SAME &

2030	PRINT IF CCPOS(0%)<>0% &
	\ PRINT "Utilize Crash File Output (Yes/No) <No>"; &
	\ INPUT W$ &
	\ W$=CVT$$(W$,-2%) &
	\ GOTO 1260 IF LEN(W$)=0% OR (LEN(W$)=2% AND W$="NO") &
	\ GOTO 2510 IF LEN(W$)=3% AND W$="YES" &
	\ GOTO 2030 &
	&

2500	! &
	&
	&
	!	M E R G E    $ E R R C R S . F I L &
	&

2510	OPEN PKG.LOC$+"ERRCRS.FIL" FOR INPUT AS FILE 3% &
	\ OPEN "_NL:" AS FILE 4%, RECORDSIZE 512% &
	\ GET #3%+SWAP%(4%), RECORD 1% &
	\ FOR W%=0% TO 61% &
	\	FIELD #4%, W%*8% AS CW$, 2% AS CRS.RECRD.LOG$, &
		2% AS CRS.ER.LOG$, 2% AS CRS.ER.RCV$, 2% AS CRS.RECRD.ALW$ &
	\	GOTO 2550 IF &
			CVT$%(CRS.RECRD.LOG$)>CVT$%(CRS.RECRD.ALW$) OR &
			(CVT$%(CRS.RECRD.ALW$)<40%) OR &
			(CVT$%(CRS.ER.RCV$)<CVT$%(CRS.ER.LOG$)) &
	\ NEXT W% &
	\ FIELD #4%, 496% AS CW$, 2% AS CRS.TOT.LOG$, 2% AS CRS.TOT.REC$, &
		2% AS CRS.TOT.USED$, 2% AS CRS.BYT.POS$, 2% AS CRS.TOT.LIM$ &
	\ CRS.TOT.USED%=CVT$%(CRS.TOT.USED$) &
	\ CRS.BYT.POS%=CVT$%(CRS.BYT.POS$) &
	\ GOTO 2550 IF &
		(CVT$%(CRS.TOT.LOG$)>CVT$%(CRS.TOT.REC$)) OR &
		(CRS.TOT.USED%>CVT$%(CRS.TOT.LIM$)) OR &
		(CRS.BYT.POS%>511%) &
	\ GOTO 1260 IF (CRS.TOT.USED%=0% AND CRS.BYT.POS%=0%) &
	\ CRS.TOT.USED%=CRS.TOT.USED%-1% IF CRS.BYT.POS%=0% &
		! VALIDATE CONTROL RECORD; ERROR PROHIBITS MERGE. &
		! DON'T BOTHER IF HAPPENED TO PASS VALIDATION BUT &
		! NOTHING THERE. &

2520	FOR W%=2% TO CRS.TOT.USED% &
	\	PREV%=0% &
	\	GET #3%, RECORD W%
2530		FIELD #3%, PREV% AS W$, 2% AS L$ &
	\	LNGTH%=CVT$%(L$) &
	\	GOTO 2540 IF LNGTH%=0% OR LNGTH%<22% OR (LNGTH%+PREV%)>512% &
	\	FIELD #3%, PREV%+2% AS W$,20% AS PARAM$,(LNGTH%-22%) AS M1$ &
	\	CHANGE PARAM$ TO S% &
	\	ER.COD%=S%(1%) &
	\	REPEAT%=0% &
	\	REPEAT%=S%(4%) UNLESS ER.COD%=55% &
	\	GOSUB 10010 &
	\	PREV%=PREV%+LNGTH% &
	\	GOTO 2530 UNLESS PREV%>490% &
		! SET UP MAX BLOCK # &
		! GET RECORD LENGTH &
		! IF LENGTH IS 0 OR LESS THAN 22 OR IF IT SPILLS OFF END &
		! OF BLOCK THEN GO ON TO NEXT BLOCK &
		! FIELD OUT PARAMETERS AND MESSAGE DATA &
		! SET UP ERROR CODE AND REPEAT COUNT (0 IF 'UNRECOGNIZED MSG') &
		! GO ADD THIS ERROR TO ERRLOG.FIL &
		! GET THE NEXT RECORD OF IF NO MORE IN THIS BLOCK THEN &
		! GO ON TO NEXT BLOCK &

2540	NEXT W% &
	\ GOTO 1260 &
		! NEXT BLOCK &
		! ALL DONE SO RETURN &

2550	GOTO 1260 UNLESS ENTRY.TYP%=0% &
	\ PRINT IF CCPOS(0%)<>0% &
	\ PRINT "Crash Error File was found to be Invalid" &
	\ GOTO 2570 &
		! CONTROL RECORD INCONSISTENCY. &

2560	GOTO 1260 UNLESS ENTRY.TYP%=0% &
	\ PRINT IF CCPOS(0%)<>0% &
	\ PRINT "Zero Length Crash Error File" &
		! ERROR ON FIRST 'GET'. &

2570	PRINT "Merge will not be done" &
	\ GOTO 1260 &
		! CANNOT DO THE MERGE. &

3000	! &
	&
	&
	!	I N V A L I D   E R R O R   F I L E &
	&
	&

3010	NAME PKG.LOC$+"ERRLOG.FIL" AS PKG.LOC$+"ERRLOG.TMP" &
	\ GOTO 3030 UNLESS ENTRY.TYP%=0% &
	\ PRINT IF CCPOS(0%)<>0% &
	\ PRINT "Error File was found to be Invalid" &
	\ PRINT "New File was generated and Invalid File renamed "; &
		PKG.LOC$;"ERRLOG.TMP" &
		! SAVE A COPY OF THE OLD FILE. &
		! LET THE USER KNOW WHAT HAPPENED. &
	&

3030	OPEN PKG.LOC$+"ERRLOG.FIL" FOR OUTPUT AS FILE 2% &
	\ INIT.OR.VALID%=-1% &
	\ GOTO 1100 &
		! GENERATE THE NEW FILE. &
		! SET SWITCH TO INDICATE INITIALIZATION. &
		! GO AND INITIALIZE THE FILE. &
	&

3040	GOTO 3030 UNLESS ENTRY.TYP%=0% &
	\ PRINT IF CCPOS(0%)<>0% &
	\ PRINT "Error File is Zero Length - will be recreated" &
	\ GOTO 3030 &
		! TAKE CARE OF THE ERROR ON THE FIRST "GET". &

3090	KILL PKG.LOC$+"ERRLOG.TMP" &
	\ GOTO 3010 &
	! Here's where we end up if ERRLOG.TMP already exists. &
	! Get rid of the old file and try again. &
	&

10000	! &
	&
	&
	!	S U B R O U T I N E S &
	&
	&
	&
	!	P R O C E S S    E R R O R    M E S S A G E &
	&
	&

10010	FIELD #2%, ER.COD%*8% AS W$, 2% AS RECRD.LOG$, 2% AS ER.LOG$, &
		   2% AS ER.RCV$, 2% AS RECRD.ALW$ &
	\ LSET ER.RCV$=CVT%$(CVT$%(ER.RCV$)+REPEAT%+1%) &
	\ LSET TOT.REC$=CVT%$(CVT$%(TOT.REC$)+REPEAT%+1%) &
	\ GOTO 10100 IF &
		(CVT$%(RECRD.LOG$)>=CVT$%(RECRD.ALW$)) OR &
		CVT$%(TOT.USED$)>=CVT$%(TOT.LIM$) &
		! ER.COD% = THE CODE FOR THE ERROR TYPE &
		! REPEAT% = ERROR REPEAT COUNT &
		! LNGTH%  = LENGTH OF THE MESSAGE TRANSFERRED+ &
		!           2 BYTES FOR THE LENGTH FIELD+ &
		!           20 BYTES FOR THE PARAMETER STRING &
		! FIELD THE HEADER RECORD FOR ERROR TYPE ER.COD%. &
		! BUMP THE # OF ERRORS RECEIVED FOR THIS TYPE. &
		! BUMP THE TOTAL # OF ERRORS RECEIVED. &
		! &
		! QUIT HERE IF # OF RECORDS LOGGED IS = MAX FOR ERROR &
		! TYPE ER.COD% OR IF FILE LENGTH EXCEEDS MAX ALLOWABLE. &

10050	BLK%=CVT$%(TOT.USED$) &
	\ OFFSET%=CVT$%(BYT.POS$) &
	\ IF (512%-OFFSET%)<LNGTH% THEN &
		BLK%=BLK%+1% &
	\	OFFSET%=0% &
		! BLK%=BLOCK # &
		! OFFSET%=OFFSET IN BLOCK BLK% WHERE NEXT RECORD STARTS &
		! IF REMAINING SPACE IN BLOCK IS LESS THAN ERROR RECORD &
		! LENGTH THEN &
		!	BUMP BLOCK # AND RESET OFFSET TO BEGINNING OF BLOCK &

10060	GET #2%+SWAP%(4%), RECORD BLK% UNLESS OFFSET%=0% &
	\ REST%=512%-LNGTH%-OFFSET% &
	\ FIELD #4%, OFFSET% AS W$, LNGTH% AS ER.RECRD$, REST% AS REST$ &
	\ LSET REST$=STRING$(REST%,0%) &
	\ LSET ER.RECRD$=CVT%$(LNGTH%)+PARAM$+M1$ &
	\ PUT #2%+SWAP%(4%), RECORD BLK% &
		! GET THE PROPER BLOCK UNLESS IT'S A NEW ONE. &
		! FIELD IT AND THE 'MESSAGE BUFFER'. &
		! PUT THE TOTAL RECORD LENGTH, THE PARAMETER &
		! STRING AND THE ACTUAL ERROR RECORD INTO THE BLOCK. &
		! WRITE OUT THE BLOCK. &

10070	LSET TOT.USED$=CVT%$(BLK%) &
	\ LSET BYT.POS$=CVT%$(OFFSET%+LNGTH%) &
	\ LSET RECRD.LOG$=CVT%$(CVT$%(RECRD.LOG$)+1%) &
	\ LSET ER.LOG$=CVT%$(CVT$%(ER.LOG$)+REPEAT%+1%) &
	\ LSET TOT.LOG$=CVT%$(CVT$%(TOT.LOG$)+REPEAT%+1%) &
		! UPDATE THE HEADER RECORD: &
		! STORE THE LAST BLOCK # USED. &
		! STORE THE OFFSET INTO BLOCK. &
		! BUMP # OF ERROR RECORDS LOGGED FOR TYPE ER.COD% &
		! BUMP # OF ERRORS (INCLUDING REPEATS) LOGGED FOR TYPE ER.COD% &
		! BUMP TOTAL ERRORS LOGGED (INCLUDING REPEATS) &

10100	RETURN &
	&

19000	! &
	&
	&
	! 	E R R O R    H A N D L E R &
	&

19010	RESUME 3030 IF ERR=5% AND ERL=1090% &
	\ RESUME 3040 IF ERR=11% AND ERL=1090% &
	\ RESUME 32767 IF ERR=11% AND (ERL=2020% OR ERL=2030%) &
	\ RESUME 1260 IF ERR=5% AND ERL=2510% &
	\ RESUME 2560 IF ERR=11% AND ERL=2510% &
	\ RESUME 3090 IF ERR=16% AND ERL=3010% &
	\ RESUME 19020 &
		! ERRLOG.FIL DOESNT EXIST GO CREATE ONE &
		! CATCH CONTROL/Z &
		! ERRCRS.FIL DOESNT EXIST SO SKIP MERGE PHASE &
		! ERRCRS.FIL IS ZERO LENGTH; WILL INFORM USER AND SKIP MERGE. &
		! ERRLOG.TMP already exists - Go wipe it out and try again. &
	&

19020	PRINT "?ERRINT - "; &
	CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)+CHR$(ERR)),3%),4%); &
	" at Line ";ERL &
	\ GOTO 32767 &
		! PRINT ERROR MESSAGE. &
	&

20000	! &
	&
	!	P r i v i l e g e   C h e c k   F u n c t i o n &
	&
	! &
	DEF*	FNPRIV%(X$) &
	\ X$=SYS(CHR$(6%)+CHR$(32%)+CHR$(1%)+STRING$(3%,0%)+X$) &
	\ FNPRIV%=(ASCII(MID(X$,3%,1%))=0%) &
	\ FNEND &
	! This function takes a privilege name as it's argument, and returns &
	!  -1 if the user has the specified privilege, or 0 if not. &
	&

31000	! &
	&
	&
	!	C H A I N   E N T R Y &
	&
	&

31010	ENTRY.TYP%=2% &
	\ GOTO 31100 &
		! WE GOT HERE BECAUSE ERROR FILE DISAPPEARED &
		! SET ENTRY.TYP% TO INDICATE CHAIN ENTRY &

31020	ENTRY.TYP%=4% &
	\ GOTO 31100 &
		! ATPK 'REGULAR START-UP' ENTRY POINT. &

31030	ENTRY.TYP%=6% &
		! ATPK 'CRASH START-UP' ENTRY POINT. &

31100	ON ERROR GOTO 19000 &
	\ SWAP$ = SYS(CHR$(7%)) &
	\ SWAP$ = "SWAP" UNLESS SWAP$ = "NOSWAP" &
	\ PKG.LOC$="ERROR$:" &
	\ GOTO 1030 &
		! GO RE-CREATE THE FILE IF CHAIN FROM ERRCPY. &
		! OTHERWISE, WE'RE ALMOST LIKE A RUN. &

32760	W$=SYS(CHR$(6%)+CHR$(-21%)) &
	\ W$=SYS(CHR$(9%)) &
		! Get rid of privileges for good. &
		! REMOVE OURSELVES FROM MEMORY. &

32767	END
