!*_ DATED 11 NOV 76   1
! ALTERATIONS BY K.YARWOOD ...
!        PRINT FL AND NEXT SYMBOL LINES COMMENTED OUT
!        PRINTTEXT'S TURNED TO PRINTSTRING'S
!        ADDITION FOR LONGINTEGER IN RT PRINT VAR
!         HEX EQUIVALENTS FOR INTS,LONGINTS ETC PRINTED
!        INF PRINTED IN HEX IN RT ERRMESS

%EXTERNALSTRINGFNSPEC STRHEX(%INTEGER I)
%EXTERNALSTRING(8)%FNSPEC STRINT(%INTEGER I)
%CONSTINTEGER STACKBASE=X'80100000';  ! START OF RESIDENT STACK
! %SYSTEMROUTINESPEC SIGNAL(%INTEGER I, J, K, %INTEGERNAME F)
%ROUTINESPEC PRINTMESS(%INTEGER N)
! %SYSTEMROUTINESPEC TIDY EXIT
!*
%ROUTINESPEC INDIAG(%INTEGER OLDLNB, L, PC, %INTEGERNAME NEWLNB)
! %ROUTINESPEC FDIAG(%INTEGER OLDLNB,PC,%INTEGERNAME NEWLNB)
%ROUTINESPEC ERMESS(%INTEGER N, INF)
! %ROUTINESPEC ICL9CELABELS

%ROUTINE TRANS(%INTEGERNAME FAULT, EVENT, SUBEVENT)
!***********************************************************************
!*_______TRANSLATE FAULT TO EVENT & VICE VERSA                         *
!***********************************************************************
%CONSTBYTEINTEGERARRAY ETOF(0:54)=0,14,22,24,26,28,35,38,40,42,44,47,
                                  0(3),3,1,5,54,56,53,19,0,23,0,28,0,26,
                                  0,18,50,51,16,15,20,0,7,6,0,32,0,11,0,
                                  25,0,54,0,72,73,71,74,75,70,0,30
%CONSTBYTEINTEGERARRAY FTOE(1:75)=X'12',0,X'11',0,X'13',X'62',X'61',0,
                                  0(2),X'81',0(3),X'55',X'54',
                                  0,X'51',X'17',X'56',0(4),
                                  X'91',X'41',0,X'31',0,X'B1',0,X'71',
                                  0(17),X'52',X'53',X'53',X'16',
                                  X'14'(4),0(8),X'14'(2),0(2),
                                  X'A6',X'A3',X'A1',X'A2',X'A4',X'A5'
%INTEGER K

      %IF FAULT=0 %THEN %START;         ! EVENT-SUBEVENT GIVEN
         K=ETOF(EVENT)
         %IF K#0 %THEN FAULT=ETOF(K+SUBEVENT)
      %FINISH %ELSE %START
         %IF 1<=FAULT<=75 %START
            K=FTOE(FAULT)
            EVENT=K>>4;  SUBEVENT=K&15
         %FINISH
      %FINISH
%END;                                   ! TRANS
%ROUTINE DUMP(%INTEGER START, FINISH)
%INTEGER I, J
      I=START&(-4)
      %WHILE I<=FINISH %CYCLE
         PRINTSTRING(STRHEX(I))
         %CYCLE J=0,4,12
            SPACES(2)
            PRINTSTRING(STRHEX(INTEGER(I+J)))
         %REPEAT
         NEWLINE
         I=I+16
      %REPEAT
%END;                                   ! DUMP
%ROUTINE ASSDUMP(%INTEGER PCOUNT, OLDLNB)
%INTEGER I
      PRINTSTRING("
PC  =")
      PRINTSTRING(STRHEX(PCOUNT))
      PRINTSTRING("
LNB =")
      PRINTSTRING(STRHEX(OLDLNB))
      PRINTSTRING("
 GLA
")
      I=INTEGER(OLDLNB+16)
      DUMP(I,I+128)
      PRINTSTRING("
STACK FRAME
")
      DUMP(OLDLNB,OLDLNB+256)
%END;                                   ! ASSDUMP
!*
%OWNINTEGER FIRST
!*
%SYSTEMROUTINE NDIAG(%INTEGER PCOUNT, LNB, FAULT, INF)
!***********************************************************************
!*_______'MASTER DIAGNOSTIC ROUTINE'. DISCOVERS THE LANGUAGE OF THE    *
!*_______FAILED ROUTINE FROM WORD 4 OF THE GLA AND CALLS APPROPRIATE   *
!*_______DIAGNOSTIC ROUTINE. THIS IS REPEATED TILL ALL DIAGNOSTICS     *
!*_______GIVEN.                                                        *
!*_______PCOUNT = PCOUNTER AT FAILURE                                  *
!*_______LNB    = LOCAL NAME BASE AT FAILURE                           *
!*_______FAULT  = FAILURE  (0=%MONITOR  REQUESTED)                     *
!*_______INF    =ANY FURTHER INFORMATION                               *
!***********************************************************************
%OWNINTEGER ACTIVE=0;                   ! CHECK FOR LOOPS
%CONSTINTEGER RECURSE LIMIT=16; ! LIMIT OF STACK FRAME UNWOUND
%INTEGER LANGFLAG, I, J, GLA, OLDLNB, NEWLNB, EVENT, SUBEVENT, RECURSE
%SWITCH LANGUAGE(0:6)
%STRING (20) FAILNO
%CONSTSTRING(9)%ARRAY LT(0:6)=" !???! "," IMP "," FORTRAN ",
                              " IMPS "," ASMBLR "," ALGOL60 ",
                              " OPTCODE ";
! LAY DOWN A CONTINGENCY AGAINST ERRORS IN MDIAGS
      I=0; RECURSE=0
      LNB=LNB&(-4)
      *STLN_OLDLNB
      ACTIVE=ACTIVE+1
      FAILNO=" LOOPING"
      %IF ACTIVE>5 %THEN ->EOUT
      FAILNO=" CONT STACK FULL"
      %IF I>0 %THEN ->EOUT;             ! CONTINGENCY DID NOT GO DOWN
!
! FIRST CHECK THE STACK FOR VALID DESCRIPTOR TO GLA. IF INVALID ASSUME
! A FAILURE DURING A CALL AND GO BACK ONE STACK FRAME
!
INVGLA:
      %IF INTEGER(LNB+12)>>25<<1#X'B0' %THEN %C
         LNB=INTEGER(LNB)&(-4) %AND ->INVGLA
      GLA=INTEGER(LNB+16)
      *LDTB_X'18000020'
      *LDA_GLA
      *VAL_(%LNB+1)
      *JCC_12,<GLAOK>;                  ! READ ACCESS AVAILABLE
      LNB=INTEGER(LNB)&(-4); ->INVGLA
GLAOK:
      LANGFLAG=INTEGER(GLA+16)>>24
      LANGFLAG=0 %IF LANGFLAG>6
      SUBEVENT=0;  EVENT=FAULT>>8
      %IF FAULT>=256 %THEN SUBEVENT=FAULT&255 %AND FAULT=0
      TRANS(FAULT,EVENT,SUBEVENT)

!         ONCOND(EVENT,SUBEVENT,LNB)
      FIRST=1
      %IF FAULT>=0 %THEN %START
            PRINT STRING("
MONITOR ENTERED FROM".LT(LANGFLAG)."
!")
         %IF FAULT=0 %AND EVENT#0 %START
            PRINTSTRING("
MONITOR ENTERED
")
            PRINTSTRING("EVENT");  WRITE(EVENT,1)
            PRINTSYMBOL('/');  WRITE(SUBEVENT,1)
         %FINISH %ELSE ERMESS(FAULT,INF)
         NEWLINE
      %FINISH %ELSE EVENT=0

      OLDLNB=LNB
      ->LANGUAGE(LANGFLAG)
LANGUAGE(0):

LANGUAGE(6):                            ! NO TRACE CODE
LANGUAGE(4):                            ! UNKNOWN & ASSEMBLER
      ASSDUMP(PCOUNT,OLDLNB)
      NEWLNB=INTEGER(OLDLNB)&(-4)
      ->NEXTRT
LANGUAGE(1):


LANGUAGE(3):                            ! IMP & IMPS
LANGUAGE(5):                            ! ALGOL 60
      INDIAG(OLDLNB,LANGFLAG>>2,PCOUNT,NEWLNB);   ! IMP DIAGS
      %IF NEWLNB=0 %THEN ->EXIT
NEXTRT:                                 ! CONTINUE TO UNWIND STACK
      PCOUNT=INTEGER(OLDLNB+8)
      OLDLNB=NEWLNB
      RECURSE=RECURSE+1
      ->EXIT %IF OLDLNB<STACKBASE %OR RECURSE>RECURSE LIMIT
                                        ! FAR ENOUGH
      I=INTEGER(OLDLNB+16)
      LANGFLAG=INTEGER(I+16)>>24
      LANGFLAG=0 %IF LANGFLAG>6
      ->LANGUAGE(LANGFLAG)
LANGUAGE(2):                            ! FORTRAN
!         FDIAG(OLDLNB,PCOUNT,NEWLNB)
      %IF NEWLNB=0 %THEN ->EXIT
      ->NEXT RT
EOUT:                                   ! ERRROR EXIT
      PRINTSTRING("
MDIAG FAILS ".FAILNO."
")
      ACTIVE=0
      ->QUIT
EXIT:
                                        ! POP UP CONTINGENCY
      ACTIVE=0
      %IF FAULT=0=EVENT %THEN ->END
QUIT:
      %STOP
      *IDLE_X'DDDD'
END: %END;                              ! OF NDIAG

! LAYOUT OF DIAGNOSIC TABLES
!***********************

! THE BOUND FIELD OF PLT DESCRIPTOR STORED AT (LNB+3 & LNB+4) IF
! USED TO CONTAIN A DISPLACEMENT RELATIVE TO THE START OF SST OF THE
! DIAGNOSTIC TABLES FOR THE BLOCK OR ROUTINE BEING EXECUTED.
! A ZERO BOUND MEANS NO DIAGNOSTIC REQUESTED.(NB THIS MAY MEAN A DUMMY
! FIRST WORD IN THE SST).
! THE ABSOLUTE ADDRESS OF THE SST FOR THE CURRENT CODE SEGMENT WILL
! ALWAYS BE FOUND IN THE STANDARD 10 WORDS OF THE GLA/PLT

! FORM OF THE TABLES:-

! WORD 0    =   LINE OF RT IN SOURCE PROG <<16 ! LINE NO POSN(FROM LNB)
! WORD 1    =   (12 LANG DEPENDENT BITS)<<20 ! ENVIRONMENT
! WORD 2    =   DISPLAY POSN (FROM LNB)<<16 ! RT TYPE INFO
! WORD 3    =   ZERO FOR BLKS OR STRING(<=11BYTES) BEING THE
!               RT NAME. THIS WILL TAKE WORDS 4 AND 5 IF NEEDED
! WORD 6    =  LANGUAGE DEPENDENT INFO . IMP ON CONDITIONS ETC

! THE REST IS MADE UP OF VARIABLE ENTRIES AND THE SECTION IS TERMINATED BY
! A WORD OF X'FFFFFFFF'

!  EACH VARIABLE ENTRY CONSISTS OF THE VARIABLE WORD FOLLOWED BY
! THE VARIABLE NAME AS A STRING. THE WORD CONSISTS OF
! BITS 2**31 TO 2**20 TYPE INFORMATION (MAY BE LANGUAGE DEPENDENT
! BIT  2**19  =0 UNDER LNB =1 IN GLA
! BITS 2**18 TO 2**0 DISPLACEMENT FROM LNB(GLA) IN BYTES


! THE ENVIRONMENT IS A POINTER (RELATIVE TO SST) OF THE NEXT OUTERMOST
! BLOCK OR A POINTER TO GLOBAL OWNS, EXTERNAL OR COMMON AREAS
! A ZERO MEANS NO ENCLOSING BLOCK. WORD1=WORD3=0 IS AN
! IMP MAIN PROGRAM AND WILL TERMINATE THE DIAGNOSTICS.

%ROUTINE INDIAG(%INTEGER OLDLNB, LANG, PCOUNT, %INTEGERNAME NEWLNB)
!***********************************************************************
!*_______THE DIAGNOSTIC ROUTINE FOR IMP(LANG=0) %AND ALGOL             *
!*_______THE ALGOL SYMBOL TABLES ARE SET UP AS FOR IMP                 *
!***********************************************************************
%ROUTINESPEC PRINT LOCALS(%INTEGER ADATA)
%ROUTINESPEC PRINTVAR(%INTEGER ADATA)
%INTEGER GLAAD, FLINE, ADATA, NAM, TYPE, PREC
%INTEGER TSTART, PREV BLK, WORD0, WORD1, WORD2, WORD3, I
%STRING (50) NAME
      GLAAD=INTEGER(OLDLNB+16);         ! ADDR OF GLA/PLT
      TSTART=INTEGER(OLDLNB+12)&X'FFFFFF'
      %IF TSTART=0 %THEN %START
         PRINTSTRING("
RT/FN/MAP COMPILED WITHOUT DIAGNOSTICS
")
         ASSDUMP(PCOUNT,OLDLNB)
         NEWLNB=INTEGER(OLDLNB)&(-4)
         %RETURN
      %FINISH
      %UNTIL PREVBLK=0 %CYCLE
         TSTART=TSTART+INTEGER(GLAAD+12)
         WORD0=INTEGER(TSTART)
         WORD1=INTEGER(TSTART+4)
         WORD2=INTEGER(TSTART+8)
         WORD3=INTEGER(TSTART+12)
         NAME=STRING(TSTART+12)
         I=WORD0&X'FFFF';               ! LINE NO DISP
         %IF I=0 %THEN FLINE=-1 %ELSE FLINE=INTEGER(OLDLNB+I)
         NEWLINE
         %IF FIRST=1 %THEN %START
            PRINTSTRING("MONITOR ")
            FIRST=0
         %FINISH
         PRINTSTRING("ENTERED FROM")
         %IF FLINE>=0 %THEN %START
            PRINTSTRING(" LINE")
            WRITE(FLINE,4)
            PRINTSTRING(" OF")
         %FINISH
         %IF WORD3=0 %THEN PRINTSTRING(" BLOCK") %C
            %ELSE PRINT STRING(" RT/FN/MAP ".NAME)
         PRINTSTRING(" STARTING AT LINE")
         WRITE(WORD0>>16,2)
         %IF LANG=0 %THEN I=20 %ELSE I=16
         PRINT LOCALS(TSTART+I+(WORD3>>26)<<2)
         %IF WORD3#0 %START
            NEWLNB=INTEGER(OLDLNB)&(-4)
            NEWLINE
            %RETURN
         %FINISH
         PREV BLK=WORD1&X'FFFF'
         TSTART=PREV BLK
      %REPEAT
      NEWLNB=0
      NEWLINE;  %RETURN
%ROUTINE PRINT LOCALS(%INTEGER ADATA)
!***********************************************************************
!*______ADATA POINTS TO THE FIRST ENTRY FOR LOCALS IN THE SYMBOL TABLES*
!***********************************************************************
      NEWLINE
      %IF INTEGER(ADATA)<0 %THEN PRINTSTRING("NO ")
      PRINTSTRING("LOCAL VARIABLES
")
      %WHILE INTEGER(ADATA)>0 %CYCLE
         PRINT VAR(ADATA)
         ADATA=ADATA+8+BYTE INTEGER(ADATA+4)&(-4)
      %REPEAT
%END;                                   ! PRINT LOCALS
%ROUTINE PRINT VAR(%INTEGER ADATA)
!***********************************************************************
!*_______OUTPUT THE NEXT VARIABLE IN THE CURRENT BLOCK.                *
!*_______A VARIABLE ENTRY IN THE TABLES IS:-                           *
!*_______FLAG<<20!VBREG<<18!DISP                                       *
!*_______WHERE:-                                                       *
!*_________VBREG IS VARIABLE'S BASE REGISTER, DISP IS IT'S OFFSET      *
!*_________AND FLAGS=NAM<<6!PREC<<3!TYPE                               *
!***********************************************************************
%INTEGER I, J, K, DISP, VBREG, VADDR, V, ARR
%CONSTINTEGER UNASSI=X'81818181'
%STRING(11)LNAME
%STRING(63)MESS
%SWITCH INTV,REALV(3:7)
      I=INTEGER(ADATA)
      DISP=I&X'3FFFF'
      VBREG=I&X'40000'
      K=I>>20
      TYPE=K&7
      PREC=K>>4&7
      ARR=K>>8&3
      NAM=K>>10&1
      LNAME<-STRING(ADATA+4)."          "
      PRINT STRING(LNAME."=")
      %IF VBREG=0 %THEN VADDR=OLDLNB %ELSE VADDR=GLAAD
      VADDR=VADDR+DISP

! USE VALIDATE ADDRESS HERE TO CHECK ACR LEVELS ETC

      *LDTB_X'18000010'
      *LDA_VADDR
      *VAL_(%LNB+1)
      *JCC_3,<INVALID>
      J=VADDR>>18
      ->INVALID %UNLESS VADDR<X'3000' %OR ((J=5 %OR J=7 %OR J=10)%C
         %AND INTEGER(8*J+4)&X'80000001'=X'80000001')
                                        ! ALLOWS PUBLIC AND LOCKED LOCALS ONLY
      %IF (ARR=0 %AND NAM#0) %OR TYPE=5 %THEN %START
         %IF INTEGER(VADDR)>>24=X'E5' %THEN ->ESC
         VADDR=INTEGER(VADDR+4)
         ->NOT ASS %IF VADDR=UNASSI
         *LDTB_X'18000010'
         *LDA_VADDR
         *VAL_(%LNB+1)
         *JCC_3,<INVALID>
         J=VADDR>>18
         ->INVALID %UNLESS VADDR<X'3000' %OR ((J=5 %OR J=7 %OR J=10)%C
         %AND INTEGER(8*J+4)&X'80000001'=X'80000001')
                                        ! ALLOWS PUBLIC AND LOCKED LOCALS ONLY
      %FINISH
      ->ILL ENT %IF PREC<3;             ! BITS NOT IMPLEMENTED
      %IF PREC>=5 %OR ARR#0 %THEN V=INTEGER(VADDR)
      ->ARRAY %IF ARR#0
      %IF TYPE=1 %THEN ->INTV(PREC)
      %IF TYPE=2 %THEN ->REALV(PREC)
      %IF TYPE=5 %THEN ->STR
INTV(4):                                ! 16 BIT INTEGER
      V=HALFINTEGER(VADDR)
      MESS="X'".STRHEX(V)."' ".STRINT(V)
      ->OMESS
INTV(7):                                ! 128 BIT INTEGER
REALV(3):                               ! 8 BIT REAL
REALV(4):                               ! 16 BIT REAL
ILL ENT:                                ! SHOULD NOT OCCURR
      MESS="UNKNOWN TYPE OF VARIABLE"
      ->OMESS
INTV(5):                                ! 32 BIT INTEGER
      ->NOT ASS %IF V=UN ASSI
      MESS="X'".STRHEX(V)."' ".STRINT(V)
      ->OMESS
INTV(3):                                ! 8 BIT INTEGER
      WRITE(BYTEINTEGER(VADDR),1);  ->NEWL
REALV(5):                               ! 32 BIT REAL
      ->NOT ASS %IF V=UN ASSI
      MESS="X'".STRHEX(V)."'"
      ->OMESS
INTV(6):                                ! 64 BIT INTEGER
REALV(6):                               ! 64 BIT REAL
REALV(7):                               ! 128 BIT REAL
ARRAY:                                  ! ARRAY PRINT 128 BIT HEADER
      ->NOT ASS %IF UN ASSI=V
      MESS="X'".STRHEX(V).STRHEX(INTEGER(VADDR+4))
      %IF PREC=7 %OR ARR#0 %THEN %START
        MESS=MESS." ".STRHEX(INTEGER(VADDR+8)).STRHEX(INTEGER(VADDR+12))
      %FINISH
      MESS=MESS."'"; ->OMESS
STR:  ->NOT ASS %IF BYTE INTEGER(VADDR+1)=UNASSI&255=BYTEINTEGER( %C
         VADDR)
      ->TOOLONG %IF BYTEINTEGER(VADDR)>50
      MESS="""".STRING(VADDR).""""
      ->OMESS
ESC:                                    ! ESCAPE DESCRIPTOR
INVALID:

      MESS=" INVALID ADDRESS ".STRHEX(VADDR);  ->OMESS
TOO LONG:
      MESS=" TOO LONG "; ->OMESS;       ! ASSUME SHORT STRINGS
NOT ASS:
      MESS=" NOT ASSIGNED"
OMESS:PRINTSTRING(MESS)
NEWL: NEWLINE
%END;                                   ! PRINT VAR
%END;                                   ! OF RT IDIAGS
!*
%ROUTINE ERMESS(%INTEGER N, INF)
!***********************************************************************
!*_______OUTPUTS AN ERROR MESSAGE STORED IN A COMPRESSED FORMAT        *
!***********************************************************************
%CONSTBYTEINTEGERARRAY TR(0:13)=1,2,3,4,5,6,7,3,
                                10,10,7,7,8,10
      %RETURN %IF N<=0
      %IF N=35 %THEN N=10
      %IF N=10 %THEN %START;            ! DEAL WITH INTERRUPT WT
         %IF INF=32 %THEN N=9
         %IF INF<=13 %THEN N=TR(INF)
         %IF INF=140 %THEN N=25
         %IF INF=144 %THEN N=28
                                        ! MORE HELPFUL MESSAGE IF 
                                        !POSSIBLE
      %FINISH
!*
      PRINTMESS(N)
!*
! (WE WOULD GET AN IOCP REF ON THIS NEXT LINE)
!         %IF N=26 %THEN PRINT SYMBOL(NEXT SYMBOL)
!*__________N=6(ARRAY BOUND FAULT) EXCLUDED FROM FOLLOWING - 19/3/76
      %IF N=16 %OR N=17 %OR N=10 %THEN WRITE(INF,1)
      NEWLINE
%END;                                   ! ERMESS
%ROUTINE PRINTMESS(%INTEGER N)
      PRINTSTRING("PROGRAM ERROR")
      WRITE(N,3)
      NEWLINE
%END

%ENDOFFILE