	.TITLE 	SYMBOL	ROUTINE TO TURN PC'S INTO FORTRAN LINE NUMBERS
	.IDENT	/V01.01/
	.LIBRARY	/[1,1]LIB/	; ADD LIBRARY
 
;++
; FACILITY:	FORTRAN SUBROUTINE
;
; ABSTRACT:	
;	THIS ROUTINE READS THE 'DEBUGGER SYMBOL TABLE' (DST) FROM AN
; 	IMAGE FILE AND ATTEMPTS TO CORRELATE PC VALUES FROM THE CALLING
;	PROGRAM WITH FORTRAN LINE NUMBERS FROM THE DST.  THE RESULTS
;	ARE OUTPUT TO SYS$OUTPUT.
;
; ENVIRONMENT:	USER-MODE, NON-PRIVILEGED
;
;--
;
; AUTHOR:
;		D. ELDERKIN,  CREATION DATE:	29-NOV-78
;
; MODIFIED BY:
;		R. LIPSETT, 23-FEB-79
;
; INCLUDE FILES:
;
	$DSCDEF				;DEFINE DST DESCRIPTOR OFFSETS
	$IHDDEF				;DEFINE IMAGE HEADER OFFSETS
	$IHSDEF				;DEFINE MORE IMAGE HEADER OFFSETS
	$JPIDEF				;DEFINE $GETJPI CODES
	$RMSDEF				;DEFINE RMS ERROR CODES
;
; EXTERNAL SYMBOLS:
;
 
;
; MACROS:
;
 
	.MACRO	TEXT ABC,?A,?B
	.WORD	B-A
	.WORD	0
	.LONG	A
A:
	.ASCII	\ABC\
B:
	.ENDM
 

	.MACRO	ERROR	ERRNUM
	PUSHL	#ERRNUM
	BSBW	ERROR
	.ENDM

 
	.MACRO	STATUS	ERRNUM,?A
	BLBS	R0,A
	ERROR	ERRNUM			;DECLARE THE ERROR
A:
	.ENDM

 
	.MACRO	DEFINE_ERROR	ERROR_NAME,MESSAGE
ERROR_NAME=ERRNUM
ERRNUM=ERRNUM+1
	.WORD	ERROR_NAME'_M
	.SAVE
	.PSECT	ERROR_TEXT,BYTE,NOWRT,RD,NOEXE
ERROR_NAME'_M:
	.ASCIC	&MESSAGE&
	.RESTORE
	.ENDM

 
	.MACRO	CASE,SRC,DISPLIST,TYPE=W,LIMIT=#0,NMODE=S^#,?BASE,?MAX
	CASE'TYPE	SRC,LIMIT,NMODE'<<MAX-BASE>/2>-1
BASE:
	.IRP	EP,<DISPLIST>
	.WORD	EP-BASE
	.ENDR
MAX:
	.ENDM


	; MY OWN FAO MACRO
	.MACRO DO_FAO	FMT_STRING,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12
	.NARG	ARG_COUNT
ARG_COUNT = ARG_COUNT - 1 + 3		; ACTUAL # OF ARGS TO SYS$FAO
	.IRP	PSUBI<A12,A11,A10,A9,A8,A7,A6,A5,A4,A3,A2,A1>
	.IIF	NB,PSUBI,	PUSHL	PSUBI
	.ENDR
	PUSHAQ	OUT_BUFF_DESC		; WHERE OUTPUT WILL LIVE
	PUSHAW	RAB$W_RSZ(R11)		; SIZE OF OUTPUT
	PUSHAQ	FMT_STRING		; ADDRESS OF CONTROL STRING
	CALLS	#ARG_COUNT,@#SYS$FAO	; DO THE FORMATTING.
	.ENDM


;
; EQUATED SYMBOLS:
;
 
TAB=9					;TAB
LF=10					;LINE FEED
FF=12					;FORM FEED
CR=13					;CARRIAGE RETURN
ESC=^X1B				;ESCAPE
 
OUT_BUFF_SIZE=132			;LENGTH OF GENERAL PURPOSE BUFFER
DISK_BUFF_SIZE=512			;LENGTH OF DISK BLOCK BUFFER
PCT_BUFF_SIZE=5				; LENGTH OF PERCENT BUFFER
 
;ARGUMENT LIST OFFSETS
IMAGE_NAME=4				;DESCRIPTOR OF IMAGE FILE NAME (INIT)
OUTPUT_NAME=IMAGE_NAME+4		;DESCRIPTOR OF OUTPUT FILE NAME (INIT)
USER_PC=4				;USER'S PC TO BE MATCHED (MATCH_PC)
HIT_COUNT=USER_PC+4			;HIT COUNT ON LINE (MATCH_PC)
CONTROL=4				;HIT COUNT IN P1 REGION (CLEAN_UP)
SYSTEM=CONTROL+4			;HIT COUNT IN SYSTEM (CLEAN_UP)

	$DEFINI DST
$DEF	DST$B_SIZE	.BLKB	1	;SIZE OF DST RECORD
$DEF	DST$B_TYPE	.BLKB	1	;TYPE OF DST RECORD
$DEF	DST$B_ACCESS	.BLKB	1	;ACESS FIELD FOR SOME RECORD TYPES
$DEF	DST$L_VALUE	.BLKL	1	;VALUE FIELD
$DEF	DST$T_NAME	.BLKB	1	;COUNTED ASCII NAME STRING
	$DEFEND	DST

;
; OWN STORAGE - READ/WRITE
;
	.PSECT	RW_DATA,QUAD,NOEXE,PIC,RD,WRT,NOSHR
	.ALIGN	QUAD			;START OF QUADWORD ALIGNED DATA
;
; FABS AND RABS
;
ERR_FAB:			;FAB FOR TERMINAL OUTPUT FOR ERRORS
				; ALSO USED IF OUTPUT DEV. IS SYS$OUTPUT
	$FAB	FAC=PUT,-
		FNM=<SYS$OUTPUT>,-
		ORG=SEQ,-
		MRS=132,-
		RAT=CR

ERR_RAB:				;RAB FOR TERMINAL OUTPUT
	$RAB	RAC=SEQ,-
		RBF=OUT_BUFF,-		;OUTPUT BUFFER (SIZE TO BE DEFINED)
		FAB=ERR_FAB

OUT_FAB:				;FAB FOR OUTPUT IF NOT SYS$OUTPUT
	$FAB	FAC=PUT,-
		DNM=<.HST>,-		; DEFAULT EXTENSION IS .HST
		ORG=SEQ,-
		MRS=132,-
		RAT=CR

OUT_RAB:				;RAB FOR OUTPUT
	$RAB	RAC=SEQ,-
		RBF=OUT_BUFF,-		;OUTPUT BUFFER (SIZE TO BE DEFINED)
		FAB=ERR_FAB		;DEFAULT FAB IS SYS$OUTPUT

IMAGE_FAB:				;FAB FOR READING IMAGE FILE
	$FAB	FAC=GET,-
		ORG=SEQ,-
		FOP=UFO,-		;USER FILE OPEN SO $CRMPSC CAN USE IT
		FNM=<A.EXE>,-		;*** DEFAULT ***
		DNM=<.EXE>		;SET DEFAULT EXTENSION AS .EXE

DISK_IOSB:				;I/O STATUS BLOCK FOR IMAGE HDR READ
	.BLKQ	1

	.ALIGN	LONG			;START OF LONGWORD ALIGNED DATA
;** THE NEXT TWO CELLS MUST BE CONTIGUOUS **
DST_START:				;STARTING VIRTUAL ADDRESS OF DST
	.BLKL	1
DST_END:				;ENDING VIRTUAL ADDRESS OF DST
	.BLKL	1

	.ALIGN	WORD			;START OF WORD ALIGNED DATA

	.ALIGN	BYTE			;START OF BYTE ALIGNED DATA
INIT_FLAG:				;FLAG TO REMEMBER IF SYS$OUTPUT OPENED
	.BYTE	0			;INITIALIZED TO ZERO
OUT_BUFF:				;GENERAL PURPOSE LINE BUFFER
	.BLKB	OUT_BUFF_SIZE
PCT_BUFF:				; WHERE PERCENT STRING GOES.
	.BLKB	PCT_BUFF_SIZE
DISK_BUFF:				;BUFFER FOR READING IMAGE HEADER
	.BLKB	DISK_BUFF_SIZE

;
; LOCAL STORAGE FOR DST SEARCHING ROUTINE.  STORED HERE TO MAKE INIT EASIER
;
	.ALIGN QUAD
DST_LOCAL_START:			;START OF DATA TO BE ZERO'D AT START
PERCENT_COUNT:				;PERCENT THIS ROUTINE IS OF TOTAL
	.BLKD	1

	.ALIGN	LONG
BEST_MODULE:				;DST ADDRESS OF BEST MODULE MATCH
	.BLKL	1
BEST_ROUTINE:				;DST ADDRESS OF BEST ROUTINE MATCH
	.BLKL	1
BEST_OFFSET:				;CLOSEST RELATIVE PC
	.BLKL	1
LAST_MODULE:				;MODULE USED LAST TIME AROUND
	.BLKL	1
LAST_ROUTINE:				;ROUTINE USED LAST TIME AROUND
	.BLKL	1
LAST_COUNT:				;HIT COUNT FOR LAST_ROUTINE
	.BLKL 1
CURRENT_MODULE:				;DST ADDRESS OF CURRENT MODULE
	.BLKL	1
CURRENT_ROUTINE:			;DST ADDRESS OF CURRENT ROUTINE
	.BLKL	1
CURRENT_OFFSET:				;STARTING ADDRESS OF CURRENT MODULE
	.BLKL	1
CURRENT_DST:				;CURRENT POSITON IN DST
	.BLKL	1
CURRENT_LINE:				;CURRENT GUESS AT LINE NUMBER
	.BLKL	1
CURRENT_PC:				;CURRENT GUESS AT PC
	.BLKL	1
CURRENT_INC:				;CURRENT LINE NUMBER INCREMENT
	.BLKL	1
NEXT_INC:				;NEXT LINE INCREMENT TO BE USED
	.BLKL	1
LOWHITS:				;LOWEST # OF HITS IN TOP25 NOW.
	.BLKL	1
LOWIDX:					;WORD INDEX OF TOP OF TOP25 ARRAY.
	.BLKL	1
TOP25:					;TOP 25 CPU HOGS
	.BLKL	125			;FIVE WORDS PER ENTRY
	.ALIGN	WORD
	.ALIGN	BYTE
DST_LOCAL_SIZE=.-DST_LOCAL_START	;LENGTH OF AREA TO BE CLEARED OUT
TEMP:
	.LONG	^X1E8E14

;
; OWN STORAGE - READ ONLY
;
	.PSECT	RO_DATA,QUAD,NOWRT,RD,NOEXE
	.ALIGN	QUAD			;START OF QUADWORD ALIGNED DATA
FAO_DESC:
	.LONG	FAO_LINE_SIZE
	.LONG	FAO_LINE
OUT_BUFF_DESC:				;DESCRIPTOR FOR OUT_BUFF
	.LONG	OUT_BUFF_SIZE
	.LONG	OUT_BUFF
PCT_DESC:				; DESCRIPTOR FOR PERCENT STRING
	.LONG	PCT_BUFF_SIZE
	.LONG	PCT_BUFF

	.ALIGN	LONG			;START OF LONGWORD ALIGNED DATA
CVT_PERCENT:				;ARGUMENTS FOR FOR$CNV_OUT_F ROUTINE.
	.LONG	4			; LENGTH OF THIS ARGUMENT LIST
	.LONG	PERCENT_COUNT		; WHERE VALUE LIVES
	.LONG	PCT_DESC		; WHERE OUTPUT GOES
	.LONG	2			; 2 DIGITS TO RIGHT OF DEC. POINT
	.LONG	2			; SCALE FACTOR IS 2
JPI_ARG:				;ARGUMENTS FOR $GETJPI SYSTEM SERVICE
	.WORD	4			;LENGTH OF THIS DESCRIPTOR
	.WORD	JPI$_FREP0VA		;CODE FOR FIRST FREE P0 ADDRESS
	.LONG	DST_START		;PUT THE RESULT IN THE DST START ADDR
	.LONG	0			;NOT NEEDED
	.LONG	0			;END OF JPI ARGUMENT LIST
	.ALIGN	WORD			;START OF WORD ALIGNED DATA
	.ALIGN	BYTE			;START OF BYTE ALIGNED DATA
BLANKS:	.ASCIC	/          /		;BLANKS FOR SOME CASES OF FAO1
CONTROL_NAME:				;MODULE NAME FOR P1 REGION
	.ASCIC	/Control Region/
SYSTEM_NAME:				;MODULE NAME FOR SYSTEM SPACE
	.ASCIC	/System Space/
LONG_HDR_1:				;HEADER FOR DETAILED OUTPUT
	.ASCII	/Module           Routine          Absolute  Relative  Line    Hit/
LONG_HDR_1_LEN=.-LONG_HDR_1
LONG_HDR_2:
	.ASCII	/ Name             Name               PC        PC     Num    Count/
LONG_HDR_2_LEN=.-LONG_HDR_2
HOG_HDR_1:				;HEADER FOR SUMMARY OUTPUT
	.ASCII	<TAB><TAB>/Top CPU users/<CR><LF><TAB><TAB>/--- --- -----/<CR><LF>
HOG_HDR_1_LEN=.-HOG_HDR_1
HOG_HDR_2:
	.ASCII	<CR><LF>/Module             Routine              Hits    Percent/
	.ASCII	<CR><LF>/------             -------              ----    -------/<CR><LF>
HOG_HDR_2_LEN=.-HOG_HDR_2

FAO_LINE:
	.ASCII	/** !AC ** at PC=!XL/
FAO_LINE_SIZE=.-FAO_LINE
FAO1:				; FAO CONTROL STRING FOR DETAIL OUTPUT
	TEXT	<!17AC!17AC!XL  !XL  !4ZW  -  !UL>
FAO2:				; FAO CONTROL STRING FOR MODULE SUMMARY
	TEXT	<***Totals for module !AC, routine !AC, are !UL hits, !AS% of total.!/>
FAO3:				; FAO STRING FOR P1/SYSTEM SUMMARY
	TEXT	<***Totals for !AC are !UL hits, !AS% of total.!/>
FAO4:				; FAO STRING FOR TOP25 OUTPUT
	TEXT	<!19AC!19AC!6UL    !AS%>
FAO5:				; FAO STRING FOR P1/SYSTEM TOP25 OUTPUT
	TEXT	<!38AC!6UL    !AS%>

;
; ERROR MESSAGES
;
	.ALIGN	WORD			;ERROR MESSAGE INFO IS WORD ALIGNED
ERRNUM=0				;START COUNTING ERRORS AT 0
ERROR_TABLE:				;START OF ERROR TABLE
	DEFINE_ERROR	BADERROR,<ERROR FROM RMS>
	DEFINE_ERROR	OPEERROR,<Error opening image file>
	DEFINE_ERROR	CRMPSCERROR,<Error creating process section>
	DEFINE_ERROR	JPIERROR,<Error during $GETJPI system service>
	DEFINE_ERROR	QIOERROR,<Error reading image header of image file>

;
; COMMON BLOCK FROM HIST.FOR
;
	.PSECT	PCHIST,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
TOTAL_HITS:			; FOR TOTAL NUMBER OF RECORDED HITS.
	.BLKD	1
SUMMARY_ONLY:			; -1 FOR SUMMARY ONLY, OTHERWISE 0
	.BLKL	1
DUMMIES:
	.BLKL	3
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE PERFORMS INITIALIZATION FUNCTIONS FOR THE PC HISTOGRAM
;	PACKAGE.  THE ROUTINE OPENS A SPECIFIED IMAGE FILE, READS THE IMAGE
;	HEADER TO LOCATE DEBUG INFORMATION, AND MAPS IN THE DEBUG SYMBOL
;	TABLE OF THE IMAGE AS A GLOBAL SECTION.
;
; CALLING SEQUENCE:
;	CALLG/S INIT_MATCH
;
; INPUT PARAMETERS:
;	@4(AP) -DESCRIPTOR OF IMAGE FILE NAME TO BE USED
;	@8(AP) -DESCRIPTOR OF OUTPUT FILE NAME TO BE USED (SYS$OUTPUT IF
;		LENGTH IS 0).
;
; IMPLICIT INPUTS:
;	NONE
;
; OUTPUT PARAMETERS:
;	R0 -	1 SUCCESS. IMAGE FILE COULD BE OPENED. READY TO GO
;	R0 - 	0 DEBUG INFORMATION NOT AVAILABLE, CANT DO SYMBOLIC WORK.
;	R0 - 	-1 IMAGE FILE COULD NOT BE OPENED. PACK IT IN.
;
; IMPLICIT OUTPUTS:
;	NONE
;
;--
	.PSECT	SYMBOL_CODE,QUAD,RD,NOWRT,EXE,SHR
	.ENABL	LSB
	.ENTRY	INIT_MATCH,^M<R2,R3,R4,R5,R9,R10,R11> ;ENTRY POINT DESCRIPTION
;
; OPEN PATH TO SYS$OUTPUT FOR ERROR MESSAGES
;
	MOVAL	ERR_RAB,R11		;POINT TO THE SYS$OUTPUT RAB
	BBSS	#0,INIT_FLAG,5$		;IF SET, ALREADY INITED.
	$OPEN	FAB=W^ERR_FAB		;OPEN SYS$OUTPUT
	STATUS	BADERROR		;CHECK STATUS
	$CONNECT (R11)			;CONNECT TO THE FAB
	STATUS	BADERROR
5$:
;
; OPEN PATH TO OUTPUT FILE
;
	MOVAL	OUT_RAB,R11		; TRY TO USE OUT_RAB
	TSTW	@OUTPUT_NAME(AP)	; DID HE WANT THE DEFAULT?
	BEQL	6$			; IF EQL, YES, GO CONNECT
	 MOVAB	OUT_FAB,R10		; GET ADDRESS OF OUT_FAB
	 MOVL	R10,RAB$L_FAB(R11)	; SAVE IN OUT_RAB
	 MOVL	OUTPUT_NAME(AP),R0	; GET DESCRIPTOR ADDRESS
	 MOVB	(R0),FAB$B_FNS(R10)	; STORE OUTPUT FILENAME SIZE
	 MOVL	4(R0),FAB$L_FNA(R10)	; AND ADDRESS OF NAME.
	 $CREATE (R10)		; CREATE THE FILE
	 STATUS BADERROR
6$:	$CONNECT (R11)			; CONNECT TO THE FAB
	STATUS	BADERROR

7$:
;
; AT THIS POINT, R11 -> OUTPUT RAB
;
; OPEN DESIRED IMAGE FILE FOR USE BY $CRMPSC
;
	MOVAB	IMAGE_FAB,R10		;POINT TO FAB FOR IMAGE FILE
	MOVL	IMAGE_NAME(AP),R0	;GET ADDRESS OF DESCRIPTOR OF NAME
	MOVB	(R0),FAB$B_FNS(R10)	;STORE SIZE OF FILE NAME
	MOVL	4(R0),FAB$L_FNA(R10)	;STORE ADDRESS OF NAME
	$OPEN	(R10)			;OPEN THE FAB FOR UFO GETS
	BLBS	R0,71$			;IF LBS ALL IS WELL
	MCOML	#0,R0			;SET A -1 CODE FOR FORTRAN
	RET				;AND RETURN IN DISGRACE
71$:
	$GETJPI_S ITMLST=JPI_ARG	;FIND OUT THE NEXT AVAILABLE P0 ADDR
	STATUS	JPIERROR		;CHECK FOR SUCCESS
;
; READ IN ONE BLOCK OF THE IMAGE HEADER
;
	MOVAB	DISK_BUFF,R9		;POINT TO DISK BUFFER
					; (SOON TO BE IMAGE HDR)
	$QIOW_S	EFN=#1,-		;READ IN ONE BLOCK OF THE IMAGE FILE
		CHAN=FAB$L_STV(R10),-	;IN ORDER TO FIND THE IMAGE HEADER
		FUNC=#IO$_READVBLK,-
		IOSB=DISK_IOSB,-	;USE AN IOSB TO MAKE SURE IT WORKED
		P1=(R9),-		;PUT THE BLOCK IN THIS BUFFER
		P2=#DISK_BUFF_SIZE,-	;WE KNOW THIS IS REALLY JUST 512
		P3=#1			;READ VBN #1
	STATUS	QIOERROR		;CHECK FOR SUCCESS
	MOVQ	DISK_IOSB,R0		;PICK UP THE IOSB FROM THE TRANSFER
	STATUS	QIOERROR		;CHECK FOR SUCCESS ON THE IOSB
;
; EXAMINE THE IMAGE HEADER TO FIND OUT WHERE THE DEBUGGING INFORMATION
; IN THE IMAGE IS LOCATED
;
	CLRL	R0			;ASSUME FAILURE IS ABOUT TO HAPPEN
	MOVZWL	IHD$W_SYMDBGOFF(R9),R8	;EXTRACT SYMBOL DATA OFFSET
	BEQL	10$			;IF EQL NO SYMBOL DATA, CANT DO IT
	ADDL	R9,R8			;ADD IN HEADER BASE ADDRESS
	MOVZWL	IHS$W_DSTBLKS(R8),R7	;EXTRACT NUMBER OF DST BLOCKS
	BEQL	10$			;IF EQL NO SYMBOL DATA
	CMPL	#2,IHS$L_DSTVBN(R8)	;IS THERE MEANINGFUL SYMBOL DATA?
	BGEQ	10$			;IF GEQ NO SYMBOL DATA PRESENT
	MOVL	#^X20000000,DST_END	;SET ENDING ADDRESS TO MAXIMUM ADDRESS
	$CRMPSC_S INADR=DST_START,-	;MAP IN THE DST AS A PROCESS SECTION
		RETADR=DST_START,-	;RETURN ACTUAL BOUNDARIES HERE
		FLAGS=#0,-		;NO FLAGS, PRIVATE READ-ONLY SECTION
		RELPAG=#0,-		;START MAPPING AT FIRST VA
		CHAN=FAB$L_STV(R10),-	;FILE OPEN ON THIS CHANNEL
		PAGCNT=R7,-		;MAP THIS MANY PAGES (IHS$W_DSTBLKS)
		VBN=IHS$L_DSTVBN(R8)	;START WITH THIS VBN
	STATUS	CRMPSCERROR		;CHECK FOR SUCCESS
;
; INITIALIZE ALL LOCAL STORAGE FOR DST SEARCHING
;
	MOVC5	#0,(SP),#0,#DST_LOCAL_SIZE,DST_LOCAL_START
					;CLEAR OUT LOCAL STORAGE
	MOVL	DST_START,CURRENT_DST	;SET STARTING POSITION IN DST
	MOVL	#1,R0			;SET SUCCESS CODE FOR CALLER
10$:
	PUSHL	R0			;SEE WHAT THE RETURN CODE IS.
	BLEQ	11$			;IF NOT 1, DON'T PRINT HEADER.
	BLBS	SUMMARY_ONLY,11$	;ALSO DON'T PRINT IF SUMMARY ONLY.
	MOVL	#LONG_HDR_1_LEN,RAB$W_RSZ(R11)
	MOVC3	#LONG_HDR_1_LEN,LONG_HDR_1,OUT_BUFF
	$PUT	(R11)
	MOVL	#LONG_HDR_2_LEN,RAB$W_RSZ(R11)
	MOVC3	#LONG_HDR_2_LEN,LONG_HDR_2,OUT_BUFF
	$PUT	(R11)
	MOVL	#LONG_HDR_2_LEN,RAB$W_RSZ(R11)
	MOVC5	#0,.,S^#^A/-/,#LONG_HDR_2_LEN,OUT_BUFF ; UNDERLINE
	$PUT	(R11)
11$:	POPL	R0			;RESTORE RETURN CODE
	RET				;RETURN TO CALLER
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS FORTRAN SUBROUTINE ATTEMPTS TO CORRELATE A USER PROGRAM COUNTER
;	WITH A FORTRAN LINE NUMBER IN SOME IMAGE FILE.  THE DEBUG SYMBOL TABLE
;	IS SEARCHED TO TRY TO FIND THE BEST MODULE, ROUTINE, PSECT, AND LINE
;	NUMBER MATCH FOR THE PC.
;
; CALLING SEQUENCE:
;	CALLG/S MATCH_PC
;
; INPUT PARAMETERS:
;	@4(AP) - PC TO BE MATCHED
;
; IMPLICIT INPUTS:
;	INIT_MATCH MUST HAVE BEEN CALLED (WITH A SUCCESS RETURN) PRIOR TO
;	CALLING THIS ROUTINE.  IF THIS ROUTINE RETURNS FAILURE, IT MUST NOT
;	BE CALLED AGAIN.
;
; OUTPUT PARAMETERS:
;	R0 - LBC ERROR, DO NOT CALL THIS ROUTINE AGAIN
;	R0 - LBS SUCCESS, THE MATCHED VALUES ARE PRINTED
;
; IMPLICIT OUTPUTS:
;	NONE
;
;--
	.ENABL	LSB
	.ENTRY	MATCH_PC,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	MOVAL	OUT_RAB,R11		;POINT TO SYS$OUTPUT RAB
	MOVL	CURRENT_DST,R10		;SET UP PTR TO CURRENT DST POSITION
	CLRL	CURRENT_LINE		;FORCE GENERATION OF NEW NUM THIS TIME
	CLRL	BEST_MODULE		;INIT MODULE FOLLOWER
	BRB	20$			;JUMP INTO THE THICK OF THE DST LOOP
10$:
	BSBW	GET_NEXT_DST		;GET A DST ENTRY
	BLBS	R0,20$			;IF LBS GOT ONE
	BRW	90$
20$:
	MOVZBL	DST$B_TYPE(R10),R0	;EXTRACT TYPE FIELD OF DST RECORD
	CASE	TYPE=W,LIMIT=#DSC$K_DTYPE_PCT,R0,<- ;CASE BY DST TYPE
		PCT,-			;PSECT INFORMATION
		DPC,-			;PC CORRELATION TABLE
		LBL,-			;LABEL RECORD
		SLB,-			;SYMBOLIC LABEL
		MOD,-			;START OF MODULE
		EOM,-			;END OF MODULE
		RTN,-			;START OF ROUTINE
		EOR>			;END OF ROUTINE

DPC:					;PC CORRELATION TABLE
LBL:					;LABEL
SLB:					;SYMBOLIC LABEL
	BRB	10$			;IGNORE ALL THESE RECORDS THIS PASS

MOD:					;START OF MODULE
	MOVL	R10,CURRENT_MODULE	;REMEMBER POSITION OF THIS DST
	BRB	10$			;CONTINUE ON TO NEXT

EOM:					;END OF MODULE
	CLRL	CURRENT_MODULE		;NOTE THAT NO CURRENT MODULE EXISTS
	TSTL	BEST_MODULE		;IS THIS THE BEST MODULE POSSIBLE?
	BEQL	10$			;IF EQL NO, CONTINUE SEARCH
	BRW	GOT_LINE		;SOMEBODY THINKS THIS IS THE BEST SHOT

RTN:					;START OF ROUTINE
	SUBL3	DST$L_VALUE(R10),@USER_PC(AP),CURRENT_OFFSET
					;COMPUTE DIFFERENCE BETWEEN START OF
					;ROUTINE AND USER'S PC
	BLSS	10$			;IF LSS, NOT A GOOD ROUTINE.
	MOVL	R10,CURRENT_ROUTINE	;THIS MIGHT BE THE RIGHT ROUTINE.
	BRB	10$			;CONTINUE WITH NEXT DST RECORD.

EOR:					;END OF ROUTINE
	MOVL	CURRENT_ROUTINE,R0	;RESTORE DST ADDRESS OF ROUTINE START
	BEQL	10$			;IF EQL NOT OF INTEREST, SKIP IT
	ADDL3	DST$L_VALUE(R0),DST$L_VALUE(R10),R1
					;COMPUTE END OF MODULE ADDRESS.
	CMPL	@USER_PC(AP),R1		;IS THIS END PAST THE DESIRED PC?
	BLEQ	PASS2			;IF LEQ THIS IS THE BEST MODULE
	CLRL	CURRENT_ROUTINE		;NOTE END OF ROUTINE IN SIGHT
30$:
	BRW	10$			;CONTINUE DST SEARCH

PCT:					;PSECT SPECIFICATION
	CMPL	DST$L_VALUE(R10),@USER_PC(AP) ;DOES PSECT START BEFORE PC?
	BGTRU	30$			;IF GTRU NO, SKIP IT
	MOVZBL	DST$T_NAME(R10),R0	;FETCH LENGTH OF PSECT NAME
	ADDL3	R0,R10,R1		;BEGIN TO FIGURE POSITION OF PSECT
	ADDL	#DST$T_NAME+1,R1	;LENGTH, AND ADD IN NAME OFFSET.
	ADDL3	DST$L_VALUE(R10),(R1),R1 ;COMPUTE END ADDRESS OF PSECT
	CMPL	R1,@USER_PC(AP)		;DOES THIS PSECT END AFTER USER'S PC?
	BLSSU	30$			;IF LSSU NO, NOT A RELEVANT PSECT
	MOVL	CURRENT_MODULE,BEST_MODULE ;REMEMBER MODULE AS A POSSIBLE BEST
	MOVL	CURRENT_ROUTINE,BEST_ROUTINE ;REMEMBER ROUTINE NAME AS WELL
	SUBL3	DST$L_VALUE(R10),@USER_PC(AP),BEST_OFFSET ;COMPUTE OFFSET TOO
	BRB	30$			;CONTINUE SEARCH

90$:					;COME HERE WHEN NO GOOD ROUTINE FOUND
	MOVL	DST_START,CURRENT_DST	;RE-START NEXT SEARCH AT THE BEGINNING
	BRW	GOT_LINE		;MATCH THE LAST ROUTINE FOUND
;*** MORE HERE*** HANDLE FAILURE

	.ENABL	LSB
PASS2:
	MOVL	CURRENT_MODULE,BEST_MODULE ;STORE BEST GUESS AT MODULE
	MOVL	CURRENT_ROUTINE,BEST_ROUTINE ;STORE BEST GUESS AT ROUTINE
	MOVL	CURRENT_OFFSET,BEST_OFFSET ;STORE BEST GUESS AT RELATIVE PC
	MOVL	R0,CURRENT_DST		;STORE RESTART POSITION FOR NEXT PASS
;
; NOW RESCAN THIS ROUTINE FOR PC CORRELATION RECORD
; AND TRY TO CORRELATE LINE NUMBER WITH USER_PC
;
	MOVL	BEST_ROUTINE,R10	;RESTORE DST ADDRESS OF ROUTINE START
	MOVL	DST$L_VALUE(R10),CURRENT_PC ;TAKE MODULE STATING ADDRESS AS PC
	MOVL	#1,CURRENT_INC		;SET INITIAL VALUE FOR LINE INCREMENT
	CLRL	NEXT_INC		;SET INITIAL VALUE FOR STORED INC
10$:
	BSBW	GET_NEXT_DST		;GET ANOTHER DST RECORD
	BLBS	R0,15$			;IF LBS SUCCESS, CONTINUE
	BRW	90$			;HIT END OF DST WITH NO MATCH
15$:
	CMPB	#DSC$K_DTYPE_EOR,DST$B_TYPE(R10) ;IS THIS AN END OF ROUTINE?
	BNEQ	17$
	BRW	GOT_LINE		;TAKE CLOSEST MATCH TO DATE
17$:
	CMPB	#DSC$K_DTYPE_DPC,DST$B_TYPE(R10) ;IS THIS A PC CORRELATION?
	BNEQ	10$			;IF NEQ NO, SKIP IT AND CONTINUE
;
; FOUND A PC CORRELATION RECORD, PROCESS IT
;
	ADDL3	#2,R10,R9		;BYPASS UNINTERESTING PART OF RECORD
	MOVZBL	DST$B_SIZE(R10),R0	;EXTRACT SIZE OF THIS DST RECORD
	ADDL3	R0,R10,R8		;COMPUTE ENDING ADDRESS OF RECORD
					;AT THIS POINT:
					;R10 - CURRENT DST ENTRY ADDRESS
					;R9  - CURRENT POSITION IN DST ENTRY
					;R8  - ENDING ADDRESS OF DST ENTRY
20$:
	CMPL	R8,R9			;AT OR PAST END OF RECORD YET?
	BLSS	10$			;IF LSS YES, GET NEXT RECORD
	CVTBL	(R9)+,R0		;SIGN EXTEND CODE FROM PC RECORD
	CASE	LIMIT=#1,R0,<-		;CASE BY PC RECORD CODE
		WORD_DELTA_PC,-		;NEXT 2 BYTES A DELTA PC
		BYTE_LINE_INCR,-	;NEXT BYTE AN UNSIGNED LINE # INCR
		WORD_LINE_INCR,-	;NEXT WORD AN UNSIGNED LINE # INCR
		BYTE_INCR,-		;NEXT BYTE AN UNSIGNED INCREMENT
		WORD_INCR,-		;NEXT WORD AN UNSIGNED INCREMENT
		INCR_1>			;CHANGE INCREMENT TO 1

DELTA_PC:				;DELTA PC RECORD, BYTE IS NEGATIVE
					; PC CHANGE
	MNEGL	R0,R0			;MAKE THE OFFSET INTO A POSITIVE ONE
	BLSS	90$			;IF LSS, A BAD RECORD, END SEARCH
	BRB	CHANGE_PC		;PROCESS A CHANGE IN PC

WORD_DELTA_PC:				;NEXT TWO BYTES A DELTA PC
	MOVZWL	(R9)+,R0		;EXTRACT WORD DELTA
	BRB	CHANGE_PC		;SKIP TWO BYTES AND MOVE ON

BYTE_LINE_INCR:				;BYTE OF LINE NUMBER CHANGE
	MOVZBL	(R9)+,R0		;GET LINE NUMBER CHANGE
	BRB	40$			;MOVE ON

WORD_LINE_INCR:				;WORD OF LINE NUMBER CHANGE
	MOVZWL	(R9)+,R0		;GET LINE NUMBER CHANGE
40$:
	MOVL	R0,NEXT_INC		;SET UP NEXT LINE INCRMENT
	BRB	20$			;CONTINUE CHECKING

BYTE_INCR:				;NEXT BYTE IS NEW LINE INCREMENT
	MOVZBL	(R9)+,R0		;GET NEW INCREMENT
	BRB	50$			;FINISH IN COMMON

WORD_INCR:				;NEXT WORD IS NEW LINE INCREMENT
	MOVZWL	(R9)+,R0		;GET NEW INCREMENT
	BRB	50$			;FINISH IN COMMON

INCR_1:					;SET INCREMENT TO 1
	MOVL	#1,R0			;GET NEW INCREMENT
50$:
	MOVL	R0,CURRENT_INC		;STORE NEW LINE NUMBER INCREMENT
	BRB	20$			;CONTINUE LOOP

CHANGE_PC:			;PC IS ABOUT TO CHANGE, TAKE A GOOD LOOK
	ADDL3	R0,CURRENT_PC,R1	;COMPUTE NEW PC
	CMPL	R1,@USER_PC(AP)		;IS THIS BEYOND THE DESIRED ADDR YET?
	BGTR	GOT_LINE		;IF GTR, FINALLY FOUND THE RIGHT LINE
	MOVL	R1,CURRENT_PC		;SET NEW CURRENT PC VALUE
	ADDL	CURRENT_INC,CURRENT_LINE ;BUMP LINE NUMBER
	ADDL	NEXT_INC,CURRENT_LINE 	;BUMP UP THE LINE NUMBER
	CLRL	NEXT_INC		;RE-INIT SAVED INCREMENT
	BRW	20$			;CONTINUE WITH THE SEARCH

90$:					;ERROR IN DST OR NO MATCH
GOT_LINE:				;FOUND GOOD LINE NUMBER MATCH
	MOVAB	BLANKS,R0		;ASSUME NO MODULE NAME PRESENT
	MOVL	BEST_MODULE,R10		;GET DST ADDRESS OF THIS MODULE
	BEQL	33$			;IF EQL NO MODULE NAME PRESENT
	MOVAB	DST$T_NAME(R10),R0	;GET ADDRESS OF MOUDULE NAME STRING
33$:
	MOVAB	BLANKS,R1		;SET ADDR OF ALL BLANKS JUST IN CASE
	MOVL	BEST_ROUTINE,R9		;GET DST ADDRESS OF THIS ROUTINE
	BEQL	35$			;IF EQL NO ROUTINE NAME
	MOVAB	DST$T_NAME(R9),R1	;SET ADDRESS OF ROUTINE NAME STRING
35$:
	CMPL	R0,LAST_MODULE		;MODULE NAME THE SAME?
	BNEQ	37$			;IF NOT, GO OUTPUT TOTALS
	CMPL	R1,LAST_ROUTINE		;ROUTINE NAME THE SAME?
	BEQL	39$			;IF SO, JUST DO OUTPUT
37$:	CMPL	#0,LAST_COUNT		; FIRST PC EXAMINED IN RUN?
	BEQL	38$			; IF EQL, YES, DON'T PRINT ANYTHING
	BSBW	PRINT_TOTAL		;GO PRINT TOTALS
38$:	MOVL	R0,LAST_MODULE		; SET UP LAST_MODULE
	MOVL	R1,LAST_ROUTINE		; AND LAST_ROUTINE
	CLRL	LAST_COUNT		; ZERO COUNT.

39$:
	ADDL2	@HIT_COUNT(AP), LAST_COUNT ;REMEMBER NUMBER OF HITS
	BLBS	SUMMARY_ONLY, 391$	; IF SUMMARY ONLY, JUST RETURN
	DO_FAO	FAO1,R0,R1,@USER_PC(AP),BEST_OFFSET,-
			CURRENT_LINE,@HIT_COUNT(AP)
	$PUT	(R11)			;OUTPUT THE LINE ON SYS$OUTPUT
391$:	MOVL	#1,R0			;SET SUCCESS
	RET				;RETURN TO CALLER
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE PRINTS TOTALS AT THE END OF A MODULE
;
; CALLING SEQUENCE:
;	BSB/JSB PRINT_TOTAL
;
; INPUT PARAMETERS:
;	NONE
;
; IMPLICIT INPUTS:
;	LAST_MODULE - ADDRESS OF MODULE NAME STRING
;	LAST_ROUTINE - ADDRESS OF ROUTINE NAME STRING
;	LAST_COUNT - HIT COUNT FOR ROUTINE
;	TOTAL_HITS - TOTAL RECORDED HITS FOR RUN
;
; OUTPUT PARAMETERS:
;	NONE
;
; IMPLICIT OUTPUTS:
;	TERMINAL OUTPUT
;
;--
	.ENABL LSB
PRINT_TOTAL:
	PUSHR	#^M<R0,R1>
	CVTLD	LAST_COUNT, PERCENT_COUNT ; MAKE HIT COUNT FLOATING
	DIVD2	TOTAL_HITS, PERCENT_COUNT ; GET FRACTION OF TOTAL
	BLBS	SUMMARY_ONLY, 10$	; IF SUMMARY, JUST CALL CHECK_TOP25

	CALLG	CVT_PERCENT, FOR$CNV_OUT_F	; CONVERT TO PERCENT STRING

	DO_FAO	FAO2, LAST_MODULE, LAST_ROUTINE, LAST_COUNT, #PCT_DESC
	$PUT	(R11)			; WRITE IT.

10$:	BSBW	CHECK_TOP25
	POPR	#^M<R0,R1>
	RSB				; AND RETURN
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE LOCATES THE NEXT DST ENTRY.
;
; CALLING SEQUENCE:
;	BSB/JSB GET_NEXT_DST
;
; INPUT PARAMETERS:
;	R10 - CURRENT DST ADDRESS
;
; IMPLICIT INPUTS:
;	NONE
;
; OUTPUT PARAMETERS:
;	R0 - LBC END OF DST REACHED
;	R0 - LBS NEXT DST RECORD AVAILABLE
;		R10 - ADDRESS OF NEXT DST RECORD
;
; IMPLICIT OUTPUTS:
;	NONE
;
;--
	.ENABL	LSB
GET_NEXT_DST:
	MOVZBL	DST$B_SIZE(R10),R0	;EXTRACT SIZE FIELD FROM PREV DST REC.
	MOVAB	1(R0)[R10],R10		;COMPUTE ADDRESS OF NEXT DST ENTRY
	CMPL	DST_END,R10		;PAST END OF DST?
	BLEQ	10$			;IF LEQ YES, DONE
	TSTB	(R10)			;PAST END OF MEANINGFUL DATA?
	BEQL	10$			;IF EQL YES, DONE
	MOVL	#1,R0			;SET SUCCESS CODE FOR CALLER
	RSB				;RETURN TO CALLER
10$:
	CLRL	R0			;SET FAILURE CODE FOR CALLER
	RSB				;RETURN TO CALLER
	.PAGE 
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE MANIPULATES THE LIST OF THE TOP 25 CPU HOGS
;
; CALLING SEQUENCE:
;	BSB/JSB CHECK_TOP25
;
; INPUT PARAMETERS:
;	NONE
;
; IMPLICIT INPUTS:
;	LAST_MODULE - ADDRESS OF MODULE NAME STRING
;	LAST_ROUTINE - ADDRESS OF ROUTINE NAME STRING
;	LAST_COUNT - HIT COUNT FOR ROUTINE
;	PERCENT_COUNT - PERCENT HIT COUNT FOR ROUTINE
;	TOP25 - ARRAY OF TOP 25 USERS
;	LOWHITS - LOWEST HIT COUNT CURRENTLY IN ARRAY
;	LOWIDX - INDEX OF LOWEST ENTRY IN ARRAY
;
; OUTPUT PARAMETERS:
;	NONE
;
; IMPLICIT OUTPUTS:
;	POTENTIALLY MODIFIES TOP25, LOWHITS, AND LOWIDX
;
;--
	.ENABL LSB
CHECK_TOP25:
	MOVAL	TOP25,R0
	TSTL	LOWIDX			; TOP25 EMPTY?
	 BEQL	10$			; IF EQL, YES.  BRANCH.
	CMPL	LAST_COUNT,LOWHITS	; HIT COUNT LARGER THAN
					;  SMALLEST NOW THERE?
	 BGTR	5$			; IF GTR, YES, BRANCH.

; HERE TO INSERT AN ENTRY AT THE END
	CMPL	#<5*25>,LOWIDX		; ARRAY FULL?
	 BEQL	15$			; IF EQL, YES, JUST RETURN
	ROTL	#2,LOWIDX,R1		; OTHERWISE, FIGURE ADDRESS OF NEW
	ADDL2	R1,R0			; TOP25 ENTRY.
	BRB	10$			; GO TO COMMON CODE TO FINISH

; HERE TO INSERT AN ENTRY IN THE MIDDLE
5$:	CMPL	8(R0),LAST_COUNT	; COMPARE COUNT WITH THIS ENTRY.
	BGEQ	51$			; IF GEQ, THIS IS NOT THE ONE WE WANT.
	 SUBL3	R0,#TOP25+<4*5*24>,R1	; HOW MANY CHARACTERS TO MOVE
	 PUSHL	R0
	 MOVC3	R1,(R0),<4*5>(R0)	; MOVE THE CHARACTERS
	 POPL	R0
	 CMPL	#<5*25>,LOWIDX		; IS TOP25 ALREADY FULL?
	  BEQL	101$			; IF EQL, YES, DO NOT INCREMENT LOWIDX
	 BRB	10$			; OTHERWISE, DO INCREMENT LOWIDX.
51$:	ADDL2	#<4*5>,R0		; INCREMENT R0 TO POINT TO NEXT ENTRY,
	BRB	5$			; AND TRY AGAIN.

; COMMON CODE TO SET TOP25 ENTRY.  R0 POINTS TO ENTRY IN TOP25 TO BE SET.
10$:	ADDL2	#5,LOWIDX		; INCREMENT LOWIDX
101$:	MOVL	LAST_MODULE,(R0)+	; REMEMBER MODULE NAME
	MOVL	LAST_ROUTINE,(R0)+	; REMEMBER ROUTINE NAME
	MOVL	LAST_COUNT,(R0)+	; REMEMBER HIT COUNT
	MOVD	PERCENT_COUNT,(R0)+	; REMEMBER PERCENT OF HITS
	SUBL3	#3,LOWIDX,R0		; SET UP LOWHITS AGAIN
	MOVL	TOP25[R0],LOWHITS
15$:	RSB				; AND RETURN
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE DOES CLEAN-UP, INCLUDING ANALYSIS OF THE CONTROL
;	REGION AND SYSTEM SPACE NUMBERS.
;
; CALLING SEQUENCE:
;	CALLG/S CLEAN_UP
;
; INPUT PARAMETERS:
;	4(AP) - ADDRESS OF CONTROL REGION HITS
;	8(AP) - ADDRESS OF SYSTEM SPACE HITS
;
; IMPLICIT INPUTS:
;	TOP25
;
; OUTPUT PARAMETERS:
;	NONE
;
; IMPLICIT OUTPUTS:
;	PRINTS ON TERMINAL
;
;--
	.ENABL	LSB
	.ENTRY CLEAN_UP,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	MOVAL	OUT_RAB,R11		; SET UP RAB POINTER
	BSBW	PRINT_TOTAL		; OUTPUT DATA FOR FINAL ROUTINE.
	MOVL	@CONTROL(AP),LAST_COUNT	; GET CONTROL REGION HITS
	BEQL	5$			; IF NONE, IGNORE
	CVTLD	LAST_COUNT,PERCENT_COUNT ; CONVERT TO FLOATING
	DIVD2	TOTAL_HITS,PERCENT_COUNT ; AND COMPUTE FRACTION  OF TOTAL
	CALLG	CVT_PERCENT, FOR$CNV_OUT_F  ; CONVERT TO PERCENT STRING,

	BLBS	SUMMARY_ONLY, 4$
	DO_FAO	FAO3, #CONTROL_NAME, LAST_COUNT, #PCT_DESC
	$PUT	(R11)			; WRITE IT
4$:	CLRL	LAST_MODULE		; FLAG FOR LATER IN TOP25
	BSBW	CHECK_TOP25

5$:	MOVL	@SYSTEM(AP),LAST_COUNT	; GET SYSTEM SPACE HITS
	BEQL	10$			; IF NONE, IGNORE
	CVTLD	LAST_COUNT,PERCENT_COUNT ; CONVERT TO FLOATING
	DIVD2	TOTAL_HITS,PERCENT_COUNT ; AND COMPUTE FRACTION  OF TOTAL
	CALLG	CVT_PERCENT, FOR$CNV_OUT_F  ; CONVERT TO PERCENT STRING,

	BLBS	SUMMARY_ONLY,9$
	DO_FAO	FAO3, #SYSTEM_NAME, LAST_COUNT, #PCT_DESC
	$PUT	(R11)			; WRITE IT.
9$:	MNEGL	#1,LAST_MODULE		; FLAG FOR LATER IN TOP25
	BSBW	CHECK_TOP25

; NOW PROCESS THE TOP25 ARRAY.
10$:	BLBS	SUMMARY_ONLY,101$
	MOVL	#1,RAB$W_RSZ(R11)	; PRINT <FF>
	MOVB	#FF,OUT_BUFF
	$PUT	(R11)
101$:	MOVL	#HOG_HDR_1_LEN,RAB$W_RSZ(R11) ; FIRST PRINT HEADER
	MOVC3	#HOG_HDR_1_LEN,HOG_HDR_1,OUT_BUFF
	$PUT	(R11)
	MOVL	#HOG_HDR_2_LEN,RAB$W_RSZ(R11)
	MOVC3	#HOG_HDR_2_LEN,HOG_HDR_2,OUT_BUFF
	$PUT	(R11)

	MOVAL	TOP25,R2		; POINT R2 TO START OF TOP25.
	CLRL	R3			; USE R3 AS INDEX.
	SUBL2	#5,LOWIDX		; TO GET LOOP COUNT CORRECT
11$:	MOVL	12(R2)[R3],PERCENT_COUNT
	MOVL	16(R2)[R3],PERCENT_COUNT+4
	CALLG	CVT_PERCENT, FOR$CNV_OUT_F
	TSTL	(R2)[R3]
	BEQL	12$			; HANDLE CONTROL REGION
	BLSS	13$			; HANDLE SYSTEM SPACE

; NORMAL ROUTINE
	DO_FAO	FAO4, (R2)[R3], 4(R2)[R3], 8(R2)[R3], #PCT_DESC
	BRB	15$

; HANDLE P1 AND SYSTEM REGIONS
12$:	MOVAL	CONTROL_NAME,R4
	BRB	14$
13$:	MOVAL	SYSTEM_NAME,R4
14$:	DO_FAO	FAO5, R4, 8(R2)[R3], #PCT_DESC

; WRITE OUT WHATEVER WE JUST PRODUCED.
15$:	$PUT	(R11)
	ACBW	LOWIDX,#5,R3,11$		; LOOP BACK FOR NEXT ENTRY
	RET					; NO MORE, RETURN
	.PAGE
;++
;
; FUNCTIONAL DESCRIPTION:
;	THIS ROUTINE PROCESSES ERRORS DETECTED BY THE MAIN ROUTINE
;
; CALLING SEQUENCE:
;	PUSHL	ERROR-NUMBER
;	BSBW	ERROR
;
; INPUT PARAMETERS:
;	(SP) - ADDRESS AT WHICH ERROR TOOK PLACE
;	4(SP)- ERROR CODE
;
; IMPLICIT INPUTS:
;	ERROR_TABLE IS A LIST OF ERRORS WHICH THIS ROUTINE CAN PROCESS
;
; OUTPUT PARAMETERS:
;	NONE- THIS ROUTINE EXITS AFTER PRINTING AN ERROR MESSAGE
;
; IMPLICIT OUTPUTS:
;	NONE
;
;--
	.ENABL	LSB
ERROR::
	MOVAL	OUT_RAB,R11		;POINT TO SYS$OUTPUT RAB
	SUBL3	#6,(SP)+,R9		;FETCH ERRANT PC
	MOVL	(SP)+,R10		;AND ERROR NUMBER
	BEQL	10$			;IF EQL, BAD ERROR, NO MESSAGE
	PUSHL	R0			;SAVE THE FAILING STATUS
					;R9 = ERROR PC
					;R10= ERROR MESSAGE NUMBER
	MOVZWL	ERROR_TABLE[R10],R10	;GET THE ADDRESS OF THE MESSAGE
	DO_FAO	FAO_DESC, R10, R9
	$PUT	(R11)			;PUT THE MESSAGE
	POPL	R0			;RESTORE R0
10$:
	$EXIT_S R0			;AND CALL IT A DAY
	.END	
