%MAINEP ICL9CEZPERQIMP
%TRUSTEDPROGRAM
%BEGIN
%CONSTINTEGER RELEASE=4
%CONSTINTEGER YES=1,NO=0
%CONSTINTEGER ON PERQ=NO
%CONSTSTRING(9) LADATE="9 Sep 82";       ! LAST ALTERED
%INTEGER I, J, K
%CONSTINTEGER NO OF SNS=63
%CONSTINTEGER LRLPT=X'62'
!
%CONSTBYTEINTEGERARRAY BYTES(0:7)=0(3),1,2,4,8,16;
%CONSTBYTEINTEGERARRAY WORDS(0:7)=0(3),1,1,2,4,8;
%CONSTINTEGER MAXLEVELS=31,CONCOP=13
!
%INCLUDE "ERCC07.PERQ_OPCODES"
%INCLUDE "ERCC07.TRIPCNSTS"
%INCLUDE "ERCC07.PERQ_FORMAT3S"
%CONSTINTEGER SNPT=X'1006';         ! SPECIALNAME PTYPE
%CONSTINTEGER UNASSPAT=X'80808080'
%CONSTINTEGER LABUSEDBIT=X'01000000'
%CONSTINTEGER LABSETBIT=X'02000000'
%CONSTSTRING(8)MDEP="S#NDIAG"
!
%INTEGER DUMMYFORMAT, P1SIZE, STARSIZE, ASL, ARSIZE, OLDLINE,
         NEXTP, SNUM, RLEVEL, NMAX, PLABEL, LEVEL, PROFAAD, LAST INST,
         LINE, BFFLAG, RBASE, N, EXITLAB, CONTLAB, Q, R, FNAME, STMTS,
         FILE PTR, FILE END, FILE SIZE, BIMSTR, MAX ULAB, SFLABEL, NEXTTRIP
%INTEGERNAME CA,GLACA,SSTL,USTPTR
%STRING(31)MAINEP
!
%EXTERNALRECORD(CODEPF)CODEP
%EXTERNALRECORD(PARMF) PARM
%EXTERNAL%RECORD(WORKAF)WORKA
%SYSTEMINTEGERMAPSPEC COMREG(%INTEGER N)
%BEGIN
      WORKA_FILE ADDR=COMREG(46);       ! SOURCE FILE IF CLEAN
      PARM=0
      PARM_BITS1=COMREG(27)
      PARM_BITS2=COMREG(28)
      WORKA_WKFILEAD=COMREG(14)
      WORKA_WKFILEK=INTEGER(WORKA_WKFILEAD+8)>>10
      %IF WORKA_FILE ADDR<=0 %THEN %START
         FILESIZE=64000
         WORKA_FILE ADDR=0
      %FINISH %ELSE %START
         FILE PTR=WORKA_FILE ADDR+INTEGER(WORKA_FILE ADDR+4)
         FILE END=WORKA_FILE ADDR+INTEGER(WORKA_FILE ADDR)
         FILE SIZE=INTEGER(WORKA_FILE ADDR)
      %FINISH
      WORKA_NNAMES=511
      %IF FILESIZE>32000 %THEN WORKA_NNAMES=1023
      %IF FILESIZE>256*1024 %OR WORKA_WKFILEK>512 %THEN WORKA_NNAMES=2047
      ASL=3*WORKA_NNAMES
      %IF ASL>4095 %THEN ASL=4095
      WORKA_ASL MAX=ASL
      ARSIZE=WORKA_WKFILEK*768-300
%END
%BYTEINTEGERARRAYFORMAT AF(0:ARSIZE)
%BYTEINTEGERARRAYNAME A
%RECORD(LISTF)%ARRAY ASLIST(0:ASL)
%INTEGERARRAY WORD, TAGS(0:WORKA_NNAMES)
%INTEGERARRAY DVHEADS(0:12)
%RECORD(LEVELF)%ARRAY LEVELINF(0:MAXLEVELS)
%INTEGERFNSPEC FROMAR4(%INTEGER PTR)
%INTEGERFNSPEC FROMAR2(%INTEGER PTR)
%EXTERNALROUTINESPEC INITASL(%RECORD(LISTF)%ARRAYNAME A,%INTEGERNAME B)
%EXTERNALINTEGERFNSPEC MORE SPACE
!%EXTERNALINTEGERFNSPEC NEWCELL
%EXTERNALROUTINESPEC INSERTATEND(%INTEGERNAME S, %INTEGER A, B, C)
%EXTERNALROUTINESPEC INSERT AFTER(%INTEGERNAME S,%INTEGER A,B,C)
%EXTERNALROUTINESPEC FROM12(%INTEGER CELL, %INTEGERNAME S1, S2)
%EXTERNALROUTINESPEC FROM123(%INTEGER CELL, %INTEGERNAME S1, S2, S3)
%EXTERNALROUTINESPEC POP(%INTEGERNAME C, P, Q, R)
%EXTERNALROUTINESPEC PUSH(%INTEGERNAME C, %INTEGER S1, S2, S3)
%EXTERNALINTEGERFNSPEC FIND(%INTEGER LAB, LIST)
%EXTERNALROUTINESPEC MLINK(%INTEGERNAME CELL)
%EXTERNALROUTINESPEC REPLACE1(%INTEGER CELL, S1)
%EXTERNALROUTINESPEC REPLACE123(%INTEGER CELL,A1,A2,S3)
%EXTERNALINTEGERFNSPEC FROM2(%INTEGER CELL)
%EXTERNALINTEGERFNSPEC FROM1(%INTEGER CELL)
%EXTERNALINTEGERFNSPEC FROM3(%INTEGER CELL)
%EXTERNALROUTINESPEC BINSERT(%INTEGERNAME T,B,%INTEGER S1,S2,S3)
%EXTERNALROUTINESPEC CLEARLIST(%INTEGERNAME HEAD)
%EXTERNALROUTINESPEC CODEOUT
%EXTERNALROUTINESPEC PTLATE(%INTEGER WORD)
%EXTERNALROUTINESPEC PWORD(%INTEGER WORD)
%EXTERNALROUTINESPEC PB1(%INTEGER OPCODE)
%EXTERNALROUTINESPEC PB2(%INTEGER OPCODE,BYTE)
%EXTERNALROUTINESPEC PB3(%INTEGER OPCODE,BYTE1,BYTE2)
%EXTERNALROUTINESPEC PB4(%INTEGER OPCODE,B1,B3,B3)
%EXTERNALROUTINESPEC PBW(%INTEGER OPCODE,WORD)
%EXTERNALROUTINESPEC PWW(%INTEGER OPCODE,W1,W2)
%EXTERNALROUTINESPEC PB2W(%INTEGER OPCODE,BYTE1,WORD)
%EXTERNALROUTINESPEC PERM
%EXTERNALROUTINESPEC CAB
%EXTERNALROUTINESPEC CNOP(%INTEGER I, J)
%EXTERNALROUTINESPEC PGLA(%INTEGER BDRY, L, INF ADR)
%EXTERNALROUTINESPEC PLUG(%INTEGER AREA, AT, VALUE, BYTES)
%EXTERNALROUTINESPEC GXREF(%STRING(31) NAME,%INTEGER MODE,XTRA,AT)
%EXTERNALROUTINESPEC CIOCP(%INTEGER N)
%EXTERNALROUTINESPEC RELOCATE(%INTEGER BITS,GLARAD,AREA)
%EXTERNALROUTINESPEC ABORT
%EXTERNALROUTINESPEC PERQPROLOGUE
%EXTERNALROUTINESPEC REPEAT PROLOGUE
%EXTERNALROUTINESPEC PERQEPILOGUE(%INTEGER STMTS)
%DYNAMICROUTINESPEC QPUT(%INTEGER A,B,C,D)
%EXTERNALROUTINESPEC FAULT(%INTEGER A,B,C)
%EXTERNALROUTINESPEC WARN(%INTEGER N,V)
%EXTERNALROUTINESPEC PPJ(%INTEGER MASK,N)
%EXTERNALROUTINESPEC ERASE(%INTEGER WORDS)
%EXTERNALREALFNSPEC ICLREALTOPERQ(%REAL ICLREAL)
%EXTERNALLONGREALFNSPEC ICLLONGREALTOPERQ(%LONGREAL ICLREAL)
%EXTERNALROUTINESPEC PRINTTRIPS(%RECORD(TRIPF)%ARRAYNAME T)
! END OF "ERCC07.PERQ_XSPECS"
%EXTERNALROUTINESPEC STACKDUMP(%INTEGER WORDS)
%EXTERNALROUTINESPEC STACKUNDUMP(%INTEGER WORDS)
%EXTERNALROUTINESPEC CTOP(%INTEGERNAME OP,MASK,%INTEGER XTRA,
         %RECORD(RD)%NAME OPND1,OPND2)
%EXTERNALROUTINESPEC GENERATE(%RECORD(TRIPF)%ARRAYNAME T,
      %RECORD(LEVELF)%NAME L,%ROUTINE GETWSP(%INTEGERNAME PL,%INTEGER SIZE))
%EXTERNALROUTINESPEC PRINTLIST(%INTEGER HEAD)
         ! START OF COMPILATION
         A==ARRAY(WORKA_WKFILE AD+256*WORKA_WKFILEK, AF)
         %BEGIN
!***********************************************************************
!*       THIS BLOCK INITIALISE THE COMPILER SCALARS AND ARRAYS         *
!*       WAS ORIGINALLY ROUTINE 'INITIALISE'.                          *
!*       THE INITIALISATION OF THE CONSTANT LISTS WITH THE VALUES      *
!*       IN PERM MAY BE OMITTED IN BATCH OR CUT-DOWN VERSIONS.         *
!***********************************************************************
%EXTERNALINTEGERFNSPEC PASSONE
      WORKA_CCSIZE=256*(WORKA_WKFILEK-1)
%BYTEINTEGERARRAYFORMAT CCF(0:WORKA_CCSIZE)
%BYTEINTEGERARRAYNAME CC
         CC==ARRAY(WORKA_WKFILEAD+32,CCF)
      WORKA_CC==CC
      WORKA_A==A
      WORKA_WORD==WORD
      WORKA_TAGS==TAGS
      WORKA_LINE==LINE
      WORKA_RELEASE=RELEASE
      WORKA_LADATE=LADATE
      WORKA_AASL0=ADDR(ASLIST(0))
      PLABEL=24999
      N=12;
      MAX ULAB=WORKA_NNAMES+16384;      ! LARGEST VALID USER LABEL
      LAST INST=0
      SFLABEL=20999
      EXITLAB=0; CONTLAB=0
      RLEVEL=0; NMAX=0; BFFLAG=0
      RBASE=1
      CA==CODEP_CAS(1); GLACA==CODEP_CAS(2)
      SSTL==CODEP_CAS(4); USTPTR==CODEP_CAS(5)
      STMTS=1;  SNUM=0
      BIMSTR=0
      WORKA_RTCOUNT=1;                  ! ROUTINE 0 RESERVED FOR MAIN PROG
      MAINEP="S#GO";                    ! DEFAULT MAIN ENTRY
!
! OPEN OBJECT FILE HERE BEFORE MORE PAGES OF COMPILER CODE
! ARE PAGED IN AND SUB-SYSTEM PAGES MOVE OUT
!
      QPUT(0,0,0,0)
      INITASL(ASLIST,ASL)
      %CYCLE I=0,1,12
         DVHEADS(I)=0
      %REPEAT
!
      DUMMY FORMAT=0;                   ! DUMMY RECORD FORMAT
      PUSH(DUMMY FORMAT,0,0,0);         ! FOR BETTER ERROR RECOVERY
      P1SIZE=PASSONE
      R=P1SIZE
      WORKA_ARTOP=P1SIZE
%END;                              ! OF BLOCK CONTAINING PASS 1
%BEGIN
!***********************************************************************
!*    SECOND OR TRIPLES GENERATING PASS                                *
!***********************************************************************
%RECORD(LEVELF)%NAME CURRINF
%INTEGER TWSPHEAD
%RECORD(TRIPF)%ARRAY TRIPLES(0:999)
%INTEGERARRAYFORMAT CF(0:12*WORKA_NNAMES)
%INTEGERARRAYNAME CTABLE
!%ROUTINESPEC NOTE CREF(%INTEGER CA)
!%ROUTINESPEC STORE CONST(%INTEGERNAME D,%INTEGER L,AD)
!%INTEGERFNSPEC WORD CONST(%INTEGER VALUE)
%ROUTINESPEC REUSE TEMPS
%ROUTINESPEC GET WSP(%INTEGERNAME PLACE,%INTEGER SIZE)
%ROUTINESPEC RETURN WSP(%INTEGER PLACE,SIZE)
%ROUTINESPEC COMPILE A STMNT
%INTEGERFNSPEC NEW TRIP
%INTEGERFNSPEC UCONSTTRIP(%INTEGER OPERN,OPTYPE,FLAGS,CONST)
%INTEGERFNSPEC UNAMETRIP(%INTEGER OPERN,OPTYPE,FLAGS,NAME)
%INTEGERFNSPEC UTEMPTRIP(%INTEGER OPERN,OPTYPE,FLAGS,TEMP)
%INTEGERFNSPEC BRECTRIP(%INTEGER OPERN,OPTYPE,FLAGS,
         %RECORD(RD)%NAME OPND1,OPND2)
%INTEGERFNSPEC URECTRIP(%INTEGER OPERN,OPTYPE,FLAG,%RECORD(RD)%NAME OPND1)
%ROUTINESPEC CSS(%INTEGER P)
         %CYCLE I=0, 1, MAXLEVELS
         LEVELINF(I)=0
         LEVELINF(I)_NAMES=-1
         %REPEAT
         CTABLE==ARRAY(ADDR(ASLIST(1)),CF)
         WORKA_CTABLE==CTABLE
         WORKA_LEVELINF==LEVELINF
         CTABLE(0)=M'CTAB'
         LINE=0
         TWSPHEAD=0
         PERQPROLOGUE
         NEXTTRIP=1
         NEXTP=1; LEVEL=1; STMTS=0
         CURRINF==LEVELINF(LEVEL)
         RLEVEL=0; RBASE=0
         %WHILE A(NEXTP+3)!A(NEXTP+4)#0 %CYCLE
            COMPILE A STMNT
         %REPEAT
         LINE=99999
         PERQEPILOGUE(STMTS)
         %STOP
%ROUTINE FORCE TRIPS
!***********************************************************************
!*    FORCE OUT THE TRIPLES TO CODE. NEEDED IN CEND ETC                *
!***********************************************************************
      %IF PARM_DCOMP#0 %THEN CODEOUT
      %RETURN %IF NEXT TRIP=1
      GENERATE(TRIPLES,CURRINF,GET WSP)
      %IF PARM_DCOMP#0 %THEN CODEOUT
      TRIPLES(0)=0
      NEXTTRIP=1
      TRIPLES(0)_FLINK=NEXT TRIP
%END
%ROUTINE COMPILE A STMNT
%INTEGER I
      %IF TWSPHEAD#0 %THEN REUSE TEMPS
      FORCE TRIPS %IF NEXT TRIP>1
      I=NEXTP
      STARSIZE=A(NEXTP)<<16+A(NEXTP+1)<<8+A(NEXTP+2)
      NEXTP=NEXTP+STARSIZE
      LINE=A(I+3)<<8+A(I+4)
      STMTS=STMTS+1
      CSS(I+5)
!      %CYCLE I=0,1,4
!      %REPEAT
!      CHECK ASL %IF LINE&7=0
%END
%ROUTINE CSS(%INTEGER P)
%RECORDFORMAT RD((%INTEGER S1 %OR %BYTEINTEGER UPTYPE,PTYPE,XB,FLAG),%C
   %INTEGER D,XTRA)
%ROUTINESPEC ENTER JUMP(%INTEGER MASK,STAD,FLAG)
%INTEGERFNSPEC ENTER LAB(%INTEGER M,FLAG)
%ROUTINESPEC REMOVE LAB(%INTEGER LAB)
%ROUTINESPEC CEND(%INTEGER KKK)
%INTEGERFNSPEC CCOND(%INTEGER CTO,A,B,JFLAGS)
%INTEGERFNSPEC REVERSE(%INTEGER MASK)
%ROUTINESPEC SET LINE
%ROUTINESPEC CUI(%INTEGER CODE)
%ROUTINESPEC ASSIGN(%INTEGER A,B)
%ROUTINESPEC CSTART(%INTEGER CCRES,MODE)
%INTEGERFNSPEC CHECKBLOCK(%INTEGER P,PIN)
%ROUTINESPEC CCYCBODY(%INTEGER UA,ELAB,CLAB)
%ROUTINESPEC CLOOP(%INTEGER ALT,MARKC,MARKUI)
%ROUTINESPEC CIFTHEN(%INTEGER MARKIU,MARKC,MARKUI,MARKE,MARKR,SKIP)
%ROUTINESPEC CREATE AH(%INTEGER MODE)
%ROUTINESPEC TORP(%INTEGERNAME HEAD,BOT,NOPS)
%INTEGERFNSPEC INTEXP(%INTEGERNAME VALUE,%INTEGER PRECTYPE)
%INTEGERFNSPEC CONSTEXP(%INTEGER PRECTYPE)
%ROUTINESPEC CSEXP(%INTEGER MODE)
%ROUTINESPEC CSTREXP(%INTEGER B)
%ROUTINESPEC CRES(%INTEGER LAB)
%ROUTINESPEC EXPOP(%INTEGERNAME A,B,%INTEGER C,D)
%ROUTINESPEC  TEST APP(%INTEGERNAME NUM)
%ROUTINESPEC SKIP EXP
%ROUTINESPEC SKIP APP
%ROUTINESPEC NO APP
%INTEGERFNSPEC DOPE VECTOR(%INTEGER A,B,MODE,ID,%INTEGERNAME C,D)
%ROUTINESPEC DECLARE ARRAYS(%INTEGER A,B)
%ROUTINESPEC DECLARE SCALARS(%INTEGER A,B)
%ROUTINESPEC CRSPEC(%INTEGER M)
%INTEGERFNSPEC SET SWITCHLAB(%INTEGER HEAD,LAB,FNAME,BIT)
%ROUTINESPEC CFPLIST(%INTEGERNAME A,B)
%ROUTINESPEC CFPDEL
%ROUTINESPEC CLT
%ROUTINESPEC CQN(%INTEGER P)
%INTEGERFNSPEC TSEXP(%INTEGERNAME VALUE)
%ROUTINESPEC CRCALL(%INTEGER RTNAME)
%ROUTINESPEC NAMEOP(%INTEGER Z,SIZE,NAMEP)
%ROUTINESPEC CNAME(%INTEGER Z)
%ROUTINESPEC AATORP(%INTEGERNAME A,B,C,%INTEGER D,E,F)
%ROUTINESPEC CANAME(%INTEGER Z,ARRP,BS,DP)
%ROUTINESPEC CSNAME(%INTEGER Z)
%ROUTINESPEC COPY TAG(%INTEGER KK)
%ROUTINESPEC REDUCE TAG
%ROUTINESPEC STORE TAG(%INTEGER KK,SLINK)
%ROUTINESPEC UNPACK
%ROUTINESPEC PACK(%INTEGERNAME PTYPE)
%ROUTINESPEC DIAG POINTER(%INTEGER LEVEL)
%ROUTINESPEC RDISPLAY(%INTEGER KK)
%ROUTINESPEC RHEAD(%INTEGER RTNAME,AXNAME)
%ROUTINESPEC EVEN ALIGN
%INTEGERFNSPEC CFORMATREF
%ROUTINESPEC CRFORMAT(%INTEGERNAME OPHEAD,OPBOT,NLIST,MRL,%INTEGER INIT)
%INTEGERFNSPEC DISPLACEMENT(%INTEGER LINK)
%INTEGERFNSPEC COPY RECORD TAG(%INTEGERNAME SUBS)
%ROUTINESPEC BULKM(%INTEGER  M,L,D2)
%ROUTINESPEC BYTECUT(%INTEGER ODDEVEN)
%ROUTINESPEC DFETCHAD(%INTEGER SEGNO,LEVEL,DISP)
%ROUTINESPEC DFETCH(%INTEGER SIZE,LEVEL,DISP)
%ROUTINESPEC DSTORE(%INTEGER SIZE,LEVEL,DISP)
%SWITCH SW(1:24)
%CONSTBYTEINTEGERARRAY FCOMP(0:14)=0,
                                   8,10,2,7,12,4,7,
                                   8,12,4,7,10,2,7;
%INTEGER SNDISP,ACC,K,KFORM,STNAME,MIDCELL
%INTEGER TCELL,JJ,JJJ,KK,QQ,MARKER,REPORTUI,XDISP,MASK, %C
      BASE,AREA,ACCESS,DISP,EXTRN, CURR INST,VALUE,STRINGL, %C
      PTYPE,I,J,OLDI,USEBITS,STRFNRES,BML,DML, %C
      MARKIU,MARKUI,MARKC,MARKE,MARKR,INAFORMAT
%INTEGER LITL,ROUT,NAM,ARR,PREC,TYPE
%OWNINTEGER FPTR
%RECORD(RD) EXPOPND;                    ! RESULT RECORD FOR EXPOP
         CURR INST=0; INAFORMAT=0
         ->SW(A(P))
SW(13):                                 ! INCLUDE SOMETHING
SW(24):                                 ! REDUNDANT SEP
SW(2):                                  ! <CMARK> <COMMENT TEXT>
CSSEXIT:  LAST INST=CURR INST
         %RETURN
SW(1):                                !(UI)(S)
         FAULT(57,0,0) %UNLESS LEVEL>=2
         MARKER=P+1+A(P+1)<<8+A(P+2)
         P=P+3
         ->LABFND %IF A(MARKER)=1
         %IF A(MARKER)=2 %THEN SET LINE %AND CUI(0) %AND ->CSSEXIT
         MARKE=0; MARKR=0
         MARKUI=P; MARKIU=MARKER+1
         MARKC=MARKIU+1
         %IF A(MARKER)=3 %THEN CIFTHEN(MARKIU,MARKC,MARKUI,0,0,NO) %C
            %AND ->CSSEXIT
         CLOOP(A(MARKIU),MARKC+2,MARKUI)
         ->CSSEXIT
LABFND:  OLDLINE=0
         ->SWITCH %UNLESS A(P)=1 %AND A(P+5)=2;  ! 1ST OF UI AND NO APP
         ->SWITCH %UNLESS A(P+6)=2 %AND A(P+7)=2;! NO ENAMSE OR ASSNMNT
         JJ=ENTER LAB(FROM AR2(P+3),0); ->CSSEXIT
SW(5):                                 ! %CYCLE
         FAULT(57,0,0) %UNLESS LEVEL>=2
         %IF A(P+5)=2 %THEN %START;     ! OPEN CYCLE
            CLOOP(0,P+1,P+1)
         %FINISH %ELSE %START
            SET LINE
            CLOOP(6,P+6,P+1)
         %FINISH
         ->CSSEXIT
!
SW(6):                                 ! REPEAT
         ->CSSEXIT
SW(22):                                ! '%CONTROL' (CONST)
         J=FROM AR4(P+2)
         CODEOUT
         PARM_DCOMP=J>>28; ->CSSEXIT
!
SW(3):                                 ! (%IU)(COND)%THEN(UI)(ELSE')
         MARKIU=P+1; MARKC=MARKIU+3
         MARKR=P+2+A(P+2)<<8+A(P+3); ! ! FROMAR2(P+2)
         MARKE=0
         %IF A(MARKR)=3 %THEN %START
            MARKE=MARKR+1+FROMAR2(MARKR+1)
            MARKUI=MARKR+3
         %FINISH
         CIFTHEN(MARKIU,MARKC,MARKUI,MARKE,MARKR,NO)
         ->CSSEXIT
SW(4):
                                        ! '%FINISH(ELSE')(S)
      ->CSSEXIT
SWITCH:  %BEGIN;                       ! SWITCH LABEL
%INTEGER NAPS,FNAME
      FNAME=FROM AR2(P+3)
      %UNLESS A(P)=1 %AND A(P+5)=1 %THEN FAULT(5,0,FNAME) %AND ->BEND
                                        ! 1ST OF UI + APP
      P=P+3; TEST APP(NAPS)
      P=P+6
      %UNLESS INTEXP(JJ,X'41')=0 %THEN FAULT(41,0,0) %AND ->BEND
                                        ! UNLESS EXPRESSION EVALUATES AND
      %UNLESS NAPS=1 %THEN FAULT(21,NAPS-1,FNAME) %AND ->BEND
                                        ! NO REST OF APP
      %UNLESS A(P+1)=2=A(P+2) %THEN FAULT(5,0,FNAME) %AND ->BEND
                                        ! NO ENAME OR REST OF ASSIGMENT
      COPY TAG(FNAME)
      %IF OLDI#LEVEL %OR TYPE#6 %THEN FAULT(4,0,FNAME) %AND ->BEND
      %IF SET SWITCHLAB(K,JJ,FNAME,1)#0 %THEN FAULT(6,JJ,FNAME)
BEND:    %END;   ->CSSEXIT
SW(23):
                                        ! SWITCH(*):
%BEGIN
%INTEGER FNAME,LB,UB,JJ,RES
      FNAME=FROM AR2(P+1)
      COPY TAG (FNAME)
      %IF OLDI=LEVEL %AND TYPE=6 %START
         FROM123(K,JJ,LB,UB)
         %CYCLE JJ=LB,1,UB
            RES=SET SWITCHLAB(K,JJ,FNAME,0)
         %REPEAT
      %FINISH %ELSE FAULT(4,0,FNAME)
%END; ->CSSEXIT
!
SW(7):                                 ! (%WU)(SC)(COND)(RESTOFWU)
         FAULT(57,0,0) %UNLESS LEVEL>=2
         MARKIU=P+1;                   ! TO WHILE/UNTIL
         MARKC=MARKIU+3;               ! TO (SC)(COND)
         CLOOP(A(MARKIU)+3,MARKC,MARKIU+1+FROMAR2(MARKIU+1))
         ->CSSEXIT
!
SW(8):                                 ! SIMPLE DECLN
         FAULT(57,0,0) %UNLESS LEVEL>=2
         FAULT(40,0,0) %IF CURRINF_NMDECS&1#0
         P=P+1
         MARKER=P+FROMAR2(P);           ! TO ALT OF DECLN
         P=P+2; ROUT=0; LITL=0
         %IF A(MARKER)#1 %THEN %START; ! ARRAY DECLARATIONS
            CLT
            %IF TYPE=5 %AND (ACC<=0 %OR ACC>256) %THEN %C
               FAULT(70,ACC-1,0)  %AND ACC=255
            NAM=0
            SET LINE
            QQ=2-A(P+1); P=P+2;        ! QQ=1 FOR ARRAYFORMATS
            DECLARE ARRAYS(QQ,KFORM)
         %FINISH %ELSE %START
            CLT
            CQN(P+1); P=P+2
            DECLARE SCALARS(1,KFORM)
         %FINISH
         ->CSSEXIT
!
SW(9):                                 ! %END
         %BEGIN
         %SWITCH S(1:5)
         -> S(A(P+1))
S(1):                                  ! ENDOFPROGRAM
S(2):                                  ! ENDOFFILE
         %IF PARM_CPRMODE=0 %THEN PARM_CPRMODE=2
         FAULT(15,LEVEL+PARM_CPRMODE-3,0) %UNLESS LEVEL+PARM_CPRMODE=3
         CEND(PARM_CPRMODE)
         ->BEND
S(3):                                  ! ENDOFLIST
         ->BEND
S(4):                                  ! END
         %IF PARM_CPRMODE=1 %AND LEVEL=2 %THEN FAULT(14,0,0) %ELSE %C
            CEND(CURRINF_FLAG)
BEND:    %END
         ->CSSEXIT
!
SW(11):
%BEGIN
%INTEGER MARKER1,RTNAME,KKK,PTR,PTYPEP,CNT,PP,PCHAIN,AXNAME
%RECORD(LISTF)%NAME LCELL
      P=P+1; MARKER1=FROM AR2(P)+P;     ! (SEX)(RT)(SPEC')(NAME)(FPP)
AGN:  Q=P; RTNAME=FROM AR2(MARKER1+1);  ! RTNAME ON NAME
      EXTRN=A(P+2);                     ! 1=SYSTEM,2=EXTERNAL
                                        ! 3=DYNAMIC, 4=INTERNAL

      LITL=EXTRN&3
      %IF A(MARKER1)=1 %THEN %START;    ! P<%SPEC'>='%SPEC'
         P=P+3;  CRSPEC(1-EXTRN>>2);    ! 0 FOR ROUTINESPEC
                                        ! 1 FOR EXTERNAL (ETC) SPEC
         ->BEND
      %FINISH
      COPY TAG(RTNAME)
      AXNAME=WORKA_DICTBASE+WORD(RTNAME)
      %IF EXTRN=3 %THEN EXTRN=2
      %IF A(MARKER1+3)=1 %THEN AXNAME=ADDR(A(MARKER1+4))
      %IF EXTRN=4 %THEN AXNAME=0
      %IF OLDI=LEVEL %THEN %START;      ! NAME ALREADY KNOWN AT THIS LEVEL
         %IF PARM_CPRMODE=0 %THEN PARM_CPRMODE=2; ! FLAG AS FILE OF ROUTINES
         FAULT(56,0,RTNAME) %UNLESS EXTRN=4 %OR %C
            (PARM_CPRMODE=2 %AND LEVEL=1)
         %IF A(P+3)=1 %THEN KKK=LITL<<14!X'1000' %ELSE %START
            ROUT=1; P=P+4;              ! FIGURE OUT PTYPE FOR FNS&MAPS
            CLT; ARR=0; NAM=0
            %IF A(P)=2 %THEN NAM=2;     ! SET NAME ARRAY BIT FOR MAPS
            PACK(KKK);                  ! AND STORE PTYPE IN KKK
         %FINISH
      %FINISH
!
! UNLESS A MATCH WAS OBTAINED BETWEEN HEADING AND SPEC SOMETHING
! HAS GONE WRONG. COMPILE HEADING AGAIN AS SPEC. THIS WILL
! PREVENT ANY INCONSISTENCIED AND CAUSE A "NAME SET TWICE"
! FOR ANY ERROR
!
      %UNLESS OLDI=LEVEL %AND (J=15 %OR J=7*EXTRN) %AND %C
         PTYPE=KKK %START
         P=Q+3; CRSPEC(0); P=Q; ->AGN
      %FINISH
      PTYPE=PTYPE!(EXTRN&3)<<14;        ! DEAL WITH %ROUTINESPEC FOLLOWED
                                        ! BY %EXTERNALROUTINE
!
! RESET THE TAGS TO BODY GIVEN AND ALLOWING FOR SPEC/EXTERNALROUTINE
! AND EXTERNALSPEC/EXTERNAL ROUTINE COMBINATIONS. RESTORE THE USE
! BITS WHICH WILL SHOW USED AS A RESULT OF THE COPYTAG IN THIS SEQUENCE
!
      LCELL==ASLIST(TAGS(RTNAME))
      LCELL_S1=LCELL_S1&X'3FF0'!PTYPE<<16!USEBITS<<14
                                        ! NEWPTYPE & SET J=0
      %IF J=14 %THEN LCELL_S2=WORKA_RTCOUNT %AND %C
         WORKA_RTCOUNT=WORKA_RTCOUNT+1;  ! NO RT NO ALLOCATED TO EXTERNAL SPECS
      PTYPEP=PTYPE
      PCHAIN=K;                         ! CHAIN OF PARAMETER DESCRIPTUONS
      RHEAD(RTNAME,AXNAME);             ! FIRST PART OF ENTRY SEQUENCE
!
! NOW DECLARE THE FORMAL PARAMETERS. FOLLOW BY CLAIMING DISPLAY
! AND SETTING DIAGNOSTIC PTR IN ROUTINE RDISPLAY
!
      P=MARKER1+4
      %IF A(P-1)=1 %THEN P=P+A(P)+1;    ! SKIP OVER ALIASNAME
      N=0; CNT=1
      PTYPE=PTYPEP; UNPACK
      %IF TYPE#0 %THEN N=(BYTES(PREC)+1)&(-2)
      %IF NAM#0 %OR TYPE=5 %THEN N=4;   ! MAPS
      %WHILE A(P)=1 %CYCLE;             ! WHILE SOME (MORE) FP PART
         PP=P+1+FROMAR2(P+1)
         P=P+3
         CFPDEL
         PTR=P
         %UNTIL A(PTR-1)=2 %CYCLE;      ! CYCLE DOWN NAMELIST
            %IF PCHAIN#0 %THEN %START
               FROM12(PCHAIN,J,JJJ);    ! EXTRACT PTYPE XTRA INFO
               %UNLESS J>>16=PTYPE %AND(PTYPE#5 %OR JJJ>>16=ACC)%C
                  %THEN FAULT(9,CNT,RTNAME)
            %FINISH %ELSE FAULT(8,0,RTNAME);! MORE FPS THAN IN SPEC
            PTR=PTR+3
            CNT=CNT+1
            MLINK(PCHAIN)
         %REPEAT
         DECLARE SCALARS(0,KFORM)
         P=PP
      %REPEAT;                          ! UNTIL NO MORE FP-PART
      N=(N+1)&(-2);                     ! TO WORD BOUNDARY AFTER ALL SYSTEM
                                        ! STANDARD PARAMETERS HAVE BEEN DECLARED
      FAULT(10,0,RTNAME) %UNLESS PCHAIN=0
      PTYPE=PTYPEP
!      %IF PTYPE&X'F0F'=5 %THEN N=N+8;   ! STR FNS RESULT PARAM IS STACKED
                                        ! AS XTRA PARM JUST BEFORE DISPLAY
      RDISPLAY(RTNAME)
BEND: %END; ->CSSEXIT
!
SW(14):                                 ! %BEGIN
%BEGIN
      PTYPE=0
      %IF LEVEL=1 %AND RLEVEL=0 %START
         %IF PARM_CPRMODE=0 %THEN %START
            RLEVEL=1; RBASE=1
            CURRINF_ENTRYAD=CA;              ! MAIN ENTRY
            PARM_CPRMODE=1
            RHEAD(-1,ADDR(MAINEP))
            N=0
         %FINISH %ELSE FAULT(58,0,0)
      %FINISH %ELSE %START
         SET LINE;                      ! SO 'ENTERED FROM LINE' IS OK
         RHEAD(-1,0)
      %FINISH
      RDISPLAY(-1)
%END
         ->CSSEXIT
!
SW(15):
                                        ! '%ON'(EVENT')(N)(NLIST)'%START'
      FAULT(57,0,0) %UNLESS LEVEL>=2
      FAULT(40,0,0) %IF CURRINF_NMDECS&1#0
      CURRINF_NMDECS=CURRINF_NMDECS!X'11';! NO MORE DECS AND IN ONCOND
      PB1(NOOP);                    ! GET PROGRAM MASK
!      DUMPRX(ST,0,0,RBASE,N+8);         ! AND SAVE IT
      PLABEL=PLABEL-1
      JJJ=PLABEL
      ENTER JUMP(15,JJJ,B'10');         ! JUMP ROUND ON BODY
!
      P=P+1; JJ=0;                      ! SET UP A BITMASK IN JJ
      %UNTIL A(P)=2 %CYCLE;             ! UNTIL NO MORE NLIST
         KK=-1; P=P+4
         FAULT(26,KK,0) %UNLESS INTEXP(KK,X'41')=0 %AND 1<=KK<=14
         JJ=JJ!1<<(KK-1)
      %REPEAT
      P=P+1
      KK=CA; PGLA(4,4,ADDR(CA))
!      RELOCATE(GLACA-4,KK,1);           ! ENTRY ADDRESS IN PLT
      CURRINF_ONWORD=JJ<<18!(GLACA-4)
!      DUMPM(STM,0,1,RBASE,N);           ! AND SAVE THEM
!      DUMPRX(LGR,1,0,RBASE,N+8);        ! RETRIEVE PROGRAM MASK
      PB1(NOOP);                     ! AND RESET IT
      CURRINF_ONINF=N; N=N+12
      OLDLINE=0
      CSTART(0,3)
      CURRINF_NMDECS=CURRINF_NMDECS!!X'10';! NOT IN ONCOND
      JJ=ENTER LAB(JJJ,B'111');         ! REPLACE ENVIRONMENT
      ->CSSEXIT
SW(16):  
%BEGIN;                                 ! %SWITCH (SWITCH LIST)
%INTEGER Q,RANGE,KKK,LB,UB,PP,D0,OPHEAD,V,R
      FAULT(57,0,0) %UNLESS LEVEL>=2
      Q=P
      PLABEL=PLABEL-1
      ENTER JUMP(15,PLABEL,0)
      %UNTIL A(Q)=2 %CYCLE;             ! UNTIL NO'REST OF SW LIST'
         P=P+3
         P=P+3 %WHILE A(P)=1
         P=P+4;                         ! TO P(+')
         KKK=INTEXP(LB,X'41');          ! EXTRACT LOWER BOUND
         P=P+3
         KKK=KKK!INTEXP(UB,X'41');      ! EXTRACT UPPER BOUND
         RANGE=(UB-LB+1)
         %IF RANGE<=0 %OR KKK#0 %START
            FAULT(38,1-RANGE,FROMAR2(Q+1))
            LB=0; UB=10; RANGE=11
         %FINISH
         PTYPE=X'56'+1<<8;              ! WORD LABEL ARRAY
         PP=P; P=Q+1
         %UNTIL A(P-1)=2 %CYCLE;       !  DOWN NAMELIST
            K=FROM AR2(P)
            P=P+3
            OPHEAD=0; R=LB
!
! SET UP A BIT LIST (96 BITS PER CELL) TO CHECK FOR SWITCH LABELS
! SET TWICE
!
            %UNTIL R>UB %CYCLE
               PUSH(OPHEAD,0,0,0)
               R=R+96
            %REPEAT
            %IF CA&1=0 %THEN PB1(NOOP)
            SNDISP=CA;                  ! OF CASE JUMP
            PB1(XJP)
            PWORD(LB)
            PWORD(UB)
            V=WORKA_PLABS(6)-CA
            PWORD(V);                   ! TO PLABS(6) IF BOUND FAULT
            D0=CA;                      ! START OF TABLE
            PUSH(OPHEAD,D0,LB,UB)
            KFORM=0; ACC=4
            J=1; STORE TAG(K,OPHEAD)
!
!THE TABLE WILL CONSIST OF RELATIVE DISPLACEMENTS FROM EACH ENTRY 
! TO THE LABEL POSN. SET ALL TO GO TO PLAB(6) INITIALLY
!
            V=V-2
            %CYCLE KKK=LB,1,UB
               PWORD(V)
               V=V-2
            %REPEAT
         %REPEAT;                       ! FOR ANY MORE NAMES IN NAMELIST
         Q=PP; P=Q
      %REPEAT;                          ! UNTIL A(Q)=2
      KKK=ENTER LAB(PLABEL,0);          ! COMPLETE JUMP AROUND TABLE
%END;->CSSEXIT
!
SW(17):       ->CSSEXIT
!
SW(12):                                ! '%OWN' (TYPE)(OWNDEC)
%BEGIN
!***********************************************************************
!*       INITIALISED DECLARATION GO INTO THE GLA OR GLA SYMBOL TABLES  *
!*       EXCEPT FOR CONST ARRAYS WHICH GO INTO THE CODE SYMBOL TABLES  *
!*       STRINGS AND ARRAYS HAVE A HEADER IN THE GLA. QPUT ARRANGES    *
!*       FOR THE LOADER TO RELOCATE THE HEADERS.                       *
!*       EXTERNALS ARE IDENTICAL WITH OWN BUT ALSO HAVE A DATA EP DEFN *
!*       IN THE LOAD DATA SO THEY CAN BE FOUND AT LOAD TIME            *
!*       EXTRINSICS HAVE A DATA REFERENCE AND A DUMMY HEADER IN THE GLA*
!*       THE LOADER USES THE FORMER TO RELOCATE THE LATTER.            *
!***********************************************************************
%ROUTINESPEC CLEAR(%INTEGER L)
%ROUTINESPEC STAG(%INTEGER J, DATALEN)
%ROUTINESPEC XTRACT CONST(%INTEGER CONTYPE, CONPREC)
%ROUTINESPEC INIT SPACE(%INTEGER A, B)
%HALFINTEGER AH1, AH2, AH3, AH4
%INTEGER LENGTH, PP, SIGN, FICONST, ICONST, TAGDISP, EPTYPE, EPDISP,
          AD, STALLOC, SPOINT, CONSTSFOUND, CPREC, EXTRN, NNAMES,  %C
         MARK, QPUTP, LB, CTYPE, CONSTP, FORMAT,DPTYPE,   %C
         DIMEN, SACC, TYPEP
%LONGREAL RCONST, FRCONST
%OWNLONGREAL ZERO=0
%STRING (255) SCONST, NAMTXT
%RECORD(LISTF)%NAME LCELL
%INTEGERNAME STPTR
      QPUTP=45;  STPTR==USTPTR;         ! NORMAL CASE GLA SYMBOLTABLES
!      FAULT(40,0,0) %IF NMDECS&1#0
      EXTRN=A(P+1)
      P=P+2
      %IF EXTRN>=4 %THEN EXTRN=0;       ! CONST & CONSTANT->0
      SNDISP=0
      CONSTS FOUND=0
      %IF EXTRN=0 %THEN QPUTP=44 %AND STPTR==SSTL
      CLT
!
! CHECK FOR %SPEC AND CHANGE EXTERNAL SPEC TO EXTRINSIC
!
      %IF A(P+2)=1 %START
         %IF EXTRN=2 %THEN EXTRN=3 %ELSE FAULT(46,0,0)
      %FINISH
      %IF 2<=EXTRN<=3 %AND ((A(P)=1 %AND A(P+1)#3) %OR %C
         (A(P)=2 %AND A(P+1)#2)) %THEN FAULT(46,0,0)
      LITL=EXTRN
      %IF LITL<=1 %THEN LITL=LITL!!1
      %IF A(P)=1 %THEN CQN(P+1) %ELSE ARR=1 %AND NAM=0
      %IF TYPE=5 %AND NAM=0 %AND (ACC<=0 %OR ACC>256) %THEN %C
         FAULT(70,ACC-1,0) %AND ACC=2
      STALLOC=ACC;                      ! ALLOCATION OF STORE FOR ITEM OR POINTER
      %IF TYPE=5 %THEN STALLOC=(STALLOC+1)&X'FFE'
      ROUT=0;  PACK(PTYPE); DPTYPE=PTYPE;! FOR DECLARATION
      %IF NAM#0 %START;                 ! OWN POINTERS
         %IF ARR#0 %THEN STALLOC=8 %ELSE STALLOC=4
      %FINISH %ELSE %START;             ! OWN VARS & ARRAYS
         ->NON SCALAR %IF ARR#0
      %FINISH
      P=P+2
      %UNTIL A(MARK)=2 %CYCLE;          ! UNTIL <RESTOFOWNDEC> NULL
         MARK=P+1+FROM AR2(P+1)
         PP=P+3;  P=PP+2;               ! PP ON FIRST NAME'
         K=FROM AR2(PP);                ! FOR ERROR MESSAGES RE CONST
         NAMTXT=STRING(WORKA_DICTBASE+WORD(K))
         %IF A(P)=1 %THEN NAMTXT<-STRING(ADDR(A(P+1))) %AND %C
            P=P+A(P+1)+1
         P=P+1;                         ! P ON CONST'
!
! OBTAIN THE INITIAL CONSTANT,ITS TYPE(CTYPE) AND SIGN(SIGN)
!
         ICONST=0;  FICONST=0
         RCONST=0;  FRCONST=0;  SCONST=""
         PTYPE=DPTYPE; UNPACK;          ! MAY HAVE BEEN CONSTANT EVALUATIONS
                                        ! WHICH HAVE CHANGED PTYPE
         SIGN=3;  CTYPE=TYPE;  CONSTSFOUND=0;  CPREC=PREC
         %IF TYPE=3 %THEN CTYPE=1;      ! RECS INITTED TO REPEATED BYTE
         %IF NAM#0 %THEN CTYPE=1 %AND CPREC=5
         P=P+1
         %IF A(P-1)=1 %THEN %START;     ! CONSTANT GIVEN
            XTRACT CONST(CTYPE,CPREC)
         %FINISH %ELSE %START
            WARN(7,K) %IF EXTRN=0;      ! %CONST NOT INITIALISED
         %FINISH
         J=0
         %IF NAM#0 %THEN %START;        ! OWNNAMES AND ARRAYNAMES
            AH1<-FICONST>>16
            AH2<-FICONST
            %IF ARR=0 %THEN %START
               %IF TYPE=5 %THEN STALLOC=6 %AND AH3=ACC-1
               PGLA(2,STALLOC,ADDR(AH1))
            %FINISH %ELSE %START;       ! ARRAYNAMES
               AH3=DOPE VECTOR(TYPE,ACC,-1,K,QQ,LB)>>1
               AH4=0
               %IF PARM_COMPILER#0 %AND LB#0 %THEN FAULT(99,0,0)
               %IF EXTRN#0 %THEN SNDISP=0 %ELSE %C
                  SNDISP=(SNDISP&X'3FFFF')>>2
               PGLA(4,STALLOC,ADDR(AH1))
               RELOCATE(32,GLACA-4,4)
            %FINISH
            TAGDISP=GLACA-STALLOC;  EPDISP=TAGDISP
            STAG(TAGDISP,STALLOC)
            P=MARK
            %CONTINUE
         %FINISH
         %IF EXTRN=3 %THEN %START;      ! EXTRINISIC
            PTYPE=PTYPE!X'400';         ! FORCE NAM=1 (IE VIA POINTER)
            AH3=0; AH2=0
            PGLA(4,4,ADDR(AH2))
            TAGDISP=GLACA-4
            GXREF(NAMTXT,2,2<<24,TAGDISP);! RELOCATE BY EXTERNAL
            STAG(TAGDISP,STALLOC)
            P=MARK
            %CONTINUE
         %FINISH
         %IF TYPE=5 %THEN %START;       ! STRING
            PTYPE=PTYPE!X'400';         ! FORCE NAM = 1
            AH1=STPTR>>1
            AH2=0;                      ! WILL HAVE SEGMENT NO
            AH3=ACC-1
            AD=ADDR(SCONST)
            %IF PARM_INHCODE=0 %START
               QPUT(QPUTP,STALLOC,STPTR,AD)
               %IF ONPERQ=NO %THEN QPUT(9,QPUTP-40,STPTR,STALLOC)
            %FINISH
                                        ! O/P STRING
            STPTR=(STPTR+STALLOC+1)&(-2)
            PGLA(2,6,ADDR(AH1))
            TAGDISP=GLACA-6
            RELOCATE(32,TAGDISP,QPUTP-40)
            EPTYPE=5;  EPDISP=AH1;      ! DATA IN GLA SYMBOL TABLES
         %FINISH
         %IF TYPE=3 %THEN %START;       ! RECORDS
            EPDISP=GLACA
            TAGDISP=EPDISP;             ! AND RELOCATE REL APPROPIATE AREA
            EPTYPE=2;                   ! DATA IN GLA TABLES
            I=0;  ICONST=ICONST&255
            ICONST=ICONST<<8!ICONST
            %WHILE I<STALLOC %CYCLE;    ! RECORDS INITIALISED AS REPEATED BYTE
               PGLA(2,2,ADDR(ICONST))
               I=I+2
            %REPEAT
         %FINISH
         %IF 1<=TYPE<=2 %START;         ! INTEGER & REAL
            %IF TYPE=2 %THEN %START
               AD=ADDR(FRCONST)+8-STALLOC
            %FINISH %ELSE %START;       ! INTEGER VARIABLES
               AD=ADDR(FICONST)
            %FINISH
            %IF EXTRN#0 %THEN %START
               %IF PARM_DCOMP#0 %THEN WRITE(FICONST,10)
                  %IF PREC=3 %THEN PGLA(2,2,AD) %ELSE %C
                     PGLA(ACC,ACC,AD)
               %FINISH
                                        ! PUT CONSTANT INTO GLA
            TAGDISP=GLACA-ACC;          ! OFFSET OF VAR FOR TAGS
            EPDISP=TAGDISP;             ! AND FOR ENTRY DEFN
            EPTYPE=2;                   ! DATA IN ADRESSABLE GLA
         %FINISH
         STAG(TAGDISP,ACC)
         %IF EXTRN=0=NAM %AND 1<=TYPE<=2 %START;! CONST = LITERAL
            LCELL==ASLIST(TAGS(K))
            %IF TYPE=1 %THEN LCELL_S2=ICONST %ELSE %C
               LONGREAL(ADDR(LCELL_S2))=RCONST
         %FINISH
         P=MARK
      %REPEAT
      ->BEND
NONSCALAR:                              ! OWN AND OWNRECORD ARRAYS
!***********************************************************************
!*       OWN ARRAYS CAN BE INITIALISED BUT ONLY ONE ARRAY CAN BE       *
!*       DECLARED IN A STATEMENT.(THANK HEAVENS!)                      *
!*       OWN RECORD ARRAYS ARE INITIALISED AS BYTE ARRAYS              *
!***********************************************************************
      P=P+1
      FORMAT=2-A(P)
      %IF FORMAT#0 %THEN ARR=3 %AND PACK(PTYPE)
      PP=P+2;  P=P+4;  NNAMES=1
      K=FROM AR2(PP)
      NAMTXT=STRING(WORKA_DICTBASE+WORD(K))
      SACC=ACC;  TYPEP=PTYPE
      AH3=DOPE VECTOR(TYPE,STALLOC,0,K,QQ,LB)>>1
      %IF SNDISP=-1 %THEN SNDISP=0;     ! BUM DOPE VECTOR
      SNDISP=(SNDISP&X'3FFFF')>>2;      ! AS WORD DISPLACEMENT
      DIMEN=J;                          ! SAVE NO OF DIMENESIONS
      ACC=SACC;  PTYPE=TYPEP;  UNPACK
      %IF LB=0 %AND FORMAT=0 %THEN ARR=2 %AND PACK(PTYPE)
      %IF TYPE=3 %THEN LENGTH=QQ %ELSE LENGTH=QQ//STALLOC;! NO OF ELEMENTS
      SPOINT=STPTR
      %IF FORMAT=0 %THEN %START
         %IF A(P)=1 %THEN P=P+1 %AND INIT SPACE(QQ,LENGTH)
      %FINISH
      %IF CONSTS FOUND=0 %THEN %START;  ! NO CONSTANTS GIVEN
                                        ! SO CLEAR AN AREA TO ZERO
         CONSTS FOUND=LENGTH
         CLEAR(QQ) %UNLESS LENGTH<1 %OR EXTRN=3 %OR FORMAT#0
      %FINISH %ELSE %START
         FAULT(49,0,K) %IF EXTRN=3 %OR FORMAT#0
      %FINISH
      %IF EXTRN=3 %THEN EPDISP=0 %ELSE EPDISP=SPOINT

! OUTPUT AN ARRAYHEAD INTO THE GLA RELATIVE TO THE START OF THE SYMBOL-
! TABLES IN WHICH THE ARRAY RESIDES.

      J=DIMEN;                          ! RESET DIMENSIONS AFTER INITTING
      AH1=EPDISP>>1
      AH2=0;                            ! WILL BE SEG NO
      AH4=0;                            ! WILL BE DV SEG NO
      PGLA(4,8,ADDR(AH1))
      TAGDISP=GLACA-8
      %IF EXTRN=3 %THEN %START;         ! EXTRINSIC ARRAYS
         GXREF(NAMTXT,2,2<<24,TAGDISP); ! RELOCATE ADDR(A(0))
      %FINISH %ELSE %START
         RELOCATE(32,TAGDISP,QPUTP-40)
      %FINISH
      RELOCATE(32,TAGDISP+4,4);         ! RELOCATE DV POINTER
      EPTYPE=5;                         ! DATA IN GLA SYMBOL TABLES
      STAG(TAGDISP,QQ)
      ->BEND
%ROUTINE INIT SPACE(%INTEGER SIZE, NELS)
!***********************************************************************
!*       P IS TO FIRST ENTRY FOR CONSTLIST                             *
!*    MAP SPACE ONTO WORKFILE END TO GIVE SANE ERROR MESSAGE IF        *
!*    THERE WAS NOT ENOUGH SPACE                                       *
!***********************************************************************
%INTEGER RF, I, II, ELSIZE, AD, SPP, LENGTH, SAVER, WRIT
%BYTEINTEGERARRAYNAME SP
%BYTEINTEGERARRAYFORMAT SPF(0:4096+256)
      SAVER=R;  R=R+(4096+256)
      %IF R>ARSIZE %THEN FAULT(102, WORKA_WKFILEK,0)
      SP==ARRAY(ADDR(A(SAVER)),SPF)
      %IF TYPE=1 %THEN AD=ADDR(FICONST)
      %IF TYPE=2 %THEN AD=ADDR(FRCONST)+8-ACC
      %IF TYPE=3 %THEN AD=ADDR(ICONST)+3
      %IF TYPE=5 %THEN AD=ADDR(SCONST)
      SPP=0;  WRIT=0
      ELSIZE=SIZE//NELS
      %UNTIL A(P-1)=2 %CYCLE
         XTRACT CONST(TYPE,PREC)
         %IF A(P)=1 %START;             ! REPITITION FACTOR
            P=P+2
            %IF A(P-1)=2 %THEN RF=NELS-CONSTS FOUND %ELSE %START
               P=P+2
               %IF INTEXP(RF,X'41')#0 %THEN FAULT(41,0,0) %AND RF=1
            %FINISH
            P=P+1
         %FINISH %ELSE RF=1 %AND P=P+2
         FAULT(42,RF,0) %IF RF<=0
         %CYCLE I=RF,-1,1
            %IF TYPE=1=ACC %OR TYPE=3 %START
               %CYCLE II=0,1,ELSIZE-1
                  %IF CONSTS FOUND<=NELS %THEN SP(SPP)<- %C
                     ICONST %AND SPP=SPP+1
               %REPEAT
            %FINISH %ELSE %START
               %CYCLE II=0,2,ELSIZE-2
                  %IF CONSTS FOUND<=NELS %THEN %C
                     HALFINTEGER(ADDR(SP(SPP)))=HALFINTEGER(AD+II) %C
                     %AND SPP=SPP+2
               %REPEAT
            %FINISH
            CONSTS FOUND=CONSTS FOUND+1
            %IF SPP>=4096 %START;       ! EMPTY BUFFER
               %IF PARM_INHCODE=0 %THEN %START
                  QPUT(QPUTP,SPP,STPTR+WRIT,ADDR(SP(0)))
                  %IF ONPERQ=NO %AND (TYPE=5 %OR (TYPE=1 %AND PREC=3))%C
                     %THEN QPUT(9,QPUTP-40,STPTR+WRIT,SPP)
               %FINISH
               WRIT=WRIT+SPP
               SPP=0
            %FINISH
         %REPEAT
      %REPEAT;                          ! UNTIL P<ROCL>=%NULL
      %IF CONSTS FOUND#NELS %THEN FAULT(45,CONSTS FOUND,NELS)
      LENGTH=(SIZE+3)&(-4)
      %IF PARM_INHCODE=0 %START
      QPUT(QPUTP,LENGTH-WRIT,STPTR+WRIT,ADDR(SP(0)))
         %IF ONPERQ=NO %AND(TYPE=5 %OR(TYPE=1 %AND PREC=3)) %C
            %THEN QPUT(9,QPUTP-40,STPTR+WRIT,LENGTH-WRIT)
      %FINISH
      STPTR=STPTR+LENGTH
      R=SAVER
%END
%ROUTINE CLEAR(%INTEGER LENGTH)
      STPTR=(STPTR+3)&(-4)
      LENGTH=(LENGTH+3)&(-4)
      QPUT(QPUTP,LENGTH<<14!4,STPTR,ADDR(ZERO)) %IF PARM_INHCODE=0
      STPTR=STPTR+LENGTH
%END
%ROUTINE STAG(%INTEGER J, DATALEN)
      %IF EXTRN=2 %THEN QPUT(14,EPTYPE<<24!DATALEN,EPDISP,ADDR( %C
         NAMTXT))
      RBASE=0
      STORE TAG(K,J)
      RBASE=RLEVEL
%END
%ROUTINE XTRACT CONST(%INTEGER CONTYPE, CONPREC)
!***********************************************************************
!*       P POINTS TO P<+'> OF <+'><OPERNAD><RESTOFEXPR>  AND IS UPDATED*
!*       THE CONST IS CONVERTED TO REQUIRED FORM AND IF INTEGER        *
!*       IS LEFT IN ICONST, IF REAL IN RCONST AND IF STRING IN SCONST  *
!***********************************************************************
%INTEGER LENGTH, STYPE, SACC, CPREC, MODE, I
%LONGREAL LRCONST;                    ! TO ASSIST IN FORMAT CHANGES
      STYPE=PTYPE;  SACC=ACC;           ! MAY BE CHANGED IF CONST IS EXPR
      %IF CONTYPE=5 %THEN %START
         CTYPE=5
         %IF A(P)=4 %AND A(P+1)=2 %AND A(P+2)=X'35' %C
            %AND A(P+A(P+3)+4)=2 %START
            SCONST=STRING(ADDR(A(P+3)))
            LENGTH=A(P+3)
            P=P+A(P+3)+5
         %FINISH %ELSE %START
            FAULT(44,CONSTS FOUND,K);  SCONST=""
            LENGTH=0;  P=P-3;  SKIP EXP
         %FINISH
      %FINISH %ELSE %START
         MODE=CONPREC<<4!CONTYPE
         %IF CONPREC<5 %THEN MODE=CONTYPE!X'50'
         CONSTP=CONSTEXP(MODE)
         %IF CONSTP=0 %THEN FAULT(41,0,0) %AND CONSTP=ADDR(ZERO)
                                        ! CANT EVALUATE EXPT
         CTYPE=TYPE;  CPREC=PREC
         %IF CTYPE=1 %THEN %START
            ICONST=INTEGER(CONSTP)
         %FINISH %ELSE %START
            RCONST=LONGREAL(CONSTP)
         %FINISH
      %FINISH
      PTYPE=STYPE;  UNPACK;  ACC=SACC

! FAULT ANY OBVIOUS ERRORS IE:-
! CONSTANT FOR EXTRINSIC OR INCOMPATIBLE TYPE OR STRING TOO LONG

      %IF EXTRN=3 %THEN FAULT(49,0,K) %AND %RETURN
      %IF (CTYPE=5 %AND LENGTH>=ACC) %C
         %OR (CONTYPE=1 %AND ((CONPREC=3 %AND ICONST>255) %C
         %OR (CONPREC=4 %AND ICONST>X'FFFF'))) %C
         %THEN FAULT(44,CONSTS FOUND,K)
!
! IF CROSS COMPILING THEN A CONSTANT FORMAT CHANGE IS NEED FROM
! IBM&ICL FORM TO PERQ FORM. IF ON PERQ FORMAT IS CORRECT
!
      FICONST=ICONST; FRCONST=RCONST
      %IF ON PERQ=NO %THEN %START
         FICONST=(ICONST>>16)!(ICONST<<16)
         %IF CONPREC=6 %THEN LRCONST=ICLLONGREALTOPERQ(RCONST) %ELSE %C
            LRCONST=ICLREALTOPERQ(RCONST)
         %CYCLE I=0,2,6
            HALFINTEGER(ADDR(FRCONST)+6-I)=HALFINTEGER(ADDR(LRCONST)+I)
         %REPEAT
      %FINISH
%END
BEND: %END;  ->CSSEXIT
SW(18):
         ABORT
SW(10):
         %BEGIN;                       ! %RECORDFORMAT (RDECLN)
%INTEGER NAME,OPHEAD,OPBOT,NLIST,MRL,CELLREF
%RECORD(LISTF)%NAME LCELL,FRCELL
      SNDISP=0
      NAME=FROM AR2(P+1); P=P+3
      COPY TAG(NAME)
      %UNLESS PTYPE=4 %AND J=15 %AND OLDI=LEVEL %START
         KFORM=0
         PUSH(KFORM,0,0,0)
         ACC=X'7FFF'
         PTYPE=4; J=0
         STORETAG(NAME,KFORM);          ! IN CASE OF REFS IN FORMAT
      %FINISH%ELSE %START
         LCELL==ASLIST(TAGS(NAME))
         LCELL_S1=LCELL_S1&X'FFFFFFF0';! J=15 TO J=0
      %FINISH
      LCELL==ASLIST(KFORM)
      OPHEAD=0; OPBOT=0
      NLIST=0; MRL=0
      INAFORMAT=1
      CRFORMAT(OPHEAD,OPBOT,NLIST,MRL,X'80000000')
      INAFORMAT=0
      CLEAR LIST(NLIST)
!
! IN CASE OF FORWARD REFS COPY TOP CELL OF FORMAT CHAIN INTO DUMMY
! SET UP BEFORE CALL OF CRFORMAT. ALSO RESET J&ACC TO CORRECT VALUE
!
      %WHILE LCELL_S3#0 %CYCLE;         ! THROUGH FORWARD REFS
         POP(LCELL_S3,CELLREF,I,I)
         FRCELL==ASLIST(CELLREF)
         FRCELL_S1=FRCELL_S1&X'FFFFFFF0';! SET J BACK TO 0
         FRCELL_S2=FRCELL_S2&X'FFFF0000'!ACC;! ACC TO CORRECT VALUE
      %REPEAT
      POP(OPHEAD,LCELL_S1,LCELL_S2,LCELL_S3)
      LCELL_LINK=OPHEAD
      LCELL==ASLIST(TAGS(NAME))
      LCELL_S2=LCELL_S2&X'FFFF0000'!ACC
%END;->CSSEXIT
!
SW(19):
                                        ! '*' (UCI) (S)
      FAULT(57,0,0) %UNLESS LEVEL>=2
%BEGIN
!***********************************************************************
!*       COMPILE USERCODE INSTRUCTION. MOST WORK IS DONE BY HAIRY      *
!*       BUILT-IN PHRASE IN COMPARE. SINCE ALMOST ANYTHING IS LEGAL    *
!*       IN USERCODE THIS BLOCK HAS ONLT TO ASSEMBLE AND PLANT THE     *
!*       THE INSTRUCTION.                                              *
!***********************************************************************
%SWITCH UCITYPE(1:4),QINST(1:7)
%INTEGER ALT,AALT,FNAME,OPTINC,OPC,KK,VAL1,VAL2,I,TR
      ALT=A(P+1); P=P+2
      ->UCITYPE(ALT)
UCITYPE(1):                             ! **@'(NAME)(OPTINC)
      AALT=A(P);                        ! ALT OF @'
      FNAME=A(P+1)<<8!A(P+2)
      P=P+3; OPTINC=0
      %IF A(P)#3 %START;                ! THERE IS AN OPTINC
         OPTINC=FROMAR2(P+1)
         %IF A(P)=2 %THEN OPTINC=-OPTINC
      %FINISH
      COPY TAG(FNAME)
      FAULT(97,FNAME,0) %IF TYPE>=6 %OR ROUT#0
      %IF AALT=1 %THEN DFETCHAD(NO,I,K+OPTINC) %ELSE %C
         %IF AALT=2 %THEN DSTORE(2,I,K+OPTINC) %ELSE %C
         DFETCH(2,I,K+OPTINC)
      ->BEND
UCITYPE(2):                             ! PUT (HEX HALFWORD)
      TYPE=A(P)
      PREC=TYPE>>4; TYPE=TYPE&7
      FAULT(97,0,0) %UNLESS TYPE=1 %AND PREC<6
      %IF PREC=5 %THEN P=P+2
      KK=FROM AR2(P+1); I=UCB2
      ->OTRIP
UCITYPE(4):                             ! CNOP
      I=UCNOP; KK=FROM AR2(P)
      ->OTRIP
UCITYPE(3):                             ! ASSEMBLER
      AALT=A(P); P=P+1
      OPC=A(P); P=P+4
      %IF AALT>1 %THEN %START
         KK=INTEXP(VAL1,X'41')
         FAULT(96,0,1) %UNLESS KK=0
%FINISH
      %IF AALT>=5 %START
         P=P+3
         KK=INTEXP(VAL2,X'41')
         FAULT(96,0,2) %UNLESS KK=0
      %FINISH
      ->QINST(AALT)
QINST(1):                               ! ONE BYTE INSTRUCTION
      I=UCB1; KK=OPC; ->OTRIP
QINST(2):                               ! UNSIGNED BYTE OPERAND
      FAULT(96,0,1) %UNLESS 0<=VAL1<=255
      I=UCB2; KK=OPC<<8!VAL1
      ->OTRIP
QINST(3):                               ! SIGNED BYTE OPERAND
      FAULT(96,0,1) %UNLESS -128<=VAL1<=127
      I=UCB2; KK=OPC<<8!(VAL1&255)
      ->OTRIP
QINST(4):                               ! SIGNED WORD OPERAND
      FAULT(96,0,1) %UNLESS IMOD(VAL1)<=X'7FFF'
      I=UCW; KK=OPC<<16!(VAL1&X'FFFF')
      ->OTRIP
QINST(5):                               ! 2 UNSIGNED BYTE OPERANDS
      FAULT(96,0,1) %UNLESS 0<=VAL1<=255
      FAULT(96,0,2) %UNLESS 0<=VAL2<=255
      I=UCB3; KK=OPC<<16!VAL1<<8!VAL2
      ->OTRIP
QINST(6):                               ! BYTE & WORD OPERANDS
      FAULT(96,0,1) %UNLESS 0<=VAL1<=255
      FAULT(96,0,2) %UNLESS IMOD(VAL2)<=X'7FFFF'
      I=UCBW; KK=OPC<<24!VAL1<<16!(VAL2&X'FFFF')
      ->OTRIP
OTRIP:
      TR=UCONSTTRIP(I,0,DONT OPT,KK)
BEND:
%END
         ->CSSEXIT
SW(20):
                                        ! '%TRUSTEDPROGRAM'
         PARM_COMPILER=1 %IF PARM_ARR=0 %AND PARM_CHK=0; ->CSSEXIT
SW(21):                                 ! '%MAINEP'(NAME)
         KK=FROM AR2(P+1)
         FAULT(97,0,0) %UNLESS PARM_CPRMODE=0
         MAINEP<-STRING(WORKA_DICTBASE+WORD(KK))
         ->CSSEXIT
%INTEGERFN CFORMATREF
!***********************************************************************
!*    P IS TO ALT OF FORMAT REF                                        *
!*    P<FORMTAREF>::=(NAME),(RFDEC)(RESTOFRFDEC)(ALTRFDEC)             *
!*    RETURNS CELL NO OF TOP CELL OF THE FORMATLIST                    *
!***********************************************************************
%INTEGER FNAM,OPHEAD,OPBOT,NHEAD,MRL
%RECORD(LISTF)%NAME LCELL
      %IF A(P)=1 %START;                ! A RECORD OF RECORDFORMAT NAME
         FNAM=FROM AR2(P+1)
         P=P+3
         COPY TAG(FNAM)
         %IF 3<=TYPE<=4 %THEN %RESULT=KFORM
         %IF INAFORMAT#0 %AND OLDI#LEVEL %START
            KFORM=0; SNDISP=0;ACC=X'7FFF'
            PTYPE=4; J=15
            PUSH(KFORM,0,0,0)
            STORE TAG(FNAM,KFORM)
            %RESULT=KFORM
         %FINISH
         FAULT(62,0,FNAM);             ! NOT A RECORD OF FORMAT NAME
         ACC=8;                         ! GUESS A RECORD SIZE
         %RESULT=DUMMY FORMAT
      %FINISH
                                        ! FORMAT ACTUALLY SPECIFIED
      P=P+1
      OPHEAD=0; OPBOT=0
      NHEAD=0; MRL=0
      CRFORMAT(OPHEAD,OPBOT,NHEAD,MRL,X'80000000')
      CLEAR LIST(NHEAD)
      %IF CURRINF_UNATT FORMATS#0 %START
         LCELL==ASLIST(CURRINF_UNATT FORMATS)
         %IF LCELL_S2=0 %THEN LCELL_S2=OPHEAD %AND %RESULT=OPHEAD
         %IF LCELL_S3=0 %THEN LCELL_S3=OPHEAD %AND %RESULT=OPHEAD
      %FINISH
      PUSH(CURRINF_UNATT FORMATS,OPHEAD,0,0)
      %RESULT=OPHEAD
%END

%ROUTINE CRFORMAT(%INTEGERNAME OPHEAD, OPBOT, NLIST, MRL, %INTEGER INIT)
!***********************************************************************
!*       CONVERTS A RECORDFORMAT STATEMENT TO A LIST HEADED BY OPHEAD  *
!*       FORMAT OF AN ENTRY.                                           *
!*       S1=SUBNAME<<20!PTYPE<<4!J                                     *
!*       S2,S3=4  16 BIT DISPLACEMENTS  D2,ACC,D1,KFORM                *
!*       NORMALLY D1=RECORD RELATIVE DISPLACEMENT AND ACC=LMAX(STRINGS)*
!*       FOR ARRAYS D2=FIRST ELEMENT DISPLACEMENT AND D1=DISPLACEMENT  *
!*       OF RECORD RELATIVE ARRAYHEAD IN THE GLA                       *
!*       KFORM IS ONLY USED FOR RECORDS AND POINTS TO THE FORMAT       *
!*       ON EXIT ACC HAS THE RECORD SIZE ROUNDED UP TO THE BOUNDARY    *
!*       REQUIRED BY ITS LARGEST COMPONENT                             *
!***********************************************************************
%INTEGER D1, D2, FORM, RL, STALLOC, INC, Q, R, RFD, LB, TYPEP, SACC
%HALFINTEGER A0, A1, A2, A3
%ROUTINESPEC SN(%INTEGER Q)
%ROUTINESPEC ROUND
      FORM=0;  ACC=0
      INC=INIT&X'FFFF';                 ! INC COUNTS DOWN RECORD
      %CYCLE
         ROUT=0;  LITL=0;  NAM=0;  RFD=A(P)
         P=P+1
         %IF RFD=1 %THEN %START
            CLT
            FORM=KFORM
            STALLOC=ACC
            %IF PTYPE=X'35' %THEN STALLOC=(STALLOC+1)&(-2)
            P=P+1
            %IF A(P-1)=1 %START
                                        ! (TYPE) (QNAME')(NAMELIST)
               FORM=KFORM
               CQN(P);  P=P+1
               %IF NAM=1 %THEN %START
                  STALLOC=4
                  %IF TYPE=5 %OR(TYPE=1 %AND PREC=3) %THEN STALLOC=6
                  %IF ARR#0 %THEN STALLOC=8
               %FINISH
               PACK(PTYPE);  D2=0
               %IF STALLOC=1 %THEN RL=0 %ELSE RL=1
               ROUND;  J=0
               %UNTIL A(P-1)=2 %CYCLE
                  D1=INC;  SN(P)
                  P=P+3;  INC=INC+STALLOC
               %REPEAT
            %FINISH %ELSE %START
                                        ! (TYPE)%ARRAY(NAMELIST)(BPAIR)
               Q=P+1;  ARR=1;  PACK(PTYPE)
               %CYCLE
                  P=Q
                  P=P+3 %UNTIL A(P-1)=2
                  TYPEP=PTYPE;  SACC=ACC
                  A2=DOPE VECTOR(TYPE,ACC,0,FROMAR2(Q)>>1,R,LB)>>1
                                        ! DOPE VECTOR INTO SHAREABLE S.T.
                  ACC=SACC;  PTYPE=TYPEP;  UNPACK
                  RL=1
                  ROUND
                  %CYCLE
                     A0=INC>>1
                     A1=0
                     A3=0
                     PGLA(2,8,ADDR(A0))
                     D1=GLACA-8
                     RELOCATE(32,D1+4,4);   ! RELOCATE DV POINTER
                     D2=INC
                     SN(Q);  INC=INC+R
                     Q=Q+3
                  %REPEAT %UNTIL A(Q-1)=2;! TILL NAMELIST NULL
                  P=P+1;  Q=P+1
               %REPEAT %UNTIL A(P-1)=2; ! UNTIL <RESTOFARRAYLIST> NULL
            %FINISH
         %FINISH %ELSE %START
                                        ! (FORMAT)
            CRFORMAT(OPHEAD,OPBOT,NLIST,MRL,INC)
            INC=ACC
         %FINISH
         P=P+1
      %REPEAT %UNTIL A(P-1)=2;         ! UNTIL <RESTOFRFDEC> NULL
                                        ! FINISH OFF
      %IF A(P)=1 %START;                ! WHILE %OR CLAUSES
         P=P+1
         CRFORMAT(OPHEAD,OPBOT,NLIST,MRL,INIT&X'FFFF')
         %IF ACC>INC %THEN INC=ACC
      %FINISH %ELSE P=P+1
      %IF INIT<0 %THEN RL=MRL %AND  ROUND
      ACC=INC;                          ! SIZE ROUNDED APPROPRIATELY
      FAULT(63,X'7FFF',0) %UNLESS INC<=X'7FFF'
      %RETURN
%ROUTINE SN(%INTEGER Q)
!***********************************************************************
!*       CHECK THE SUBNAME HAS NOT BEEN USED BEFORE IN THIS FORMAT     *
!*       AND ENTER IT WITH ITS DESCRIPTORS INTO THE LIST.              *
!***********************************************************************
      FNAME=FROM AR2(Q)
      FAULT(61,0,FNAME) %UNLESS FIND(FNAME,NLIST)=-1
      BINSERT(OPHEAD,OPBOT,FNAME<<20!PTYPE<<4!J,D2<<16!ACC,D1<< %C
         16!FORM)
      PUSH(NLIST,0,FNAME,0)
      %IF PTYPE=X'433' %AND ACC=X'7FFF' %THEN %C
         PUSH(ASLIST(FORM)_S3,OPBOT,0,0);! NOTE FORWARD REFERENCE
%END
%ROUTINE ROUND
      MRL=RL %IF RL>MRL
      INC=INC+1 %WHILE INC&RL#0
%END
%END;                                   ! OF ROUTINE CRFORMAT
%INTEGERFN DISPLACEMENT(%INTEGER LINK)
!***********************************************************************
!*         SEARCH A FORMAT LIST FOR A SUBNAME                          *
!*      A(P) HAS ENAME--LINK IS HEAD OF RFORMAT LIST. RESULT IS DISP   *
!*      FROM START OF RECORD                                           *
!***********************************************************************
%RECORD(LISTF)%NAME FCELL,PCELL,LCELL
%INTEGER RR,II,ENAME,CELL
      ENAME=A(P)<<8+A(P+1); CELL=0
      %IF LINK#0 %THEN %START;          ! CHK RECORDSPEC NOT OMITTED
         FCELL==ASLIST(LINK);           ! ONTO FIRST CELL
         CELL=LINK; II=-1; ACC=-1
         %WHILE LINK>0 %CYCLE
            LCELL==ASLIST(LINK)
            %IF LCELL_S1>>20=ENAME %START;! RIGHT SUBNAME LOCATED
               TCELL=LINK
               RR=LCELL_S1
               SNDISP=LCELL_S2
               K=LCELL_S3
               J=RR&15; PTYPE=RR>>4&X'FFFF'
               ACC=SNDISP&X'FFFF'; SNDISP=SNDISP&X'FFFF0000'//X'10000'
               KFORM=K&X'FFFF'; K=K>>16
               %IF LINK#CELL %START;    ! NOT TOP CELL OF FORMAT
                  PCELL_LINK=LCELL_LINK
                  LCELL_LINK=FCELL_LINK
                  FCELL_LINK=LINK
               %FINISH;                 ! ARRANGING LIST WITH THIS SUBNAME
                                        ! NEXT TO THE TOP
               %RESULT=K
            %FINISH
            PCELL==LCELL
            LINK=LCELL_LINK
         %REPEAT
      %FINISH
      FAULT(65,0,ENAME)
      %IF CELL>0 %THEN %C
         PUSH(ASLIST(CELL)_LINK,ENAME<<20!7<<4,0,0)
      PTYPE=X'57'; TCELL=0
      %RESULT=-1
%END
%INTEGERFN COPY RECORD TAG(%INTEGERNAME SUBS)
!***********************************************************************
!*       PRODUCE PTYPE ETC FOR A COMPOUND NAME BY CHAINING DOWN ONE    *
!*       ONE OR MORE RECORD FORMAT LISTS. ON EXIT RESULT =0 IF NO      *
!*       SUBNAME FOUND OR SUBNAME IS OF TYPE RECORD WITH NO FURTHER    *
!*       SUBNAME ATTACHED. RESULT#0 IF BONE-FIDE SUBNAME LOCATED       *
!*       ON ENTRY KFORM HAS POINTER TO THE (FIRST ) FORMAT LIST AND    *
!*       P POINTS TO THE A.R. ENTRY FOR (FIRST) ENAME                  *
!***********************************************************************
%INTEGER Q,FNAME
      SUBS=0
      %UNTIL TYPE#3 %CYCLE
         FNAME=KFORM
         P=P+2; SKIP APP
         %RESULT=0 %IF A(P)=2 %OR FNAME<=0;! NO (FURTHER) ENAME
         SUBS=SUBS+1
         P=P+1; Q=DISPLACEMENT (FNAME)
         UNPACK
      %REPEAT
      %RESULT=Q+1;                      ! GIVES 0 IF SUBNAME NOT KNOWN
%END
%ROUTINE CRNAME(%INTEGER Z,MODE,BS,DP,%INTEGERNAME NAMEP)
!***********************************************************************
!*       DEAL WITH RECORD ELEMENT NAMES.Z AS FOR CNAME.CLINK=TAGS(RN)  *
!*       MODE=ACCESS FOR RECORD(NOT THE ELEMENT!)                      *
!*       ON EXIT BASE,AREA & DISP POINT TO REQUIRED ELEMENT            *
!*       RECURSIVE CALL IS NEEDED TO DEAL WITH RECORDS IN RECORDS      *
!*       DEPTH SHEWS  RECURSIVE LEVELS- NEEDED TO AVOID MIS SETTING    *
!*       REGISTER IN USE IF RECORDNAME IN RECORD HAS THE SAME NAME AS  *
!*       A GENUINE RECORD NAME.                                        *
!***********************************************************************
%INTEGER DEPTH,FNAME
%ROUTINESPEC CENAME(%INTEGER MODE,FNAME,BS,DP,XD)
         DEPTH=0
         FNAME=KFORM;                  ! POINTER TO FORMAT
         %IF ARR=0 %OR (Z=6 %AND A(P+2)=2) %START;! SIMPLE RECORD
            %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
            CENAME(MODE,FNAME,BS,DP,0)
         %FINISH %ELSE %START
            CANAME(Z,ARR,BS,DP)
            NAMEP=0
            CENAME(ACCESS,FNAME,BASE,DISP,0)
         %FINISH; %RETURN
!
%ROUTINE CENAME(%INTEGER MODE,FNAME,BS,DP,XD)
!***********************************************************************
!*       FINDS OUT ABOUT SUBNAME AND ACTS ACCORDINGLY.MOSTLY ACTION    *
!*       CONSISTS OF UPPING XD BY OFFSET OF THE SUBNAME BUT IS VERY    *
!*       HAIRY FOR RECORDS IN RECORDS ETC                              *
!*       MODE IS ACCESS FOR THE RECORD                                 *
!***********************************************************************
%ROUTINESPEC FETCH RAD
%ROUTINESPEC LOCALISE(%INTEGER SIZE)
%INTEGER Q,QQ,D,C,W
      DEPTH=DEPTH+1
      %IF A(P)=2 %THEN %START;          ! ENAME MISSING
         ACCESS=MODE; XDISP=XD
         BASE=BS; DISP=DP;              ! FOR POINTER
         %IF Z<14 %THEN %START;         ! NOT A RECORD OPERATION
            %UNLESS 3<=Z<=4 %OR Z=6 %START;   ! ADDR(RECORD)
               FAULT(64,0,NAMEP&X'FFFF'); BASE=RBASE
               DISP=0; ACCESS=0; PTYPE=X'51'; UNPACK
            %FINISH
         %FINISH
         %RETURN
      %FINISH
      P=P+1;                            ! FIND OUT ABOUT SUBNAME
      Q=DISPLACEMENT(FNAME);            ! TCELL POINTS TO CELL HOLDING
      UNPACK;                           ! INFO ABOUT THE SUBNAME
      %IF Q=-1=ACC %OR PTYPE=X'57' %START;  ! WRONG SUBNAME(HAS BEEN FAULTED)
         P=P+2; SKIP APP; P=P-3
         ACCESS=0; BASE=RBASE; DISP=0
         %RETURN
      %FINISH
      NAMEP=(A(P)<<8!A(P+1))<<16!NAMEP; ! NAMEP=-1 UNALTERED !
      ->AE %IF ARR=1;                   ! ARRAYS INCLUDING RECORDARRAYS
      %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
      %IF TYPE<=2 %OR TYPE=5 %OR %C
            (TYPE=3 %AND A(P)=2 %AND (3<=Z<=4 %OR Z=6)) %START
         ACCESS=MODE+4+4*NAM; BASE=BS;
         DISP=DP; XDISP=XD+Q
         %RETURN
      %FINISH
!
! NOW CODING BECOMES HAIRY:- STILL LEFT ARE
! A) RECORDS IN RECORDS   Q POINTS TO SECONDARY RECORD
! B) RECORDNAMES IN RECORDS   Q HAS OFF-SET OF A POINTER
! C) RECORDARRAYNAMES IN RECORDS   Q HAS OFF-SET A HEADER IN RECORD
! D) RECORDARRAYS IN RECORDS   NOT YET ALLOWED
!    Q WOULD HAVE OFF-SET OF A RECORD RELATIVE HEADER IN THE GLA
!
      XD=XD+Q
      NAMEP=-1
      %IF NAM=1 %THEN %START
         %IF MODE=0 %START
            DP=DP+XD; XD=0; MODE=2
         %FINISH %ELSE %START
            LOCALISE(4);                ! PICK UP RECNAME DESCR &STCK
            DP=DISP; BS=BASE
         %FINISH
      %FINISH
      CENAME(MODE,KFORM,BS,DP,XD)
      %RETURN
AE:                                     ! ARRAYS AND ARRAYNAMES AS ELEMEN
      FROM123(TCELL,Q,SNDISP,K)
      ACC=SNDISP&X'FFFF'; SNDISP=SNDISP&X'FFFF0000'//X'10000'
      KFORM=K&X'FFFF'; K=K>>16
      C=ACC; D=SNDISP; Q=K; QQ=KFORM
      %IF (Z=6 %OR Z>=11) %AND A(P+2)=2 %START;! 'GET ARRAYHEAD' CALL
            P=P+3
         %IF NAM=1 %THEN %START
            ACCESS=MODE+8; BASE=BS
            DISP=DP; XDISP=XD+Q
            NAMEOP(6,8,NAMEP);          ! PTR TO HEAD
            %IF Z=12 %THEN PB1(TLATE1) %AND PB2(ROPS,37)
            %RETURN
         %FINISH
!
! PASSING AN ARRAY IN A RECORD BY NAME MUST CONSTRUCT PROPER ARRAYHEAD
! FROM THE RECORD RELATIVE ONE AT Q(GLA)
!
         NAMEP=-1
         FETCH RAD
         ACCESS=2;
         DFETCHAD(NO,0,Q)
         PB2(ROPS,37);                  ! HEAD TO ESTACK
         CREATE AH(1)
      %FINISH %ELSE %START;             ! ARRAY ELEMENTS IN RECORDS
         NAMEP=-1
         %IF NAM=1 %THEN %START;        ! ARRAYNAMES-FULLHEAD IN RECORD
            XD=XD+Q
            LOCALISE(8);                ! MOVE HEAD UNDER LNB
            D=DISP
            CANAME(Z,3,BASE,DISP);      ! ARRAY MODE SETS DISP,AREA&BASE
            BASE=RBASE; DISP=D;         ! ONLY NEEDED FOR STRINGARRAYNAMES
         %FINISH %ELSE %START;          ! ARRAY RELATIVE HEAD IN GLA
            FETCH RAD;                  ! 32 BIT ADDR TO ETOS
            CANAME(Z,3,0,Q);            ! RECORD REL ARRAY ACCESS
                                        ! CAN RETURN ACCESS=1 OR 3 ONLY
            %IF PTYPE&255=X'31' %THEN PB1(MMS);! REMOVE OFFSET BYTE
            PB2(LOPS,2);                ! ADD 2 32 BIT POINTERS
            %IF PTYPE&255=X'31' %THEN PB1(MES)
         %FINISH
         XDISP=XD
         %IF TYPE=3 %THEN CENAME(ACCESS,QQ,BASE,DISP,XD)
      %FINISH
      ACC=C;                            ! NEEDED FOR STRING ARRAYS
      %RETURN
%ROUTINE FETCH RAD
!***********************************************************************
!*       SET ACC TO 32 BIT ADDRESS OF RECORD.                          *
!***********************************************************************
%INTEGER PRECP
         ACCESS=MODE+4
         BASE=BS
         DISP=DP; XDISP=XD
         PRECP=PREC; PREC=5
         NAMEOP(3,4,-1)
         PREC=PRECP;                    ! ENSURE 32BIT PICKUP
         %END
%ROUTINE LOCALISE(%INTEGER SIZE)
!***********************************************************************
!*       REMOVES A POINTER OR ARRAYHEAD FROM A RECORD AND STORES       *
!*       IT IN A TEMPORARY UNDER LNB.                                  *
!***********************************************************************
%INTEGER HOLE,PRECP
      ACCESS=MODE+4
      BASE=BS; DISP=DP
      XDISP=XD
      PRECP=PREC; PREC=5
      NAMEOP(3,SIZE,-1)
      PREC=PRECP
      GET WSP(HOLE,SIZE>>1)
      %IF SIZE=8 %START;                ! LOCALISE ARRAY HEAD
         PB1(TLATE1)
         PB2(ROPS,37)
      %FINISH
      DSTORE(SIZE,RBASE,HOLE)
      MODE=2
      BASE=RBASE; DISP=HOLE; XD=0
%END;                                   ! OF ROUTINE LOCALISE
%END;                                   ! OF ROUTINE CENAME
%END;                                   ! OF ROUTINE CRNAME
%ROUTINE CSTREXP(%INTEGER MODE)
!***********************************************************************
!*       PLANT IN-LINE CODE FOR CONCATENATION. A WORK AREA IN THE      *
!*       CURRENT STACK FRAME IS USUALLY REQUIRED.                      *
!*       ON ENTRY:-                                                    *
!*       MODE=0    NORMAL. WK AREA NOT USED FOR ONE OPERAND EXPSSNS    *
!*       MODE=1     STRING MUST GO TO WORK AREA                        *
!*       2**5 BIT OF MODE SET IF FULL VIRTUAL ADDRESS REQUIRED         *
!*       2**4 BIT OF MODE IS SET IF WK-AREA NOT TO BE FREED ON EXIT    *
!*       ON EXIT:-                                                     *
!*       VALUE#0 %IF RESULT IN A WORK AREA(CCOND MUST KNOW)            *
!***********************************************************************
%INTEGER PP,WKAREA,DOTS,ERR,KEEPWA,FNAM,I,ENDFLAG
%RECORD(RD) OPND1,OPND2,OPND3
%INTEGERFNSPEC STROP(%RECORD(RD) %NAME OPND)
      KEEPWA=MODE&16; MODE=MODE&15
      PP=P; STRINGL=0; FNAM=0; WKAREA=0
      P=P+3;                            ! LENGTH OF CONSTANT PART
      ERR=72; ->ERROR %UNLESS A(P)=4
      P=P+1
      DOTS=0;                           ! NO OPERATORS YET
      ENDFLAG=0
      STRINGL=0
      ERR=STROP(OPND2);                 ! GET FIRST OPERAND
      ->ERROR %UNLESS ERR=0
NEXT: %IF A(P)=2 %THEN ENDFLAG=1 %ELSESTART
         %IF A(P+1)#CONCOP %THEN ERR=72 %AND ->ERROR
         P=P+2
         ERR=STROP(OPND3)
         ->ERROR %UNLESS ERR=0
      %FINISH
      %IF ENDFLAG=0 %AND OPND2_FLAG=LCONST=OPND3_FLAG %START
!
! CAN FOLD OUT A CONCATENATION HERE
!
         I=CONCAT
         CTOP(I,ERR,0,OPND2,OPND3)
         %IF I=0 %THEN ->NEXT;          ! FOLDED OUR
      %FINISH
      %IF DOTS=0 %START
         %IF MODE=0 %AND ENDFLAG#0 %START; ! NO RUN-TIME OPERATIONS
            OPND1=OPND2; ->TIDY
         %FINISH
         GET WSP(WKAREA,X'80000000'!268); ! GET NEXT OPERAND
         OPND1_PTYPE=X'35'
         OPND1_FLAG=LOCALIR
         OPND1_D=RBASE<<16!WKAREA
         I=BRECTRIP(PRECC,X'35',0,OPND1,OPND2)
         DOTS=1
      %FINISH
      %IF ENDFLAG=0 %THENSTART
         I=BRECTRIP(CONCAT,X'35',0,OPND1,OPND3)
         ->NEXT
      %FINISH
TIDY:                                   ! FINISH OFF
      EXPOPND=OPND1;                    ! LEAVE REULT IN EXPOPND
      VALUE=WKAREA
      P=P+1;                            ! PAST REST OF EXPRN
      RETURN WSP(WKAREA,268) %IF KEEPWA=0 %AND WKAREA>0
      STRINGL=0
      %RETURN
ERROR:FAULT(ERR,0,FNAM)
      BASE=RBASE; DISP=0
      VALUE=0; ACCESS=0
      P=PP; SKIP EXP
      %RETURN
%INTEGERFN STROP(%RECORD(RD) %NAME OPND)
!***********************************************************************
!*       DEALS WITH OPERAND FOR CONCATENATION. RETURN RESULT=0 FOR     *
!*       VALID OPERAND OTHERWISE AN ERROR NUMBER.                      *
!***********************************************************************
%INTEGER CTYPE,MODE,I
      MODE=A(P);                        ! ALTERNATIVE OF OPERAND
      OPND=0
      %RESULT=75 %IF MODE>2
      %IF MODE#1 %THENSTART
         CTYPE=A(P+1);                  ! GET CONST TYPE & LOSE AMCK FLAGS
         %IF CTYPE=X'35' %THENSTART
            STRINGL=A(P+2)
            OPND_PTYPE=CTYPE
            OPND_FLAG=LCONST
            OPND_D=P+2
            OPND_XTRA=STRINGL
            P=P+STRINGL+3
         %FINISHELSERESULT=73
      %FINISHELSESTART
         P=P+1;                         ! MUST CHECK FIRST
         %IF 5#TYPE#7 %THEN FNAM=FROMAR2(P) %ANDRESULT=71
         %IF PTYPE=X'35' %AND A(P+2)=2=A(P+3) %START
            OPND_FLAG=DNAME
            OPND_PTYPE=PTYPE
            OPND_D=FROMAR4(P)
            P=P+4
         %FINISHELSESTART
            CNAME(2)
            OPND_FLAG=REFTRIP
            OPND_PTYPE<-PTYPE
            OPND_D=TRIPLES(0)_BLINK
         %FINISH
         STRINGL=0
         DISP=0
      %FINISH
      %RESULT=0
%END;                                   ! OF INTEGERFN STROP
%END;                                   ! OF ROUTINE CSTREXP
%ROUTINE CRES (%INTEGER LAB)
!**********************************************************************
!*       COMPILES A RESOLUTION E.G A->B.(C).D.(E).F AND JUMPS TO LAB   *
!*       ON FAILURE. (LAB=0 FOR UNCONDITIONAL RESOLUTION TO PERM ON    *
!*       FAILURE ).                                                    *
!*       THE  METHOD IS TO CALL A SUBROUTINE PASSING 5 PARAMS:-        *
!*       P1(32BITS)  POINTS TO LHS(A)                                  *
!*       P2(16BITS) ORIGINAL LENGTH OF A                               *
!*       P3(32BITS) FULL POINTER TO BYTES USED UP INITIALLY 0          *
!*       P4(48BITS) STRING TO CONTAIN FRAGMENT                         *
!*                (PASSED AS LMAX FOLLOWED BY 32BIT ADDRESS)           *
!*       P5(32BITS) THE EXPRESSION PASSED AS 32 BIT ADDRESS            *
!*       SUBROUTINE TRIES TO PERFORM THE RESOLUTION AND SETS THE       *
!*       RESULT TO TRUE IF IT SUCCEEDS.                                *
!*                                                                     *
!*       ON ENTRY LHS IS IN THE ESTACK(32BITS).                        *
!*       P POINTS TO P(+') OF RHS DEFINED AS (+')(OPERAND)(RESTOFEXP)  *
!*                                                                     *
!$       THE ROUTINE IS COMPACT BUT DIFFICULT TO FOLLOW (OR ALTER)     *
!*       THE TIME IN PERM IS LARGE SO IT IS NOT WORTHWHILE TO PERSUE   *
!*       CODE EFFICIENCY TOO INDUSTRIOUSLY .                           *
!**********************************************************************
%INTEGER P1,P2,SEXPRN,W,LAST,ERR,FNAM
      LAST=0; FNAM=0;                   ! =1 WHEN END OF EXPRNSN FOUND
      SEXPRN=0;                         ! RESOLUTION(BRKTD) EXPRESSNS
      ERR=74;                           ! NORMAL CRES FAULT
      GET WSP(W,X'80000004');           ! TO HOLD P1,P2 AND VALUE OF P3
      PB1(REPL2)
      DSTORE(4,RBASE,W);                ! SAVE 32BIT ADDR OF LHS
      PB1(LDC0)
      DSTORE(2,RBASE,W+6);              ! 0 BYTES USED UP SO FAR
      PB3(LDC0,TLATE2,LDCH)
      DSTORE(2,RBASE,W+4);              ! ORIGINAL LENGTH OF LHS
      P1=P; P=P+3
      ->RES %IF A(P)=4;                 ! LHS MUST BE A STRING
                                        ! BUT THIS CHECKED BEFORE CALL
      ERR=72
ERROR:FAULT(ERR,0,FNAM)
      P=P1; SKIP EXP; %RETURN
RES:        P=P+1;                      !    TO P(OPERAND)
      PB2(ATPB,1);                      ! HOLE FOR RESULT(=T/F)
      DFETCH(4,RBASE,W)
      PB1(MMS2);                        ! P1 IS STACKED
      DFETCH(2,RBASE,W+4)
      PB1(MMS);                         ! P2 IS STACKED
      DFETCHAD(YES,RBASE,W+6)
      PB1(MMS2);                        ! POINTER TO P3
      %IF A(P)=3 %THEN %START;          ! B OMITTED
         PB3(LDC0,REPL,REPL)
      %FINISH %ELSE %START
         ->ERROR %UNLESS A(P)=1;        ! P(OPERAND)=NAME
         P=P+1; P2=P
         CNAME(3)
         %IF TYPE#5 %THEN ERR=71 %AND FNAM=FROMAR2(P2) %AND ->ERROR
         %IF A(P+1)#CONCOP %THEN ERR=72 %AND ->ERROR
         P=P+2
      %FINISH
      PB2(MMS,MMS2);                    ! LAMX&ADDRESS AS PARAMETERS
      ->ERROR %UNLESS A(P)=3;           ! P(OPERAND)='('(EXPR)')'
      SEXPRN=SEXPRN+1; P=P+1
      CSTREXP(32);                      ! FULL 32 BIT ADDRESS
      PB1(MMS2);                        ! IS STACKED
!
      PPJ(0,16)
      PB1(MES);                         ! DEAL WITH FALSE IE RESLN FAILED
      %IF LAB#0 %THEN ENTER JUMP(JFW,LAB,B'11') %ELSE PPJ(JFW,12)
!
      -> END %IF A(P)=2
      %IF A(P+1)#CONCOP %THEN ERR=72 %AND ->ERROR
      P2=P+1; P=P2+1
      %IF A(P)=3 %THEN P=P2 %AND ->RES
      ->ERROR %UNLESS A(P)=1
      P=P+3 %AND SKIP APP %UNTIL A(P)=2
      %IF A(P+1)=1 %THEN P=P2 %AND ->RES
      P1=P+1
      P=P2+2
      CNAME(3)
      PB1(MMS);                         ! LMAX TO MSTACK
      PB1(REPL2);                       ! 2 COPIES OF VRT ADDR
      DFETCH(2,RBASE,W+4)
      DFETCH(2,RBASE,W+6)
      PB3(SBI,REPL,REPL);               ! LENGTH OF FRAGMENT
      PB2(MMS2,MMS);                    ! 3 COPIES TO MSTACK
      PB1(LDC0+1);                      ! DEST FOR MVBYTES
      DFETCH(4,RBASE,W)
      DFETCH(2,RBASE,W+6)
      PB2(LDC0+1,ADI);                  ! SOURCE FOR MOVE
      PB1(MES);                         ! LENGTH ON TOP
      PB3(STLATE,X'63',MVBW);           ! ASSIGN ALL BAR LENGTH
      PB4(LDC0,MES,TLATE3,STCH);        ! ASSIGN LENGTH
      PB2(MES2,LEQI)
      PPJ(JFW,9);                       ! CAPACITY EXCEEDED
      P=P1
END:
      RETURN WSP(W,4)
      P=P+1
%END
%ROUTINE CEND (%INTEGER KKK)
!***********************************************************************
!*       DEAL WITH ALL OCCURENCES OF '%END'                            *
!*       KKK=PTYPE(>=X'1000') FOR ROUTINES,FNS AND MAPS                *
!*       KKK=0 FOR ENDS OF '%BEGIN' BLOCKS                             *
!*       KKK=1 FOR '%ENDOFPROGRAM'                                     *
!*       %ENDOFPROGRAM IS REALLY TWO ENDS. THE FIRST IS THE USERS      *
!*       AND THE SECOND IS PERMS. KKK=2 FOR A RECURSIVE CALL OF CEND   *
!*       ON END OF PROGRAM TO DEAL WITH THE %END CORRESPONDING TO      *
!*       THE %BEGIN COMPILED IN THE INITIALISATION SEQUENCE            *
!***********************************************************************
%INTEGER KP,JJ,BIT,ID,ML
%ROUTINESPEC DTABLE(%INTEGER LEVEL)
%RECORD(RTDICTF) RTDICT
         SET LINE %UNLESS KKK=2
         BIT=1<<LEVEL
!
! NOW PLANT AN ERROR EXIT FOR FNS AND MAPS - CONTROL SHOULD BE RETURNED
! VIA %RESULT= AN SHOULD NEVVER REACH THE %END INSTRUCTION
!
         %IF KKK&X'3FFF'>X'1000' %AND PARM_COMPILER=0 %C
            %AND LAST INST=0 %THEN %C
            JJ=UCONSTTRIP(RTBAD,X'51',0,0);          ! RUN FAULT 11
!
! NOW PLANT THE BLOCK EXIT SEQUENCE
!

         %IF KKK&X'3FFF'=X'1000' %AND LAST INST=0 %THEN %C
            JJ=UCONSTTRIP(RTXIT,X'51',0,0)
         JJ=UCONSTTRIP(XSTOP,X'51',0,0) %IF KKK=1 %AND LAST INST=0;! %STOP AT %ENDOFPROGRAM
         %IF KKK=0 %THEN %START;         ! BEGIN BLOCK EXIT
            %IF PARM_TRACE=1 %THEN %START;    ! RESTORE DIAGS POINTERS
               JJ=UCONSTTRIP(RDPTR,X'51',0,LEVEL-1)
            %FINISH
            JJ=CURRINF_NMDECS>>14
            %IF JJ#0 %THEN %START;      ! ARRAYS TO BE UNDECLARED
               JJ=UCONSTTRIP(RSPTR,X'51',0,JJ)
            %FINISH
         %FINISH
         FORCE TRIPS
         NMAX=N %IF N>NMAX;            ! WORK SPACE POINTER
!
! CLEAR OUT THE LABEL LIST FAULTING LABELS WITH JUMPS OUTSTANDING
! AS NOT SET AND COMMENTING ON LABELS NOT USED
!
         %WHILE CURRINF_LABEL#0 %CYCLE
            POP(CURRINF_LABEL,I,J,KP)
            %IF J&X'FFFF'#0 %THEN %START
               J=J&X'FFFF'
               %IF 0<KP<=MAX ULAB %THEN FAULT(11,FROM3(J),KP)
               CLEAR LIST(J)
            %FINISH %ELSE %START
               %IF I&LABUSEDBIT=0 %AND KP<MAX ULAB %THEN WARN(3,KP)
            %FINISH
         %REPEAT
!
         %CYCLE JJ=0,1,4
            CLEAR LIST(CURRINF_AVL WSP(JJ));! RELEASE TEMPORARY LOCATIONS
         %REPEAT
!

         RTDICT=0
         RTDICT_DIAGS=SSTL>>1
         DTABLE(LEVEL);                ! OUTPUT DIAGNOSTIC TABLES
         %WHILE CURRINF_UNATT FORMATS#0 %CYCLE
            POP(CURRINF_UNATT FORMATS,I,J,JJ)
            CLEAR LIST(I)
            CLEAR LIST(J)
            CLEAR LIST(JJ)
         %REPEAT
!
! NOW CLAIM THE STACK FRAME BY FILING THE ASF IN THE BLOCK ENTRY CODING
!
      NMAX=(NMAX+7)&(-8)
      %IF KKK=2 %THEN %RETURN
       %IF KKK>=X'1000' %OR KKK=1 %THEN %START
         ML=CURRINF_M-1
         %IF KKK=1 %THEN ID=X'80000000' %AND JJ=ADDR(MAINEP) %ELSE %C
            ID=FROM2(TAGS(ML))&X'FFFF' %AND JJ=WORKA_DICTBASE+WORD(ML)
         PTYPE=KKK; UNPACK
         RTDICT_PS=0
         %IF ROUT#0 %THEN %START
            %IF NAM#0 %OR TYPE=5 %THEN RTDICT_PS=4 %C
               %ELSE RTDICT_PS=(BYTES(PREC)+1)&(-2)
         %FINISH
         RTDICT_PS=(CURRINF_PSIZE-RTDICT_PS)//2
         RTDICT_RPS=CURRINF_PSIZE//2
         RTDICT_LTS=NMAX//2-RTDICT_RPS
         RTDICT_ENTRY=CURRINF_ENTRYAD
         RTDICT_EXIT=CA-1
         RTDICT_LL=RLEVEL
         %IF RLEVEL=1 %THEN ID=ID!1<<16;! FLAG AS EXTERNAL
         QPUT(11,ID,ADDR(RTDICT),JJ)
         %IF CA>30000 %AND WORKA_PLABS(1)<30000 %THEN REPEAT PROLOGUE
      %FINISH
!
! RETURN TO PREVIOUS LEVEL PROVIDED THERE IS A VALID ONE !
!
         %UNLESS LEVEL>2 %OR (LEVEL=2 %AND PARM_CPRMODE=2) %THEN %START
            %IF KKK=1 %AND LEVEL=2 %THEN KKK=2 %ELSE FAULT(109,0,0)
                                        ! SHOULD BE CHKD IN PASS1
         %FINISH
         LEVEL=LEVEL-1
         CURRINF==LEVELINF(LEVEL)
         %IF KKK>=X'1000' %THEN %START
            RLEVEL=CURRINF_RBASE
            RBASE=RLEVEL
         %FINISH
!
! RESTORE INFORMATION ABOUT THE (NEW) CURRENT LEVEL
!
         NMAX=CURRINF_SNMAX %IF KKK>=X'1000'
         N=CURRINF_SN
         %IF KKK=2 %THEN CEND(KKK);    ! ROUND AGAIN FOR 'ENDOFPROGRAM'
!
! COMPLETE THE JUMP AROUND ALL NON-EXTERNAL ROUTINES EXCEPT WHEN
! %TRUSTEDPROGRAM IS IN OPERATION.
!
         %IF KKK>=X'1000' %AND PARM_COMPILER=0 %AND %C
            (RLEVEL>0 %OR PARM_CPRMODE#2) %THEN %START
            JJ=NEXTP+6
            %UNLESS A(NEXTP+5)=11 %AND A(JJ+FROMAR2(JJ))=2 %START
               JJ=ENTER LAB(CURRINF_JROUND,0)
               CURRINF_JROUND=0
            %FINISH
         %FINISH
         %RETURN
!
! 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)<<18 ! ENVIRONMENT
!                ( TOP 2 BITS OF LANG DEPENDENT HAS LITL FROM PTYPE)
!                 ( BOTTOM 4 BITS HAVE TEXTUAL LEVEL)
! 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 DTABLE(%INTEGER LEVEL)
!***********************************************************************
!*      THIS ROUTINE LOOKS AT THE DECLARATIONS FOR THE CURRENT LEVEL & *
!*      SETS UP THE SEGMENT OF SHARABLE SYMBOL TABLES TO DESCRIBE THEM.*
!*      FOR MAIN PROGRAMS OR EXTERNAL ROUTINES THE 'GLOBAL' VARIABLES  *
!*      (IF ANY) ARE ALSO INCLUDED.                                    *
!***********************************************************************
%CONSTINTEGER DAREA=6
%STRING(31) RT NAME
%STRING(11) LOCAL NAME
%RECORD(LISTF)%NAME LCELL
%CONSTINTEGER LARRROUT=X'F300'
%INTEGER DPTR,LNUM,ML,KK,JJ,Q,DEND,BIT,S1,S2,S3,S4,LANGD,II
%INTEGERARRAY DD(0:500);       ! BUFFER FOR SEGMENT OF SST
!
! FILL ALL OUTSTANDING REFERENCES TO THIS DIAGS BLOCK
!
         BIT=1<<LEVEL
         LANGD=KKK>>14<<30!LEVEL<<18;  ! GET LITL FROM PTYPE
         %WHILE CURRINF_RAL#0 %CYCLE
            POP(CURRINF_RAL,Q,JJ,KK)
            %IF Q=1 %THEN %START
               PLUG(1,JJ+2,CODEP_CAS(DAREA)>>9&255,1)
               PLUG(1,JJ+1,CODEP_CAS(DAREA)>>1&255,1)
            %FINISH %ELSE PLUG(Q,JJ,KK!CODEP_CAS(DAREA),4)
         %REPEAT
         PUSH(LEVELINF(LEVEL-1)_RAL,DAREA,CODEP_CAS(DAREA)+4,LANGD) %IF PARM_TRACE#0
         DD(0)=CURRINF_L<<16!(CURRINF_DIAGINF+2)
         DD(1)=LANGD
         DD(2)=4*RBASE!CURRINF_FLAG&X'3FFF'
         ML=CURRINF_M;                   ! ROUTINE NAME(=0 FOR %BEGIN)
         %IF ML#0 %THEN ML=WORD(ML-1);  ! IF NOT BLOCK GET DIRPTR
         LNUM=BYTEINTEGER(WORKA_DICTBASE+ML); ! LENGTH OF THE NAME
         DPTR=4; DEND=0
         %IF LNUM=0 %THEN DD(3)=0 %ELSE %START
            Q=WORKA_DICTBASE+ML
            RT NAME<-STRING(Q);         ! FOR RTS MOVE IN 1ST 32 CHARS
            LNUM=BYTE INTEGER(ADDR(RT NAME))
            STRING(ADDR(DD(3)))=RTNAME; ! AND UPDATE POINTER PAST
            %IF ON PERQ=NO %AND PARM_TRACE#0 %THEN %C
               QPUT(9,DAREA,CODEP_CAS(DAREA)+12,LNUM+1)
            DPTR=DPTR+LNUM>>2;          ! ACTUAL NO OF CHARS
         %FINISH
         DD(DPTR)=CURRINF_ONWORD;        ! ON CONDITION WORD
         DPTR=DPTR+1
         JJ=CURRINF_NAMES
         %WHILE 0<=JJ<X'3FFF' %CYCLE
            LCELL==ASLIST(TAGS(JJ))
                                         ! OBTAIN NEXT NAME FORM DECLNS
!
! GET ONLY THE MINIMUM OF DETALS NECESSARY
!
            S1=LCELL_S1; S2=LCELL_S2
            S3=LCELL_S3; S4=LCELL_LINK
            LCELL_LINK=ASL; ASL=TAGS(JJ)
            TAGS(JJ)=S4&X'3FFFF'
            PTYPE=S1>>16; TYPE=PTYPE&15
!
! FAULT ALL UNUSED NAMES EXCEPT CONSTINTEGERS&REALS
!
            %IF (TYPE>2 %OR PTYPE&X'FF00'#X'4000') %C
               %AND S1&X'C000'=0 %THEN WARN(2,JJ)
            I=S1>>4&15
            J=S1&15
            K=S3>>16
!
! ALLOW OWNS (LITL=0) AND EXTERNALS (=2) NOT CONSTS(=1) OR EXTRINSIC(=3)
!
            %IF PARM_DIAG#0 %AND PTYPE&X'7300'<=X'200' %AND DPTR<497 %C
               %AND (TYPE=1 %OR TYPE=2 %OR TYPE=5) %START
               Q=WORKA_DICTBASE+WORD(JJ);     ! ADDRESS OF NAME
               %IF I=0 %THEN II=1 %ELSE II=0;   ! GLA OR LNB BIT
               DD(DPTR)=PTYPE<<20!II<<18!K
               LOCAL NAME<-STRING(Q);   ! TEXT OF NAME FROM DICTIONARY
               LNUM=BYTE INTEGER(ADDR(LOCAL NAME))
               STRING(ADDR(DD(DPTR))+4)=LOCAL NAME;! MOVE IN NAME 
               %IF ON PERQ=NO %AND PARM_TRACE#0 %THEN %C
                  QPUT(9,DAREA,CODEP_CAS(DAREA)+4*DPTR+4,LNUM+1)
               DPTR=DPTR+(LNUM+8)>>2
            %FINISH
            %IF J=15 %AND PTYPE&X'3000'#0 %AND S1&X'C000'#0 %THEN %C
               FAULT(28,0,JJ)
                                        ! SPEC&USED BUT NO BODY GIVEN
            %IF J=15 %AND TYPE=4 %THEN FAULT(62,0,JJ)
            %IF PTYPE&X'3000'#0 %OR TYPE=4 %OR TYPE=6 %THEN %C
            CLEAR LIST(K) %ELSE %START
               %IF I#0 %AND K>4095 %AND PTYPE&LARRROUT=0 %AND TYPE#7 %C
                  %THEN WARN(5,JJ)
            %FINISH
            JJ=S4>>18
         %REPEAT
         DD(DPTR)=-1;                   ! 'END OF SEGMENT' MARK
         DPTR=DPTR<<2+4
         %IF PARM_TRACE=1 %THEN %START
            QPUT(40+DAREA,DPTR,CODEP_CAS(DAREA),ADDR(DD(0)));! ADD TO SHARABLE SYM TABS
            CODEP_CAS(DAREA)=CODEP_CAS(DAREA)+DPTR
         %FINISH
         %END;                          ! OF ROUTINE DTABLE
         %END
%ROUTINE DECLARE SCALARS(%INTEGER PERMIT,XTRA)
!***********************************************************************
!*       THIS ROUTINE DECLARES A LIST OF SCALARS FROM INFORMATION      *
!*       IN THE GLOBAL VARIABLES ROUT,NAM,ARR,PREC,TYPE & ACC.IT WORKS *
!*       OUT ROUNDING FACTORS FOR ITSELF.                              *
!*       P POINTS TO THE NAMELIST ON ENTRY AND IS UPDATED.             *
!*       PERMIT IS 0 IF DECLARING FORMAL PARAMETERS                    *
!***********************************************************************
%INTEGER INC,Q,SCHAIN,NPARMS,SCAL NAME,TYPEP
      PACK(PTYPE); J=0
      INC=ACC; SNDISP=0
      %IF PTYPE=X'35' %THEN INC=(INC+1)&(-2)
      %IF NAM#0 %AND ARR=0 %AND ROUT=0 %THEN %START
         INC=4
         %IF TYPE=5 %OR (PREC=3 %AND TYPE=1) %THEN INC=6
      %FINISH
      %IF NAM>0 %AND ARR>0 %THEN INC=8
      %IF PTYPE=X'35' %AND (ACC<=0 %OR ACC>256) %THEN %C
         FAULT(70,ACC-1,0) %AND ACC=255
      N=(N+1)&(-2)
      %UNTIL A(P-1)=2 %CYCLE;      ! DOWN THE NAMELIST
         SCAL NAME=FROM AR2(P)
         %IF PTYPE=X'31' %AND PERMIT=0 %THEN N=N+1;! BYTE PARAMS
         SCHAIN=N
         KFORM=XTRA
         %IF ROUT=1 %THEN %START
            TYPEP=PTYPE;                ! CHANGED BY CFPLIST!
            Q=P
            P=P+3 %UNTIL A(P-1)=2;      ! TO FPP
            CFPLIST(SCHAIN,NPARMS)
            P=Q
            J=13
            KFORM=NPARMS;               ! NO OF PARAMS OF FORMAL
            ACC=N;                      ! DISPLACEMENT TO MIDCELL
            PTYPE=TYPEP; UNPACK
         %FINISH
         P=P+3
         %IF PTYPE=X'33' %THEN %START
            SCHAIN=N
         %FINISH
         STORE TAG(SCAL NAME,SCHAIN)
         N=N+INC
      %REPEAT
      %IF PERMIT#0 %THEN N=(N+1)&(-2);  ! THIS IS NECESSARY !
%END
%INTEGERFN DOPE VECTOR(%INTEGER TYPEP,ELSIZE,MODE,IDEN, %INTEGERNAME ASIZE,LB)
!***********************************************************************
!*        CONSTRUCTS THE DOPE-VECTOR FOR A CONSTANT ARRAY IN THE       *
!*       SHAREABLE SYMBOL TABLES AND RETURNS ITS DISPLACEMENT AS RESULT*
!*       P IS TO ALT (MUST BE 1!) OF P<BPAIR>                          *
!*       DOPE VECTOR CONSISTS OF :-                                    *
!*       @0 DWORD CONTAINING THE BASE OFFSET                           *
!*       @4 WORD CONTAINING THE NO OF DIMENSIONS ND                    *
!*       @6 WORD HOLDING SIZE (IN BYTES) OF A SINGLE ELEMENT           *
!*       @8 DWORD OF SIZE(IN WORDS OF ENTIRE ARRAY)FOR STACK ADJUSTMENT*
!*       AND ND DWORD TRIPLES EACH CONSISTING OF:-                     *
!*       UBI THE UPPER BOUND OF THE ITH DIMENSION                      *
!*       LBI - THE LOWER BOUND OF THE ITH DIMENSION                    *
!*       RI - THE STRIDE FOR THE ITH DIMENSION=(UBI-LBI+1)             *
!*       MODE=0 DV MUST BE CONST, MODE#0 CAN BE DYNAMIC                *
!*       MODE=-1 SPECIAL FOR CONSTARRAYNAMES 1D 0:INFINITY             *
!***********************************************************************
      %INTEGER I,JJ,K,ND,D,M0,HEAD,NOPS,TYPEPP,PIN,PTR
      %RECORD(LISTF) %NAME LCELL
      %INTEGERARRAY LBH,LBB,UBH,UBB(0:12)
      %INTEGERARRAY DV(0:39);            ! ENOUGH FOR 12 DIMENSIONS
      ND = 0; NOPS = 0; TYPEPP = 0; PIN = P
      M0 = 1
      %IF MODE=-1 %THENSTART
         ND = 1; DV(4) = 0
         M0 = X'7FFF'
         DV(3) = M0
         DV(5) = M0
         ASIZE = M0
      %FINISHELSESTART
         %UNTIL A(P)=2 %CYCLE
            ND = ND+1; P = P+4
            FAULT(37,0,IDEN) %AND ND = 1 %IF ND>12
            LBH(ND) = 0; LBB(ND) = 0
            UBB(ND) = 0; UBH(ND) = 0
            TORP(LBH(ND),LBB(ND),NOPS)
            P = P+3
            TYPEPP = TYPEPP!TYPE
            TORP(UBH(ND),UBB(ND),NOPS)
            TYPEPP = TYPEPP!TYPE
         %REPEAT
         P = P+1
         ->NONCONST %UNLESS TYPEPP=1 %AND NOPS&X'40040000'=0
!
! NOW ONE CAN WORK OUT AND FILL IN THE TRIPLES
!
         PTR = 1
         %CYCLE D = 1,1,ND
            K = 3*D
            EXPOP(LBH(PTR),LBB(PTR),NOPS,X'251')
            EXPOPND_D = 0 %AND FAULT(41,0,0) %UNLESS %C
               EXPOPND_FLAG<=1 %AND EXPOPND_PTYPE=X'51'
            DV(K+1) = EXPOPND_D
            EXPOP(UBH(PTR),UBB(PTR),NOPS,X'251')
            EXPOPND_D = 10 %AND FAULT(41,0,0) %UNLESS %C
               EXPOPND_FLAG<=1 %AND EXPOPND_PTYPE=X'51'
            JJ = EXPOPND_D
            DV(K) = JJ
            DV(K+2) = JJ-DV(K+1)+1
            FAULT(38,1-DV(K+2),IDEN) %UNLESS JJ>=DV(K)
            M0 = M0*DV(K+2)
            PTR = PTR+1
         %REPEAT
         ASIZE = M0*ELSIZE
      %FINISH
!
!      CALCULATE THE OFF SET OF A(FIRST,..) FROM A(0,..)
!
      LB = DV(4); I = 6
      %WHILE I<=3*ND %CYCLE
         LB = LB+DV(I+1)*DV(I-1)
         I = I+3
      %REPEAT
      FAULT(39,0,IDEN) %IF ASIZE>X'FFFF'
      DV(2) = (ASIZE+1)>>1
      DV(0) = -LB
      DV(1) = ND<<16!ELSIZE
      K = 3*ND+2
      J = ND;                            ! DIMENSIONALITY FOR DECLN
      HEAD = DVHEADS(ND)
      %WHILE HEAD#0 %CYCLE
         LCELL == ASLIST(HEAD)
         %IF LCELL_S2=ASIZE %START
            %CYCLE D = 0,1,K
               ->ON %UNLESS DV(D)=CTABLE(D+LCELL_S1)
            %REPEAT
            SNDISP = 4*LCELL_S1
            %RESULT = LCELL_S3
         %FINISH
ON:      
         HEAD = LCELL_LINK
      %REPEAT
      SSTL = (SSTL+3)&(-4);              ! ALIGN SHAREABLE ST
      SNDISP = 4*WORKA_CONST PTR
      I = SSTL
      PUSH(DVHEADS(ND),WORKA_CONSTPTR,ASIZE,I)
      %CYCLE D = 0,1,K
         CTABLE(WORKA_CONST PTR) = DV(D)
         WORKA_CONST PTR = WORKA_CONST PTR+1
         %IF ONPERQ=NO %THEN DV(D) = DV(D)>>16!DV(D)<<16
      %REPEAT
      %IF WORKA_CONST PTR>WORKA_CONST LIMIT %THEN FAULT(102,WORKA_WKFILEK,0)
      QPUT(44,4*(K+1),SSTL,ADDR(DV(0)))
      SSTL = SSTL+K*(K+1)
WAYOUT:
      %IF MODE=-1 %THENRESULT = I;       ! NO EXPRESSION CELLS TO RETURN
      %RESULT = I
NONCONST:                                ! NOT A CONST DV
      J = ND; I = -1; SNDISP = -1
      LB = 0; ASIZE = ELSIZE
      %IF MODE=0 %THEN FAULT(41,0,0) %ELSE P = PIN
      ->WAYOUT
%END

%ROUTINE DECLARE ARRAYS(%INTEGER FORMAT,FINF)
!***********************************************************************
!*       FORMAT=1 FOR 'ARRAYFORMAT'   =0 OTHERWISE                     *
!*       FINF>0 FOR RECORD FORMAT INFORMATION =0 OTHERWISE             *
!*       P IS AT P<ADECLN>   IN                                        *
!*                                                                     *
!*       P<ADECLN>=<NAMELIST> <BPAIR> <RESTOFDECLN>                    *
!*       P<BPAIR> = '('<EXPR>':'<EXRR><RESTOFBP>*')'                   *
!*                                                                     *
!*       ARRAYS WITH CONSTANT BOUNDS HAVE THEIR D-V IN THE SST         *
!*       ALL OTHER ARRAYS HAVE A DOPE VECTOR AMONG THE LOCALS AND GET  *
!*       THEIR SPACE OFF THE STACK AT RUN TIME                         *
!*       BOTH SORTS OF ARRAYS HAVE A FOUR WORD HEAD AND D-V TO EMAS    *
!*       SYSTEM STANDARDS                                              *
!***********************************************************************
%INTEGER DVDISP,PP,DVF,ELSIZE,TOTSIZE,PTYPEP,ARRP,NN,ND,II,QQ,CDV,LWB,
   PTYPEPP,JJJ,JJ,TRIP1,TRIP2
%RECORD(RD) OPND1,OPND2,OPND3
%RECORD(TRIPF)%NAME CURRT
%INTEGERARRAY BTRIPS(0:12,0:2)
      %IF CURRINF_FLAG=0 %AND CURRINF_NMDECS>>14=0 %START
         JJJ=UTEMPTRIP(SSPTR,X'41',0,N); ! SAVE THE STACK POINTER
         CURRINF_NMDECS=CURRINF_NMDECS!N<<14
         N=N+2
      %FINISH
      ARRP=2*FORMAT+1; ARR=ARRP; PACK(PTYPEP)
      ELSIZE=ACC
START:NN=1; P=P+1;                       ! NO OF NAMES IN NAMELIST
      PP=P; CDV=0; PTYPEPP=PTYPEP
      P=P+3 %AND NN=NN+1 %WHILE A(P+2)=1
      P=P+3
      DVDISP=DOPE VECTOR(TYPE,ELSIZE,1,FROMAR2(PP),TOTSIZE,LWB)
      ND=J
      ->CONSTDV %UNLESS DVDISP<0
!
! NORMAL CASE - PLANT CODE TO SET UP DOPE-VECTOR AT RUN TIME
!
      DVF=1; TOTSIZE=X'FFFF'
      N=(N+3)&(-4);                      ! MAY BE BENEFITS IN WORD ALIGNMENT
      DVDISP=N;                          ! DVDISP IS D-V POSITION
      N=N+12*ND+12;                      ! CLAIM SPACE FOR THE D-V
      OPND1_S1=X'41'<<16!LOCALIR
      OPND1_D=RBASE<<16!DVDISP+4
      OPND2_S1=X'41'<<16!SCONST
      OPND2_D=ND
      TRIP1=BRECTRIP(LASS,X'41',0,OPND1,OPND2); ! ASSN DIMEN->DVDIPS+4
      OPND1_D=RBASE<<16!DVDISP+6
      OPND2_D=ELSIZE
      TRIP1=BRECTRIP(LASS,X'41',0,OPND1,OPND2); ! ASSN ELSIZE-> DVDISP+6
!
      %CYCLE II=1,1,ND
         P=P+1
         QQ=DVDISP+12*II;                ! TRIPLE FOR IITH DIMENSION
         %CYCLE JJ=0,1,1;                ! LOWER&UPPER BNDS
            CSEXP(X'51')
            OPND1_S1=X'51'<<16!LOCALIR
            OPND1_D=RBASE<<16!(QQ+4-4*JJ);   ! BPAIRS BACKWARD FOR PERQ!
            %IF JJ=0 %AND(EXPOPND_FLAG>0 %OR EXPOPND_D#0) %THEN DVF=0
                                         ! BASE OFFSET NOT ZERO
            TRIP1=BRECTRIP(LASS,X'51',0,OPND1,EXPOPND)
            BTRIPS(II,JJ)=TRIP1
         %REPEAT
         OPND1_S1=X'51'<<16!REFTRIP
         OPND1_D=BTRIPS(II,1);           ! UPPER BND
         OPND2_S1=X'51'<<16!REFTRIP
         OPND2_D=BTRIPS(II,0)
         OPND1_D=BRECTRIP(SUB,X'51',0,OPND1,OPND2); ! UB-LB
         OPND2_S1=X'51'<<16!SCONST
         OPND2_D=1
         OPND1_D=BRECTRIP(ADD,X'51',0,OPND1,OPND2); ! UB-LB+1
         OPND2_S1=X'51'<<16!LOCALIR
         OPND2_D=RBASE<<16!(QQ+8)
         BTRIPS(II,2)=BRECTRIP(LASS,X'51',0,OPND2,OPND1)
         %IF II=1 %THEN TRIP2=BTRIPS(II,2) %ELSESTART
            OPND1_S1=X'51'<<16!REFTRIP
            OPND1_D=TRIP2
            OPND2_S1=X'51'<<16!REFTRIP
            OPND2_D=BTRIPS(II,2)
            TRIP2=BRECTRIP(MULT,X'51',0,OPND1,OPND2)
         %FINISH
      %REPEAT
      P=P+1
!
! WORK OUT TOTAL SIZE IN WORDS. TRIP2 HAS NO OF ELEMENTS
!
      OPND1_D=TRIP2
      OPND2_S1=X'51'<<16!SCONST
      %IF ELSIZE&1#0 %THEN OPND2_D=ELSIZE %ELSE OPND2_D=ELSIZE>>1
      OPND1_D=BRECTRIP(MULT,X'51',0,OPND1,OPND2)
      %IF ELSIZE&1#0 %START;             ! ROUND UP TO NEXT BUT ONE WORD
         OPND2_D=1
         OPND1_D=BRECTRIP(ADD,X'51',0,OPND1,OPND2)
         OPND2_D=-1
         OPND2_S1=X'41'<<16!SCONST
         OPND1_D=BRECTRIP(RSHIFT,X'51',0,OPND1,OPND2)
      %FINISH
      OPND2_S1=X'51'<<16!LOCALIR
      OPND2_D=RBASE<<16!(DVDISP+8)
      JJ=BRECTRIP(LASS,X'51',0,OPND2,OPND1)
      SNDISP=0;                          ! DV NOT AVAILABLE AT COMPILETIME
      %IF DVF=1 %THENSTART
         LWB=0
         %IF FORMAT=0 %THEN PTYPEPP=PTYPEP+256
         OPND2_S1=X'51'<<16!SCONST
         OPND2_D=0;                      ! ZERO BASE OFFSET
      %FINISHELSESTART
!***********************************************************************
!*    FIND THE OFFSET OF A(0...) FROM A(FIRST...) BY COMPUTING         *
!*    THE OFFSET OF A(FIRST...) FROM A(0...) AND NEGATING              *
!***********************************************************************
         OPND2_S1=X'51'<<16!REFTRIP
         OPND3_S1=X'51'<<16!REFTRIP
         OPND1_S1=X'51'<<16!REFTRIP
         OPND2_D=BTRIPS(ND,0);           ! LB OF TOP DIMEN
         %CYCLE JJ=ND,-1,2
            OPND3_D=BTRIPS(JJ,0)
            OPND1_D=BTRIPS(JJ-1,2)
            OPND1_D=BRECTRIP(MULT,X'51',0,OPND1,OPND3)
            OPND2_D=BRECTRIP(ADD,X'51',0,OPND1,OPND2) %UNLESS JJ=ND
         %REPEAT
         OPND2_D=URECTRIP(LNEG,X'51',0,OPND2)
      %FINISH
      OPND1_S1=X'51'<<16!LOCALIR
      OPND1_D=RBASE<<16!DVDISP
      OPND2_D=BRECTRIP(LASS,X'51',0,OPND1,OPND2)
      ->DECL
CONSTDV:                                 ! ONE DIMENSION - CONSTANT BOUNDS
      DVF=1; CDV=1
      %IF LWB=0 %AND FORMAT=0 %THEN PTYPEPP=PTYPEP+256
      SNDISP=SNDISP>>2
                                         ! SET ARR=2 IF LWB=ZERO
      %IF PARM_COMPILER#0 %AND LWB#0 %THEN FAULT(99,0,0)
DECL:                                    ! MAKE DECLN - BOTH WAYS
      J=ND
      PTYPE=PTYPEPP; UNPACK
      %CYCLE JJJ=0,1,NN-1;               ! DOWN NAMELIST
         CURRT==TRIPLES(UCONSTTRIP(DARRAY,X'61',0,
            CDV<<31!JJJ<<24!(NN-1)<<16!DVDISP))
         CURRT_OPND1_XTRA=N
         ACC=ELSIZE;                     ! RESET ACC AFTER DV CMPLD
         KFORM=FINF;                     ! FORMAT INFORMATION
         K=FROM AR2(PP+3*JJJ)
         STORE TAG(K,N)
         JJ=UCONSTTRIP(ASPTR,X'51',0,CDV<<31!SNDISP<<16!DVDISP) %IF FORMAT=0
         N=N+8
      %REPEAT
      P=P+1;                             ! PAST REST OF ARRAYLIST
      %IF A(P-1)=1 %THEN ->START
      %RETURN
%END
%ROUTINE CLT
!***********************************************************************
!*       DEAL WITH PHRASE TYPE AND SET PREC,TYPE & ACC                 *
!*       ONLY PROBLEM ARE STRINGS WHICH HAS OPTIONAL MAX LENGTH ALSO   *
!*       RECORD WHICH HAVE A FORMAT                                    *
!*       P ON PHRASE TYPE AT ENTRY - TO NEXT PHRASE AT EXIT.           *
!***********************************************************************
%CONSTBYTEINTEGERARRAY TYPEFLAG(0:8)=0, %C
                                        X'51',X'52',LRLPT,X'31',X'35',
                                        X'41'(2),X'33';
%INTEGER ALT,PTYPEP,I
         ALT=A(P)
         TYPE=TYPEFLAG(ALT)
         %IF ALT=4 %OR ALT=6 %OR ALT=7 %THEN P=P+1
         PREC=TYPE>>4
         TYPE=TYPE&7
         P=P+1
         ACC=BYTES(PREC)
         PACK(PTYPEP);                  ! PRESERVE ALL COMPONENT
                                        ! BEFORE CALLINT INTEXP ETC
         %IF TYPE=5 %THEN %START;       ! P<TYPE>='%STRING'
            %IF A(P)=1 %THEN %START;    ! MAX LENGTH GIVEN
               %IF A(P+1)=1 %START;     ! EXPRESSION NOT STAR
                  P=P+4
                  %IF INTEXP(I,X'41')#0 %THEN FAULT(41,0,0)
                  ACC=I+1
                  PTYPE=PTYPEP; UNPACK
               %FINISH %ELSE ACC=0 %AND P=P+2
            %FINISH %ELSE ACC=0 %AND P=P+1
         %FINISH
         KFORM=0
         %IF TYPE=3 %THEN KFORM=CFORMATREF %AND PTYPE=PTYPEP %AND UNPACK
%END
%ROUTINE CQN(%INTEGER P)
!***********************************************************************
!*       SET NAM & ARR FROM ALTERNATIVE OF PHRASE <QNAME'>             *
!*       P<QNAME'>='%ARRAYNAME','%NAME',<%NULL>                        *
!*       P POINTS TO THE ANALYSIS RECORD ENTRY AS IS NOT UPDATED       *
!***********************************************************************
%INTEGER I
      I=A(P);NAM=0;ARR=0
      %IF I=1 %THEN ARR=1;              ! ARRAYNAMES
      %IF I<=2 %THEN NAM=1;             ! ARRAYNAMES & NAMES
%END

%INTEGERFN SET SWITCHLAB(%INTEGER HEAD,LAB,FNAME,BIT)
!***********************************************************************
!*    SET A SWITCH LABEL AND RETURNS RESULT=0 %UNLESS THE LABEL        *
!*    HAS BEEN ALREADY SET WHEN IT RETURNS RESULT#0                    *
!*    HEAD IS HEAD OF THE TAGS SIDECHAIN FOR THE SWITCH                *
!***********************************************************************
%INTEGER Q,QQ,JJJ,LB,UB,BASEPT
%RECORDFORMAT BITFORM(%INTEGERARRAY BITS(0:2),%INTEGER LINK)
%RECORD(BITFORM)%NAME BCELL
%RECORD(LISTF)%NAME LCELL
      OLDLINE=0
      LCELL==ASLIST(HEAD)
      BASEPT=LCELL_S1
      LB=LCELL_S2
      UB=LCELL_S3
      HEAD=LCELL_LINK
      BCELL==ASLIST(HEAD)
      %UNLESS LB<=LAB<=UB %THEN FAULT(50,LAB,FNAME) %AND %RESULT=0
      Q=LAB-LB
      %WHILE Q>=96 %%CYCLE
         HEAD=BCELL_LINK
         BCELL==ASLIST(HEAD)
         Q=Q-96
      %REPEAT
!
! ASLIST(HEAD) IS THE START OF 96 BIT ENTRY IN THE BIT LIST
! CHECK BIT NO Q TO SEE IF LABEL ALREADY SET AND THEN SET BIT Q
!
      QQ=Q>>5;                          ! RIGHT WORD
      Q=Q&31; JJJ=1<<Q;                 ! BIT IN WORD
      %RESULT=1 %UNLESS BCELL_BITS(QQ)&JJJ=0
      BCELL_BITS(QQ)=BCELL_BITS(QQ)!BIT<<Q;! DONT SET BIT ON SW(*) ENTRIES
      QQ=BASEPT+(LAB-LB)*2;             ! REL POSITION OF LABEL
      Q=CA-QQ;                          ! SELF RELATIVE PTR
      %IF Q>X'7FFF' %THEN FAULT(98,0,0)
      PLUG(1,QQ,Q,1)
      PLUG(1,QQ+1,Q>>8,1)
      %RESULT=0
%END
%ROUTINE CRSPEC (%INTEGER M)
!***********************************************************************
!*    MODE=0  FOR NORMAL ROUTINE SPEC                                  *
!*    MODE=1 FOR EXTERNAL(ETC) ROUTINE SPECS XREF NEEDED               *
!*    P ON ENTRY TO P(RT) IN (RT)(MARK)(%SPEC')(NAME)(FPP)             *
!***********************************************************************
%INTEGER KK,JJ,TYPEP,OPHEAD,NPARMS,AXNAME
      LITL=EXTRN&3
      %IF A(P)=1 %THEN %START;          ! P<RT>=%ROUTINE
         TYPEP=LITL<<14!X'1000'
         P=P+2;                         ! IGNORING ALT OF P(SPEC')
      %FINISH %ELSE %START;             ! P<RT>=<TYPE><FNORMAP>
         ROUT=1; ARR=0; P=P+1
         CLT; NAM=0
         %IF A(P)=2 %THEN NAM=2;        ! 2 FOR MAP 0 FOR FN
         PACK(TYPEP)
         P=P+2;                         ! AGAIN IGNORING ALT OF P(SPEC')
      %FINISH
      KK=FROM AR2(P)
      AXNAME=WORKA_DICTBASE+WORD(KK)
      JJ=0
      P=P+3
      %IF A(P-1)=1 %THEN AXNAME=ADDR(A(P)) %AND P=P+A(P)+1
      CFPLIST(OPHEAD,NPARMS)
      %IF M=1 %THEN %START
!         CXREF(XNAME,PARM_DYNAMIC!(EXTRN//3),2,JJ); ! %STSTEM & %EXTERNAL =STATIC
                                        ! %DYNAMIC = DYNAMIC
         JJ=AXNAME
      %FINISH %ELSE %START
         JJ=WORKA_RTCOUNT
         WORKA_RTCOUNT=WORKA_RTCOUNT+1
      %FINISH
      %IF M=0 %AND RLEVEL=0 %START
         %IF PARM_CPRMODE=0 %THEN PARM_CPRMODE=2
         %IF PARM_CPRMODE#2 %THEN FAULT(56,0,KK)
      %FINISH
      J=15-M; PTYPE=TYPEP
      KFORM=NPARMS
      SNDISP=JJ>>16
      ACC<-JJ&X'FFFF'
      STORE TAG(KK,OPHEAD)
%END
%ROUTINE CFPLIST(%INTEGERNAME OPHEAD,NPARMS)
!***********************************************************************
!*    COMPILE A FORMAL PARAMETER PART INTO A LIST OF PARAMETER TYPES   *
!*    P(FPP)='('{(HOLE)(FPDEL)(NAMELIST)(MARK)}*')',0.                 *
!*                                                                     *
!*    THE LIST OF PARAMETER LOOKS LIKE:-                               *
!*    S1 = PTYPE FOR PARAM<<16! DIMENSION    (DIMEN DEDUCED LATER)     *
!*    S2 = ACC <<16 ! SPARE                                            *
!*    S3 = 0                                 (RESERVED FOR FPP OF RTS) *
!*                                                                     *
!*    ON ENTRY P IS AT ALT OF FPP (WHICH MAY BE NULL)                  *
!***********************************************************************
%INTEGER OPBOT, PP
      OPHEAD=0; OPBOT=0
      NPARMS=0;                         ! ZERO PARAMETERS AS YET
      %WHILE A(P)=1 %CYCLE;             ! WHILE SOME(MORE) FPS
         PP=P+1+FROMAR2(P+1);           ! TO NEXT FPDEL
         P=P+3;                         ! TO ALT OF FPDEL
         CFPDEL;                        ! GET TYPE & ACC FOR NEXT GROUP
         %UNTIL A(P-1)=2 %CYCLE;        ! DOWN <NAMELIST> FOR EACH DEL
            BINSERT(OPHEAD,OPBOT,PTYPE<<16,ACC<<16,0)
            NPARMS=NPARMS+1
            P=P+3
         %REPEAT
         P=PP
      %REPEAT
      P=P+1
%END
%ROUTINE CFPDEL
!***********************************************************************
!*    SET UP PTYPE & ACC FOR A FORMAL PARAMETER DEFINITION             *
!*    P<FPDEL>=<TYPE><%QNAME'>,                                        *
!*             (RT)(%NAME')(NAMELIST)(FPP),                            *
!*             '%NAME'.                                                *
!***********************************************************************
%SWITCH FP(1:3)
%INTEGER FPALT
      FPALT=A(P); P=P+1
      KFORM=0; LITL=0
      ->FP(FPALT)
FP(1):                                  ! (TYPE)(%QNAME')
      ROUT=0; CLT
      CQN(P)
      %IF TYPE=5 %AND NAM=0 %AND (ACC<=0 %OR ACC>256) %THEN %C
         FAULT(70,ACC-1,0) %AND ACC=255
      P=P+1
      ->PK
FP(2):                                  ! (RT)(%NAME')(NAMELIST)(FPP)
      ROUT=1; NAM=1
      ARR=0
      %IF A(P)=1 %THEN %START;          ! RT=%ROUITNE
         TYPE=0; PREC=0
         P=P+2
      %FINISH %ELSE %START
         P=P+1; CLT;                    ! RT=(TYPE)(FM)
         NAM=1
         %IF A(P)=2 %THEN NAM=3;        ! 1 FOR FN 3 FOR MAP
         P=P+2;                         ! PAST (%NAME') WHICH IS IGNORED
      %FINISH
      ACC=8
      ->PK
FP(3):                                  ! %NAME
      ACC=8; NAM=1
      ROUT=0; TYPE=0
      ARR=0; PREC=0
PK:   PACK(PTYPE)
%END
%ROUTINE DIAG POINTER(%INTEGER LEVEL)
!***********************************************************************
!*    PLANT CODE TO UPDATE THE DIAGNOSTIC POINTER. SINCE THE           *
!*    VALUE WILL NOT BE KNOWN TILL THE  DTABLE IS GENERATED PLANT      *
!*    NO-OPS AND OVERWRITE IN ROUTINE DTABLE                           *
!***********************************************************************
      %IF PARM_TRACE#0 %THEN %START
         PUSH(CURRINF_RAL,1,CA,0)
         PBW(LDCW,256);                 ! 256 ARBITARY BUT 0 IS OPTIMISED!
      %FINISH
%END
%ROUTINE RHEAD(%INTEGER RTNAME,AXNAME)
!***********************************************************************
!*       COMPILES CODE FOR BLOCK AND ROUTINE ENTRY                     *
!*       RTNAME IS THE RT/FN/MAP NAME (=-1 FOR %BEGIN BLOCKS)          *
!*       XNAME IS THE EXTERNAL NAME (="" FOR INTERNALS&BLOCKS          *
!*       ACTIONS INCLUDE PLANTING JUMPS ROUND RT BODY AND              *
!*       DEFINING EXTERNAL ENTRIES AS WELL AS PLANTING ENTRY CODE      *
!***********************************************************************
%INTEGER W3
%RECORD(TRIPF)%NAME CURRT
%RECORD(LISTF)%NAME LCELL
      CURRINF_SNMAX=NMAX; CURRINF_SN=N
      %IF RTNAME>=0 %THEN %START;       ! SECTION FOR ROUTINES
         LCELL==ASLIST(TAGS(RTNAME))
!
! FIRST JUMP ROUND BODY UNLESS AT TOP LEVEL OR IN COMPILER 
! OR A JUMP IS ALREADY OUTSTANDING AT THIS LEVEL
! MUST DO THIS HERE BEFORE LEVEL IS CHANGED OR LABEL LIST IS WRONG
!
         %IF PARM_COMPILER=0 %AND LEVEL>1 %AND CURRINF_JROUND=0 %START
            PLABEL=PLABEL-1
            CURRINF_JROUND=PLABEL
            ENTER JUMP(15,PLABEL,0)
         %FINISH
         RLEVEL=RLEVEL+1;  RBASE=RLEVEL
      %FINISH
      LEVEL=LEVEL+1
      CURRINF==LEVELINF(LEVEL)
      CURRINF=0
      CURRINF_RBASE=RBASE
      CURRINF_NAMES=-1
      CURRINF_DIAGINF=LEVELINF(LEVEL-1)_DIAGINF
      FAULT(34, 0, 0) %IF LEVEL=MAX LEVELS
      FAULT(105, 0, 0) %IF LEVEL>MAX LEVELS
!
! DEAL WITH EXTERNAL ENTRIES SO THAT THEY COME TO THIS POINT
! IN THE CODE. THE DESCRIPTORS SET UP ARE OF NO INTEREST TO THIS MODULE
! ONLY TO OTHER MODULES SO NO DETAILS OF THEN ARE RECORDED IN TAGS
!
      %IF RTNAME<0 %THEN W3=0 %ELSE W3=RTNAME+1
      CURRINF_L=LINE;  CURRINF_M=W3
      CURRINF_FLAG=PTYPE;                ! CURRENT BLOCK TYPE MARKER
!
! TILL LOADER COPIES GLAP TO GLA MUST CALL A FRIG ROUTINE TO DO
! THIS ESSENTIAL AS SOON AS POSSIBLE IN ANYTHING EXTERNAL
!
      CURRT==TRIPLES(UCONSTTRIP(RTHD,X'51',0,RTNAME))
      CURRT_OPND1_XTRA=AXNAME
%END
%ROUTINE RDISPLAY(%INTEGER KK)
!***********************************************************************
!*       SET UP OR COPY THE DISPLAY                                    *
!*       SINCE THIS IS IN REGISTERS ON 360 IT IS EASY                  *
!*       ALSO CLAIM STACK SPACE AND SET DIAGNOSTIC POINTERS            *
!***********************************************************************
%INTEGER TRIPNO
      %IF KK>=0 %OR LEVEL=2 %START;     ! DISPLAY NEEDED
                                        ! DONE BY THE QCODE CALL
         CURRINF_PSIZE=N;               ! REMEMBER PARAMETER SIZE FOR RTDICT
         TRIPNO=UCONSTTRIP(RDSPY,X'51',0,N)
      %FINISH
!
! IF IN DIAGNOSTIC MODE PLANT CODE TO SAVE THE LINE & ROUTINE NO OF
! THE CALLING ROUTINE AND SET UP THE NEW BLOCK/ROUTINE IDENT NO.
!
      %IF PARM_TRACE#0 %START
         %IF KK>=0 %OR LEVEL=2 %START;  ! ROUTINE NEW AREA NEEDED
            TRIPNO=UCONSTTRIP(RDAREA,X'51',0,N)
            N=N+4
            CURRINF_DIAGINF=N
            N=N+4
         %FINISH
         TRIPNO=UCONSTTRIP(RDPTR,X'51',0,LEVEL)
         DSTORE(2,RBASE,CURRINF_DIAGINF)
      %FINISH
      OLDLINE=0
      SET LINE
!
! NORMALLY CODE IS PLANTED HERE TO CHECK PARAMETERS BUT I CANNOT
! SEE HOW TO DO THIS ON PERQ ARCHITECTURE. IT MAY BE IN THE QCODE ANYHOW
!
!
! CLAIM (THE REST OF) THE STACK FRAME
!
      %IF KK>=0 %OR LEVEL=2 %START
         NMAX=N
      %FINISH
%END
%ROUTINE CUI(%INTEGER CODE)
!***********************************************************************
!*       COMPILE AN UNCONDITIONAL INSTRN WHEREEVER IT OCCURS           *
!*       CODE=0 UNCONDITIOALLY,=1 AFTER %THEN, =2 AFTER %ELSE          *
!***********************************************************************
%INTEGER MARKER,J,LNAME,TYPEP,PRECP,GWRDD,ALT,KK
%INTEGER HEAD1,BOT1,NOPS
%SWITCH SW(1:9)
         REPORTUI=0
         ALT=A(P)
         ->SW(ALT)
SW(1):                                ! (NAME)(APP)(ASSMNT?)
      P=P+1; MARKER=P+FROMAR2(P)
      %IF A(MARKER)=1 %THEN %START
         J=P+2; P=MARKER+2
         ASSIGN(A(MARKER+1),J)
      %FINISH %ELSE %START
         P=P+2
         CNAME(0)
         P=P+1
      %FINISH
AUI:  J=A(P); P=P+1
      %IF J=1 %THEN CUI(CODE)
      %RETURN
SW(2):                                  ! -> (NAME)(APP)
      CURRINF_NMDECS=CURRINF_NMDECS!1
      CURR INST=1 %IF CODE=0
      LNAME=FROM AR2(P+1)
      J=A(P+3); P=P+4
      %IF J=2 %THEN %START;             ! SIMPLE LABEL
         ENTER JUMP(15,LNAME,0)
         REPORTUI=1
      %FINISH %ELSE %START;             ! SWITCH LABELS
         COPY TAG(LNAME)
         GWRDD=SNDISP;                  ! BYTE DISP OF CASEJUMP
         %UNLESS OLDI=LEVEL %AND TYPE=6 %START
            FAULT(4,0,LNAME); P=P-1; SKIP APP
            %RETURN
         %FINISH
         CSEXP(X'41')
         KK=GWRDD-(CA+2)
         %IF KK>=-128 %THEN PB2(JMPB,KK) %ELSE PBW(JMPW,KK-1)
         REPORTUI=1
      %FINISH
      %RETURN
SW(3):                                  ! RETURN
      FAULT(30,0,0) %UNLESS CURRINF_FLAG&X'3FFF'=X'1000'
      P=P+1
RET:  PB1(RETURN)
      REPORT UI=1
      CURR INST=1 %IF CODE=0
         %IF CA>30000 %AND WORKA_PLABS(1)<30000 %THEN REPEAT PROLOGUE
      %RETURN
SW(4):                                 ! %RESULT(ASSOP)(EXPR)
      PTYPE=CURRINF_FLAG&X'3FFF'; UNPACK
      %IF PTYPE>X'1000' %AND A(P+1)#3 %THEN %START;! ASSOP #'->'
         %IF A(P+1)=1 %AND NAM#0 %AND A(P+5)=4 %AND A(P+6)=1 %START
            P=P+7; TYPEP=TYPE; PRECP=PREC; J=P
            CNAME(4)
            DSTORE(4,RLEVEL,0);         ! INTO RESULT WORDS
            FAULT(81,0,0) %UNLESS A(P)=2; P=P+1
            FAULT(83,CURRINF_M-1,FROMAR2(J)) %C
               %UNLESS TYPEP=TYPE %AND PRECP=PREC
            ->RET
         %FINISH
         %IF A(P+1)=2 %THEN %START;     ! ASSOP='='
            P=P+2
            %IF NAM#0 %THEN TYPE=1;     ! MAPS HAVE INTEGER RESULTS
            %IF TYPE=5 %THEN %START
               CSTREXP(32);             ! FULL VIRTAD
               DSTORE(4,RLEVEL,0)
            %FINISH %ELSE %START
               %IF PREC<4 %THEN PREC=4
               %IF NAM=0 %THEN KK=PREC<<4!TYPE %ELSE KK=X'51'
               CSEXP(KK)
               DSTORE(BYTES(KK>>4),RLEVEL,0)
            %FINISH; ->RET
         %FINISH
      %FINISH
      FAULT(31,0,0)
      P=P+2; SKIP EXP;                  ! IGNORE SPURIOUS RESULT
      %RETURN
SW(5):                                  ! %MONITOR (AUI)
      PB1(LDC0);                        ! ERR=0
      PB1(LDC0);                        ! EXTRA=0
      PB4(LDAP,LDC0,MMS2,MMS2)
      PB3(CALLXB,1,0)
      GXREF(MDEP,0,0,CA-3)
      P=P+1; ->AUI
SW(6):                                 ! %STOP
      KK=UCONSTTRIP(XSTOP,X'51',0,0)
      P=P+1
      CURR INST=1 %IF CODE=0
      REPORTUI=1
      %RETURN
SW(7):                                  !'%SIGNAL'(EVENT')(N)(OPEXPR)
      P=P+5
      KK=INTEXP(J,X'41');               ! EVENT NO TO J
      FAULT(26,J,0) %UNLESS KK=0 %AND 1<=J<=15
      HEAD1=0; NOPS=0
      PUSH(HEAD1,X'51'<<16!1,256*J,0);  ! EVENT<<8 AS CONST
      BOT1=HEAD1
      %IF A(P)=1 %START;                ! SUBEVENT SPECIFIED
         PUSH(HEAD1,ANDL,0,0);          ! OPERATOR &
         PUSH(HEAD1,X'51'<<16!1,255,0); ! CONST=F'255'
         P=P+4; TORP(HEAD1,BOT1,NOPS)
         BINSERT(HEAD1,BOT1,ORL,0,0);   ! OPERATOR !
         NOPS=NOPS+2
      %FINISH
      EXPOP(HEAD1,BOT1,NOPS,X'51');     ! EVALUATE
      %IF CURRINF_NMDECS&16 #0 %START;   ! IN AN 'ON' GROUP
         %IF CURRINF_FLAG<=2 %START;     ! IN A BEGIN BLOCK
            DIAGPOINTER(LEVEL-1);       ! TO NEXT OUTER BLOCK
         %FINISH %ELSE %START;          ! 'ON IN A RT/FN/MAP
            PB1(NOOP)
         %FINISH
      %FINISH
      PPJ(0,2)
      CURR INST=1 %IF CODE=0
      REPORTUI=1; %RETURN
SW(8):                                  ! %EXIT
SW(9):                                  ! %CONTINUE
      ALT=ALT&7;                        ! 0 FOR EXIT 1 FOR CONTINUE
      %IF EXITLAB=0 %THEN FAULT(54+ALT,0,0) %AND %RETURN
      KK=INTEGER(ADDR(EXITLAB)+4*ALT)
      ENTER JUMP(15,KK&X'FFFFFF',B'10'!KK>>31)
      REPORTUI=1
      CURR INST=1 %IF CODE=0
%END
%ROUTINE CIFTHEN(%INTEGER MARKIU,MARKC,MARKUI,MARKE,MARKR,SKIP)
!***********************************************************************
!*    THIS ROUTINE COMPILES CONDITIONAL EXPRESSIONS.IT REQUIRES THE    *
!*    FOLLOWING PARAMETERS TO BE SET TO THEIR A .R. ENTRY.             *
!*    MARKIU TO THE ENTRY FOR P(%IU)                                   *
!*    MARKC  TO THE ENTRY FOR P(COND)                                  *
!*    MARKUI TO THE ENTRY FOR (FIRST OCCURRENCE OF)  P(UI)             *
!*    MARKE  TO THE ENTRY FOR P(ELSE')  - =0 FOR BACKWARDS CONDITION   *
!*    MARKR  TO ENTRY FOR P(RESTOFIU)   - =0 FOR BACKWARDS CONDITION   *
!***********************************************************************
%INTEGER ALTUI,CCRES,ELRES,THENLAB,ELSELAB,USERLAB,REPORT,START, %C
         ELSEALT,K,CS
%CONSTINTEGER NULL ELSE=4
%SWITCH ESW(1:NULL ELSE)
      SET LINE %UNLESS SKIP=YES
      MARKIU=A(MARKIU);                 ! ALT OF IU 1=%IF,2=%UNLESS
      PLABEL=PLABEL-1
      THENLAB=PLABEL
      START=0; CS=0;                    ! NO START IN CONDITION YET
      CS=1 %IF STARSIZE>100;            ! LONG JUMPS FOR COMPLEX STMTS
      ELSELAB=0;                        ! MEANS NO ELSE CLAUSE
      P=MARKC
      %IF MARKR>0 %AND A(MARKR)<=2 %THEN %C
         START=1 %AND CS=CHECK BLOCK(MARKR+1,MARKC);! '%START' OR '%THENSTART'
      %IF MARKE#0 %AND LEVEL<2 %AND START=0 %THEN FAULT(57,0,0)
      USERLAB=-1
      %IF START#0 %THEN ALTUI=0 %ELSE ALTUI=A(MARKUI)
      %IF ALTUI=2 %AND A(MARKUI+3)=2 %THEN %C
         USERLAB=FROM AR2(MARKUI+1);    ! UI = SIMPLE LABEL
      %IF 8<=ALTUI<=9 %AND EXITLAB#0 %START; ! VALID EXIT
         %IF ALTUI=8 %THEN USERLAB=EXITLAB %ELSE USERLAB=CONTLAB
      %FINISH
!
      %IF SKIP=YES %THEN %START;        ! NO CODE NEEDED
         %IF START#0 %START
            P=MARKR+1
            CSTART(2,1);                ! NO CODE
            MARKE=P
         %FINISH
         CCRES=1;                       ! NO CODE FOR ELSE
         ->ELSE
      %FINISH
!
      %IF USERLAB>=0 %THEN %START;      ! FIRST UI IS'->'<LABEL>
         CURRINF_NMDECS=CURRINF_NMDECS!1
         CCRES=CCOND(0,3-MARKIU,USERLAB&X'FFFFFF',USERLAB>>31)
         %IF CCRES#0 %THEN CCRES=CCRES!!3;! CONDITION BACKWARDS!
         THENLAB=0;                     ! NO THENLAB IN THIS CASE
         REPORT=1;                      ! UI TRANSFERED CONTROL
      %FINISH %ELSE %START
         CCRES=CCOND(1,MARKIU,THENLAB,B'11'!!START!!CS)
         %IF START#0 %THEN %START;      ! %THEN %START
            %IF CCRES=0 %START;         ! CONDITIONAL
               FAULT(57,0,0) %IF LEVEL<2
               CURRINF_NMDECS=CURRINF_NMDECS!1
            %FINISH
            P=MARKR+1
            CSTART(CCRES,1)
            %IF A(P)<=2 %THEN PLABEL=PLABEL-1 %AND ELSELAB=PLABEL
            MARKE=P
            REPORT=LAST INST
         %FINISH %ELSE %START
            %IF CCRES#2 %START
               P=MARKUI; CUI(1)
               REPORT=REPORTUI
            %FINISH %ELSE %START;       ! FIRST UI NEVER EXECUTED
               REPORT=1
            %FINISH
         %FINISH
      %FINISH
ELSE:                                   ! ELSE PART
      %IF MARKE=0 %THEN ELSEALT=NULL ELSE %ELSE ELSEALT=A(MARKE)
      %IF ELSEALT<NULL ELSE %THEN PLABEL=PLABEL-1 %AND ELSELAB=PLABEL
      P=MARKE+1
      %IF REPORT=0=CCRES %AND ELSEALT<NULL ELSE %THEN %START
         REPORT=1
         K=B'10'
         %IF (ELSEALT=3 %AND STARSIZE<100) %OR %C
            (ELSEALT=1 %AND CHECK BLOCK(P,P)#0) %THEN K=B'11'
         ENTER JUMP(15,ELSELAB,K);      ! LONG(?) JUMP BUT SAVE ENV
      %FINISH
      %IF THENLAB>0 %THEN ELRES=ENTER LAB(THENLAB,B'11'!REPORT<<2)
                                        ! CONDITIONAL&MERGE OR REPLACE
      ->ESW(ELSEALT)
ESW(1):                                 ! '%ELSESTART'
      %IF CCRES=0 %THEN CURRINF_NMDECS=CURRINF_NMDECS!1
      CSTART(CCRES,2)
      REPORT=LAST INST
      ->ENTER ELSELAB
ESW(2):                                 ! '%ELSE' (%IU) ETC
      MARKE=0; MARKUI=0
      MARKR=P+1+FROMAR2(P+1)
      %IF A(MARKR)=3 %THEN %START
         MARKE=MARKR+1+FROM AR2(MARKR+1)
         MARKUI=MARKR+3
      %FINISH
      %IF CCRES=1 %OR SKIP=YES %THEN K=YES %ELSE K=NO
      CIFTHEN(P,P+3,MARKUI,MARKE,MARKR,K)
      REPORT=0;                         ! CANT TELL IN GENERAL
      ->ENTER ELSELAB
ESW(3):                                 ! '%ELSE'<UI>
      %IF CCRES#1 %THEN %START
         %IF START#0 %THEN SET LINE;    ! FOR CORRECT LINE IF FAILS IN UI
         %IF THENLAB=0 %THEN K=0 %ELSE K=2
         CUI(K)
         REPORT=REPORTUI
      %FINISH
ENTER ELSELAB:
      %IF ELSELAB>0 %THEN ELRES=ENTER LAB(ELSELAB,B'11'!REPORT<<2)
                                        ! CONDITIONAL MERGE
ESW(NULL ELSE):                         ! NULL ELSE CLAUSE
%END
%INTEGERFN CHECKBLOCK(%INTEGER P,PIN)
!***********************************************************************
!*    WORK OUT IF START-FINISH OR CYCLE REPEAT IS SHORT ENOUGH TO      *
!*    MANAGE WITH BYTE JUMP. PIN ALLOWS THE CONDITION TO BE INCLUDED   *
!*    IN THE TEST WHERE RELEVANT.                                      *
!***********************************************************************
%INTEGER SIZE
      SIZE=FROMAR4(P)-PIN
      %IF SIZE<64 %OR (PARM_OPT=0 %AND SIZE<128) %THEN %RESULT=1
      %RESULT=0
%END
%ROUTINE CSTART(%INTEGER CCRES,CODE)
!***********************************************************************
!*    COMPILE A COMPLETE START-FINISH BLOCK BY RECURSION               *
!*    IF START NEVER EXECUTED SKIP TO CORRESPONDING FINISH             *
!*    CODE=0 WAS UNCONDITIONAL NOW SHOULD BE UNUSED                    *
!*    CODE=1 AFTER THEN                                                *
!*    CODE=2 AFTER ELSE                                                *
!*    CODE=3 AFTER ONEVENT                                             *
!*    P ON ENTRY TO FORWARD POINTER TO THE RIGHT FINISH                *
!*    P ON EXIT TO THE ELSE CLAUSE AFTER THE RIGHT FINISH              *
!***********************************************************************
%INTEGER SKIPCODE,FINISHAR,OLDNEXTP,OLDLINE
      SKIPCODE=NO
      %IF 1<=CODE<=2 %AND CCRES!CODE=3 %THEN SKIPCODE=YES;! NEVER EXECUTED
      FINISHAR=FROMAR4(P);              ! TO START OF AR FOR FINISH
      %IF FINISHAR<=P %THEN ABORT;      ! FOR TESTING
      OLDLINE=LINE;                     ! FOR ERROR MESSAGES
      %CYCLE;                           ! THROUGH INTERVENING STATMNTS
         OLDNEXTP=NEXTP
         %IF SKIP CODE=NO %THEN COMPILE A STMNT %ELSE %START
            LINE=A(NEXTP+3)<<8!A(NEXTP+4)
            STARSIZE=A(NEXTP)<<16+A(NEXTP+1)<<8+A(NEXTP+2)
            NEXTP=NEXTP+STARSIZE
         %FINISH
      %REPEAT %UNTIL OLDNEXTP>=FINISHAR;! HAVING COMPILED FINISH
      P=FINISHAR+6;                     ! TO ELSE CLAUSE
!
      %IF A(P)<=3 %AND CODE#1 %THEN FAULT(45+CODE,OLDLINE,0)
      %IF SKIPCODE=YES %THEN LAST INST=1
%END
%ROUTINE CCYCBODY(%INTEGER UA,ELAB,CLAB)
!***********************************************************************
!*    COMPILES A CYCLE REPEAT BODY BY RECURSION                        *
!*    ON ENTRY P IS TO FORWARD POINTER. ON EXIT TO ALT OF UNTIL        *
!*    UA = O IF UNTIL NOT ALLOWED                                      *
!*    ELAB&CLAB ARE LABELS FOR ELSE & CONTINUE                         *
!***********************************************************************
%INTEGER FINISHAR,OLDLINE,SAVEE,SAVEC
      FINISHAR=FROMAR4(P)
      %IF FINISHAR<=P %THEN ABORT
      OLDLINE=LINE; SAVEE=EXIT LAB; SAVEC=CONTLAB
      EXITLAB=ELAB; CONTLAB=CLAB
      %WHILE NEXTP<=FINISHAR %CYCLE
         COMPILE A STMNT
      %REPEAT
      EXIT LAB=SAVEE; CONTLAB=SAVEC
      P=FINISHAR+6
      %IF A(P)=1 %AND UA=0 %THEN FAULT(12,OLDLINE,0)
%END

%ROUTINE CLOOP(%INTEGER ALT,MARKC,MARKUI)
!***********************************************************************
!*    ALT=1 FOR %WHILE, =2 FOR %UNTIL, =3 FOR %FOR                     *
!*    MARKC IS TO THE CONDITION OR CONTROL CLAUSE                      *
!*    MARKUI IS TO THE UI, SPECIAL FOR %CYCLE                          *
!***********************************************************************
%INTEGER L1,L2,L3,L4,CCRES,ELRES,FLINE,TRIP
%INTEGER FORNAME,INITP,REPMASK,FORPT,FORWORDS
%RECORD(RD) INITOPND,STEPOPND,FINALOPND,DIFFOPND,ZOPND,OPND
%RECORD(TRIPF) %NAME CURRT
%ROUTINESPEC FOREXP(%RECORD(RD) %NAME EOPND, %INTEGER TT)
%ROUTINESPEC VALIDATE FOR
%SWITCH SW(0:6)
      P=MARKC
      SFLABEL=SFLABEL-2
      L1=SFLABEL; L2=L1+1
!
! SET L3 FOR ALTS 0,5&6 ONLY
!
      L3=0
      %IF B'1100001'&1<<ALT#0 %THEN L3=SFLABEL-1 %AND SFLABEL=L3
!
! UPDATE THE LINE NUMBER FOR ALTS 1 TO 3 ONLY
!
      %IF 1<=ALT<=3 %THEN SET LINE
!
! ENTER THE FIRST LABEL FOR ALL ALTS EXCEPT 3 & 6
!
      %IF B'0110111'&1<<ALT#0 %THEN ELRES=ENTER LAB(L1,0)
      ->SW(ALT)
SW(0):                                  ! %CYCLE
      C CYC BODY(1,L2,L3)
      ELRES=ENTER LAB(L3,B'011')
      %IF A(P)=1 %START;                ! %REPEAT %UNTIL <COND>
         SET LINE
         P=P+1; CCRES=CCOND(0,1,L1,0)
      %FINISHELSE ENTER JUMP(15,L1,0)
      ELRES=ENTER LAB(L2,B'011')
WAYOUT:                                 ! REMOVE LABELS NOT REQUIRED
      REMOVE LAB(L1)
      REMOVE LAB(L2)
      REMOVE LAB(L3) %IF L3>0
      %RETURN
SW(1):                                  ! UI WHILE COND
      CCRES=CCOND(0,1,L2,B'11')
      P=MARKUI
      CUI(1)
      ENTER JUMP(15,L1,0);             ! UNCONDITIONALLY BACK TO WHILE
      ELRES=ENTER LAB(L2,B'111');       ! CONDITIONAL(?) & REPLACE ENV
      ->WAYOUT
SW(2):                                  ! UI %UNTIL COND
      P=MARKUI
      CUI(1)
      P=MARKC
      CCRES=CCOND(0,1,L1,0)
      ->WAYOUT
SW(6):                                  ! %FOR ... %CYCLE
SW(3):                                  ! UI %FOR ....
      L4=SFLABEL-1; SFLABEL=L4
      FORNAME=FROMAR2(P)
      INITP=P+2; P=INITP
      COPY TAG(FORNAME)
      FAULT(91,0,FORNAME) %UNLESS TYPE=1 %AND 4<=PREC<=5 %AND ROUT=0=ARR
      FORPT=PTYPE&255;                  ! SAVE TYPE&PREC OF CONTROL
      FORWORDS=WORDS(FORPT>>4);         ! NO OF WORDS FOR TEMPS
      WARN(4,FORNAME) %UNLESS I=RBASE
!
      SKIP EXP;                         ! P TO STEP EXPRSN
      FOR EXP(STEPOPND,1);              ! STEP TO REG AND TEMP
      %IF STEPOPND_FLAG=0 %START
         FAULT(92,0,0) %IF STEPOPND_D=0; ! ZERO STEP
      %FINISHELSESTART
         %IF PARM_OPT#0 %THENSTART
            TRIP=URECTRIP(STPCK,FORPT,0,STEPOPND); ! VALIDATE STEP
         %FINISH
      %FINISH
!
      FOR EXP(FINALOPND,1);             ! EVALUATE FINAL
!
      P=INITP
      FOR EXP(INITOPND,0);              ! INITIAL VALUE TO ETOS
      %IF PARM_OPT#0 %THEN VALIDATE FOR
!
      DIFFOPND_D=BRECTRIP(SUB,FORPT,0,INITOPND,STEPOPND)
      DIFFOPND_S1=FORPT<<16!REFTRIP
!
! HAVE DIFFOPND SET TO INIT-STEP.  FOR COMPUTED STEPS NOW MUST CHECK
! FOR NEGATIVE TRAVERSES. FOR FIXED STEPS THIS CAN BE SET
! IN MASK FOR REPEATING
!
      %IF STEPOPND_FLAG>0 %THENSTART
         OPND_D=BRECTRIP(SUB,FORPT,0,FINALOPND,DIFFOPND)
         OPND_S1=FORPT<<16!REFTRIP
         OPND_D=BRECTRIP(IDIV,FORPT,0,OPND,STEPOPND)
         ZOPND_D=0; ZOPND_S1=FORPT<<16!SCONST
         CURRT==TRIPLES(BRECTRIP(COMP,FORPT,0,OPND,ZOPND))
         CURRT_X1=4;                    ! MASK FOR <0
         ENTER JUMP(4,L4,B'10')
         REPMASK=8
      %FINISHELSESTART
         %IF STEPOPND_D>0 %THEN REPMASK=10 %ELSE REPMASK=12
      %FINISH
!
      DIFFOPND_D=URECTRIP(FORPRE,FORPT,0,DIFFOPND)
      ELRES=ENTER LAB(L1,0);            ! LABEL FOR REPEATING
      DIFFOPND_D=URECTRIP(FORPR2,FORPT,USE ESTACK,DIFFOPND)
!
      CURRT==TRIPLES(BRECTRIP(COMP,FORPT,0,DIFFOPND,FINALOPND))
      CURRT_X1=REPMASK
      ENTER JUMP(REPMASK,L4,B'10')
      OPND_D=BRECTRIP(ADD,FORPT,0,DIFFOPND,STEPOPND)
      OPND_S1=FORPT<<16!REFTRIP
      ZOPND_S1=FORPT<<16!DNAME
      ZOPND_D=FORNAME
      CURRT==TRIPLES(BRECTRIP(VASS,FORPT,0,ZOPND,OPND))
      CURRT_X1=FORPT;                   ! VASS USES THIS FIELD
!
      P=MARKUI;                         ! TO UI OR '%CYCLE'(HOLE)
      %IF ALT=3 %THENSTART;             ! DEAL WITH CONTROLLED STMNTS
         CUI(0)
      %FINISHELSESTART
         CCYCBODY(0,L2,L3)
         ELRES=ENTER LAB(L3,B'011');    ! LABEL FOR CONTINUE
      %FINISH
      TRIP=UNAMETRIP(PRELOAD,FORPT,0,FORNAME)
      ENTER JUMP(15,L1,0)
      ELRES=ENTERLAB(L4,B'11')
      TRIP=UCONSTTRIP(FORPOST,FORPT,0,0)
      REMOVE LAB(L4)
      ELRES=ENTERLAB(L2,B'111');        ! REPLACE ENV
                                        ! WHEN MERGE ENV
      %IF STEPOPND_FLAG>1 %THEN RETURN WSP(FORWORDS,STEPOPND_XTRA)
      %IF FINALOPND_FLAG>1 %THEN RETURN WSP(FORWORDS,FINALOPND_XTRA)
      ->WAYOUT
SW(4):                                  ! %WHILE COND %CYCLE
      SET LINE
      CCRES=CCOND(0,1,L2,0)
      C CYC BODY(0,L2,L1)
      ENTER JUMP(15,L1,0)
      ELRES=ENTER LAB(L2,B'111');       ! CONDITIONAL & REPLACE ENV
      ->WAYOUT
SW(5):                                  ! %UNTIL ... %CYCLE
                                        ! ALSO %CYCLE... %REPEAT %UNTIL
                                        ! MARKUI TO %CYCLE
      P=MARKUI
      FLINE=LINE
      C CYC BODY(0,L2,L3)
      P=MARKC; ELRES=ENTER LAB(L3,B'011'); ! CONTINUE LABEL IF NEEDED
      LINE=FLINE; SET LINE
      CCRES=CCOND(0,1,L1,0)
      ELRES=ENTER LAB(L2,B'011')
      ->WAYOUT
%ROUTINE FOR EXP(%RECORD(RD) %NAME EOPND, %INTEGER TOTEMP)
!***********************************************************************
!*    P INDEXES EXPRESSION.  IF CONST PUT INTO EVALUE OTHERWISE        *
!*    COMPILE TO ETOS AND STORE IN TEMP IF TOTEMP#0                    *
!***********************************************************************
%INTEGER INP,VAL
      INP=P; P=P+3
      %IF INTEXP(VAL,FORPT)=0 %AND IMOD(VAL)<X'FFFF' %START
         EOPND=EXPOPND;                 ! EXPRESSION A LITERAL CONST
         %RETURN
      %FINISH
      EOPND=EXPOPND
      %IF TOTEMP#0 %START
         GET WSP(VAL,FORWORDS!X'80000000')
         EOPND_S1=FORPT<<16!LOCALIR
         EOPND_D=RBASE<<16!VAL; EOPND_XTRA=VAL
         EOPND_D=BRECTRIP(LASS,FORPT,0,EXPOPND,EOPND)
         EOPND_FLAG=REFTRIP
      %FINISH
%END
%ROUTINE VALIDATE FOR
!***********************************************************************
!*    INITIAL VALUE IN ETOS                                            *
!***********************************************************************
%INTEGER J
%RECORD(RD) OPND
      %IF INITOPND_FLAG!STEPOPND_FLAG!FINALOPND_FLAG=0 %START
         J=FINALOPND_D-INITOPND_D;      ! ALL CONSTANT CAN CHECK NOW
         %IF(J//STEPOPND_D)*STEPOPND_D#J %THEN FAULT(93,0,0)
         %RETURN
      %FINISH
      %IF STEPOPND_FLAG=0 %AND IMOD(STEPOPND_D)=1 %THENRETURN
!
! CHECK BY PLANTING CODE
!
      OPND_D=BRECTRIP(SUB,FORPT,0,FINALOPND,INITOPND)
      OPND_S1=FORPT<<16!REFTRIP
      J=BRECTRIP(FORCK,FORPT,0,OPND,STEPOPND)
%END
%END
%ROUTINE ASSIGN(%INTEGER ASSOP,P1)
!***********************************************************************
!*       HANDLES ARITHMETIC,STRING & ADDRESS ASSIGNMENTS TO VARIABLES  *
!*       FORMAL PARAMETERS AND DOPEVECTORS                             *
!*       ASSOP:-                                                       *
!*        1 IS FOR '=='                                                *
!*        2 IS FOR '='                                                 *
!*        3 IS FOR '<-' (JAM TRANSFER)                                 *
!*        4 IS FOR '->' (UNCONDITIONAL RESOLUTION)                     *
!*                                                                     *
!*       P POINTS TO THE EXPRESSION. P1 TO THE NAME ON LHS             *
!***********************************************************************
%INTEGER Q,KK,TYPEP,PRECP,PTYPEP,JJJ,P2,JJ,B,D,HEAD2,BOT2, %C
         ACCP,II,HEAD1,NOPS,TPCELL,LVL,BOT1,LHNAME,RHNAME
%RECORD(LISTF)%NAME LHCELL
%SWITCH SW(0:4);                       ! TO SWITCH ON ASSOP
      P2=P
      LHNAME=A(P1)<<8!A(P1+1)
      LHCELL==ASLIST(TAGS(LHNAME))
      P=P1; REDUCE TAG;                 ! LOOK AT LH SIDE
      PTYPEP=PTYPE; JJ=J
      KK=K; II=I; LVL=OLDI
      TPCELL=TCELL; ACCP=ACC
      P=P2; TYPEP=TYPE; PRECP=PREC;     ! SAVE USEFUL INFO FOR LATER
      -> SW(ASSOP)
SW(2):SW(3):                            ! ARITHMETIC ASSIGNMENTS
      %IF TYPE=3 %THEN ->RECOP
      TYPE=1 %UNLESS TYPE=2 %OR TYPE=5; ! IN CASE OF RUBBISHY SUBNAMES
      ->ST %IF TYPE=5;                  ! LHS IS A STRING
BACK: HEAD1=0; BOT1=0;                  ! CLEAR TEMPORAYRY LIST HEADS
      HEAD2=0; BOT2=0
      TYPE=1 %UNLESS TYPE=2;            ! DEAL WITH UNSET NAMES
      TYPEP=TYPE
      NOPS=1<<18+1
      PTYPE=PTYPEP; UNPACK
      %IF NAM=0=ARR %AND A(P1+2)=2=A(P1+3) %THEN %START;! SCALAR
         BINSERT(HEAD1,BOT1,PTYPE<<16!2,P1,LHNAME)
      %FINISH %ELSE %START
         %IF ARR>0 %AND LHCELL_S1>>16&15#3 %START;! SCALAR ARRAYS
            P=P1
            COPY TAG(LHNAME);           ! SET SNDISP ETC FOR AATORP
            AATORP(NOPS,HEAD1,BOT1,ARR,II,KK)
         %FINISH %ELSE %START
            P=P1; CNAME(3);             ! 32 BIT ADDR TO STACK
            BINSERT(HEAD1,BOT1,PTYPE<<16!9,P1,LHNAME)
         %FINISH
      %FINISH
      P=P2+3
      TORP(HEAD2,BOT2,NOPS);            ! RHS TO REVERSE POLISH
      BINSERT(HEAD2,BOT2,VASS+ASSOP-2,LHNAME<<16!PTYPEP,0);! = OR <-OPERATOR
      ASLIST(BOT1)_LINK=HEAD2
      HEAD2=0; BOT1=BOT2
      EXPOP(HEAD1,BOT1,NOPS,256+PRECP<<4+TYPEP); ! PLANT CODE
      %RETURN
ST:                                    ! STRINGS
!
! PICK OFF NULL STRINGS AND SUBSTITUTE A CRAFTY STB FOR S=""
!
      %IF A(P+3)=4 %AND A(P+4)=2 %AND %C
         A(P+5)=X'35' %AND A(P+10)=0 %AND A(P+11)=2 %THEN %START
         Q=P+12
         P=P1; CNAME(2)
         PB2(LDC0,STB)
         P=Q; %RETURN
      %FINISH
      P=P1; CNAME(3);                   ! 3 WORD POINTER TO ESTACK
      PB1(MMS);                         ! MAX LENGTH OFF ESTACK
      %IF ASSOP=3 %THEN PB1(MMS2) %ELSE PB1(LDC0);! TOP HALF OF STRING POINTER
      P=P2; CSTREXP(32)
      %IF ASSOP=3 %THEN %START
         PB1(MMS2)
         PPJ(0,18)
      %FINISH %ELSE %START
         PB2(LDC0,MES);                 ! MAX LENGTH BACK
         PB2(STLATE,X'63')
         PB1(SAS)
      %FINISH
      %RETURN
!
! THIS SECTION DEALS WITH OPERATIONS ON COMPLETE RECORDS
!
RECOP:                                   ! LHS IS RECORD WITHOUT SUBNAME
      Q=TSEXP(JJJ)
      %IF Q=1 %AND JJJ=0 %START;        ! CLEAR A RECORD TO ZERO
         P=P1; CNAME(3)
         BULKM(0,ACC,0)
      %FINISH %ELSE %START
         ->BACK %UNLESS TYPE=3 %AND A(P2+3)=4 %AND A(P2+4)=1
         P=P2+5; CNAME(3)
         ACCP=ACC
         %UNLESS A(P)=2 %THEN FAULT(66,0,LHNAME) %AND ->F00
         P=P1; CNAME(3)
         %IF ASSOP=2 %AND ACCP#ACC %THEN %C
            FAULT(67,LHNAME,FROMAR2(P2+5)) %AND ->F00
         %IF ACCP>ACC %THEN ACCP=ACC
         BULKM(1,ACCP,0)
      %FINISH
      P=P2; SKIP EXP
      %RETURN
SW(4):                                 ! RESOLUTION
      P=P1; CNAME(2)
      P=P2;
      %IF TYPE=5 %THEN CRES(0) %ELSE %START
         SKIP EXP
         FAULT(71,0,LHNAME) %UNLESS TYPE=7
      %FINISH
      %RETURN
SW(1):                                 ! '==' AND %NAME PARAMETERS
      ->F81 %UNLESS A(P2+3)=4 %AND A(P2+4)=1
      FAULT(82,0,LHNAME) %AND ->F00 %UNLESS NAM=1 %AND LITL#1
                                        ! ONLY NON-CONST POINTERS ON LHS OF==
      P=P2+5
      RHNAME=A(P)<<8!A(P+1)
      ->ARRNAME %IF ARR=1
      CNAME(3);                      ! DESCRPTR TO NEST
      ->F81 %UNLESS A(P)=2;             ! NO REST OF EXP ON RHS
      Q=P+1; P=P1
      ->F83 %UNLESS TYPE=TYPEP %AND PREC=PRECP
      ->F86 %UNLESS OLDI<=LVL %OR BASE=0 %OR NAM#0
                                        ! GLOBAL == NONOWN LOCAL
      CNAME(6)
      %IF TYPEP=5 %OR(TYPEP=1 %AND PRECP=3) %START;! 3 WORD POINTERS
         PB4(REPL2,MMS2,INCB,2)
         CAB; PB3(TLATE2,STIND,MES2);   ! STORE 3RD WORD
      %FINISH
      PB3(EXCH2,TLATE3,STDW)
!      NOTE ASSMENT(REG,1,LHNAME)
      P=Q; %RETURN
ARRNAME:
      CNAME(12);                        ! ARRAYHEAD TO ESTACK
      ->F83 %UNLESS TYPE=TYPEP %AND PREC=PRECP %AND ARR>0
      ->F86 %UNLESS OLDI<=LVL %OR BASE=0 %OR NAM#0
                                        ! GLOBAL == NONOWN LOCAL
      B=BASE; D=DISP
      ->F81 %UNLESS A(P)=2
      Q=P+1; P=P1
      CNAME(11);                        ! 32BIT ADDRESS OF POINTER TO ETOS
      PB1(PERMD);                       ! ADRESS UNDER HEAD
      PTLATE(5)
      PB2(ROPS,38);                     ! AND STORE HEAD
!      NOTE ASSMENT(-1,1,LHNAME)
      P=Q; %RETURN
F83:  FAULT(83,LHNAME,RHNAME); ->F00
F86:  FAULT(86,LHNAME,RHNAME); ->F00
F81:  FAULT(81,0,LHNAME)
F00:
      P=P2; SKIP EXP
%END
%ROUTINE CSEXP(%INTEGER MODE)
!***********************************************************************
!*       COMPILE A SIGNED EXPRESSION TO REGISTER 'REG' IN MODE 'MODE'  *
!*       MODE=1 FOR %INTEGER, =2 REAL, =3 LONG,=0 INTEGER %IF POSSIBLE *
!*       MODE=5 FOR ADDRESS EXPRESSNS(IE LEAVE ANY CONSTANT IN 'ADISP')*
!***********************************************************************
%INTEGER EXPHEAD,NOPS,EXPBOT,PP
      EXPHEAD=0; EXPBOT=0
      NOPS=0
      P=P+3
      TORP(EXPHEAD,EXPBOT,NOPS)
      PP=P
!
      EXPOP(EXPHEAD,EXPBOT,NOPS,MODE)
      P=PP
%END
%INTEGERFN CONSTEXP(%INTEGER PRECTYPE)
!***********************************************************************
!*    COMPILES AN EXPRESSION WHICH SHOULD EVALUATE TO A CONSTANT OF    *
!*    TYPE 'PRECTYPE'. P AS FOR FN INTEXP.                             *
!***********************************************************************
%INTEGER EXPHEAD,EXPBOT,NOPS,RES
      EXPHEAD=0; EXPBOT=0; NOPS=0; RES=0
      TORP(EXPHEAD,EXPBOT,NOPS)
      ->WAYOUT %UNLESS NOPS&X'00040000'=0
      EXPOP(EXPHEAD,EXPBOT,NOPS,X'200'+PRECTYPE)
      %IF EXPOPND_FLAG=3 %THEN RES=EXPOPND_XTRA %AND ->WAYOUT
      ->WAYOUT %UNLESS EXPOPND_FLAG<=1
      RES=ADDR(EXPOPND_D)
WAYOUT:
      %RESULT=RES
%END
%INTEGERFN INTEXP(%INTEGERNAME VALUE,%INTEGER PRECTYPE)
!***********************************************************************
!*    COMPILES AN EXPRESSION WHICH SHOULD EVALUATE TO A CONSTANT       *
!*    VALUE RETURNED IN VALUE. RESULT#0 IF FAILED TO EVALUATE          *
!*    IN THIS CASE RESULT IS IN ETOS. USED FOR BOUND CALCULATIONS      *
!*    P POINTS TO P(+') IN (+')(OPERNAD)(RESTOFEXPR)                   *
!***********************************************************************
%INTEGER EXPHEAD,EXPBOT,NOPS,CODE,SPTYPE,SACC
      EXPHEAD=0; EXPBOT=0; NOPS=0; CODE=0
      SPTYPE=PTYPE; SACC=ACC;           ! CALLED IN DECLARATIONS
      TORP(EXPHEAD,EXPBOT,NOPS)
      EXPOP(EXPHEAD,EXPBOT,NOPS,X'200'+PRECTYPE)
      CODE=1 %UNLESS EXPOPND_FLAG<=1 %AND EXPOPND_PTYPE=PRECTYPE
      VALUE=EXPOPND_D
      ACC=SACC; PTYPE=SPTYPE
      UNPACK
      %RESULT=CODE
%END
%ROUTINE TORP(%INTEGERNAME HEAD,BOT,NOPS)
!***********************************************************************
!*       CONVERT THE SIGNED EXPRESSION INDEXED BY P INTO REVERSE       *
!*      POLISH NOTATION. THE REVERSE POLISH LIST IS ADDED TO 'HEAD'    *
!*      WHICH MAY CONTAIN ANOTHER EXPRESSION. THE NUMBER OF OPERATORS  *
!*      IS ADDED TO NOPS.                                              *
!*      N.B. AN INTEGER EXPRESSION IS A SPECIAL CASE OF A REAL EXPRSN  *
!*    THE TOP 20 BITS OF NOPS ARE USED TO RETURN DETAILS OF THE EXPR   *
!*    THESE BITS SIGNIFY AS FOLLOWS:-                                  *
!*    1<<17    CONTAINS VARIABLE OF MORE THAN 32 BITS                  *
!*    1<<18    NOT CONSTANT EXPRSSN IE CONTAINS AT LEAST 1 VARIABLE    *
!*    1<<19    COMPLEX IE CONTAINS FN CALL OR NEEDS DR TO EVALUATE     *
!***********************************************************************
%SWITCH OPERAND(1:3)
%CONSTBYTEINTEGERARRAY PRECEDENCE(0:20)=0,3,3,4,5,5,4,3,3,4,4,5,5,3,5,5,
                                        0(3),3,5;
%CONSTBYTEINTEGERARRAY OPVAL(0:20)=0,ADD,SUB,ANDL,IEXP,REXP,MULT,NONEQ,
                  ORL,IDIV,RDIV,LSHIFT,RSHIFT,ADD,IEXP,REXP,0(3),LNEG,NOTL;
%INTEGER RPHEAD,PASSHEAD,SAVEHEAD,REAL,REALOP,COMPLEX,%C
         OPERATOR,OPPREC,OPND,C,D,E,RPTYPE,RPINF,BDISP,%C
         OPNAME,OPMASK,XTRA,RPBOT,OPSTK,OPPSTK,PASSBOT
%RECORD(LISTF)%NAME LCELL
!
         PASSHEAD=0; RPHEAD=0; SAVEHEAD=0
         REAL=0; REALOP=0; BDISP=0
         RPBOT=0; OPSTK=0; OPPSTK=0
!
         C=A(P)
         %IF 2<=C<=3 %THEN %START;     ! INITIAL '-' OR '\'
            NOPS=NOPS+1
                                       ! '-' =(11,3)   '\' =(10,5)
            OPSTK=C+17
            OPPSTK=PRECEDENCE(OPSTK)
            OPMASK=1<<(19+C);          ! - %OR !!
         %FINISH %ELSE OPMASK=0
NEXTOPND:OPND=A(P+1); P=P+2
         COMPLEX=0; XTRA=0
         -> OPERAND(OPND);             ! SWITCH ON OPERAND
OPERAND(1):                            ! NAME
         OPNAME=A(P)<<8+A(P+1)
         LCELL==ASLIST(TAGS(OPNAME))
         PTYPE=LCELL_S1>>16
         %IF PTYPE=X'FFFF' %THEN PTYPE=X'57';! NAME NOT SET
         TYPE=PTYPE&7; PREC=PTYPE>>4&15
         %IF PTYPE=SNPT %THEN PTYPE=LCELL_S2 %AND UNPACK
         %IF PTYPE&X'FF00'=X'4000' %AND A(P+2)=2=A(P+3) %C
            %AND 1<=TYPE<=2 %THEN %START; ! CONST VAR
            LCELL_S1=LCELL_S1!X'8000';  ! SET USED BIT
            RPINF=LCELL_S2; XTRA=LCELL_S3
            RPTYPE=1; PTYPE=PTYPE&255
            %IF TYPE=1 %AND PREC<=5 %AND IMOD(RPINF)<=X'7FFF'%C
               %THEN RPTYPE=0 %AND PTYPE=X'41'
            %IF PREC=7 %THEN RPTYPE=3
            REAL=1 %IF TYPE=2
            P=P+2; ->SKNAM
         %FINISH
         XTRA=OPNAME
         OPMASK=OPMASK!(COMPLEX<<19)
         RPTYPE=2; RPINF=P; PTYPE=X'51' %IF PTYPE=X'57'
         %IF TYPE=5 %THEN FAULT(76,0,OPNAME) %AND RPTYPE=0 %AND %C
            PTYPE=X'51'
         %IF TYPE=3 %THEN %START
            D=P; KFORM=LCELL_S3&X'FFFF'
            C=COPY RECORD TAG(E); P=D;
         %FINISH %ELSE %START
            %IF PTYPE&X'300'#0 %START;! ARRAYS
               COPY TAG(OPNAME)
               BINSERT(RPHEAD,RPBOT,PTYPE<<16!2,OPNAME,XTRA)
               AATORP(NOPS,RPHEAD,RPBOT,ARR,I,K)
               P=RPINF; RPTYPE=IFETCH
               XTRA=0; RPINF=0
            %FINISH
         %FINISH
         %IF PREC>=6 %THEN OPMASK=OPMASK!1<<17;! MORE THAN 32 BITS
         %IF TYPE=2 %THEN REAL=1
         P=P+2
SKNAM:   %IF A(P)=2 %THEN P=P+1 %ELSE SKIP APP
         %IF A(P)=1 %THEN P=P+3 %AND ->SKNAM
         P=P+2
INS:     %IF RPTYPE=2 %THEN OPMASK=OPMASK!1<<18
         BINSERT(RPHEAD,RPBOT,PTYPE<<16!COMPLEX<<8!RPTYPE,RPINF,XTRA)
         -> OP
OPERAND(2):                            ! CONSTANT
         PTYPE=A(P); D=PTYPE>>4
         %IF D>=6 %THEN OPMASK=OPMASK!1<<17;! MORE THAN 32 BIT OPERAND
         C=PTYPE&7
         %IF D=4 %THEN %START
            RPINF=FROM AR2(P+1)
            PTYPE=X'51'
         %FINISH %ELSE RPINF=FROM AR4(P+1)
         REAL=1 %IF C=2; RPTYPE=1
         %IF D=6 %THEN XTRA=FROM AR4(P+5)
         %IF C=5 %THEN %START;      ! STRING CONSTANT
            FAULT(77,0,0); RPINF=1; RPTYPE=0
            P=P+A(P+1)+3; PTYPE=X'51'
         %FINISH %ELSE %START
            %IF D=7 %THEN XTRA=ADDR(A(P+1)) %AND RPTYPE=3
            %IF PTYPE=X'51' %AND X'FFFF8000'<=RPINF<=X'7FFF' %THEN %C
               RPTYPE=0 %AND PTYPE=X'41'
            P=P+2+BYTES(D)
         %FINISH; -> INS
OPERAND(3):                            ! SUB EXPRESSION
         PASSHEAD=0; PASSBOT=0
         P=P+3
         TORP(PASSHEAD,PASSBOT,NOPS)
         REAL=1 %IF TYPE=2
!         CONCAT(RPHEAD,PASSHEAD)
         %IF RPBOT=0 %THEN RPHEAD=PASSHEAD %ELSE %C
            ASLIST(RPBOT)_LINK=PASSHEAD
         RPBOT=PASSBOT
         P=P+1
OP:                                     ! DEAL WITH OPERATOR
         -> EOE %IF A(P-1)=2;           ! EXPR FINISHED
         OPERATOR=A(P)
!
! THE STRING OPERATOR '.' CAUSES CHAOS IN AN ARITHMETIC EXPRSN
! SO FAULT IT AND CHANGE IT TO THE INNOCUOUS '+'
!
         %IF OPERATOR=CONCOP %THEN FAULT(78,0,0)
         OPPREC=PRECEDENCE(OPERATOR)
         C=OPVAL(OPERATOR)
         %IF C=RDIV %OR C=REXP %THEN REAL=1
         NOPS=NOPS+1
!
! UNLOAD THE OPERATOR STACK OF ALL OPERATORS WHOSE PRECEDENCE IS
! NOT LOWER THAN THE CURRENT OPERATOR. AN EMPTY STACK GIVES'-1'
! AS PRECEDENCE.
!
         %WHILE OPPREC<=OPPSTK&31 %CYCLE
            BINSERT(RPHEAD,RPBOT,OPVAL(OPSTK&31),0,0)
            OPSTK=OPSTK>>5; OPPSTK=OPPSTK>>5
         %REPEAT
!
! THE CURRENT OPERATOR CAN NOW BE STORED
!
         OPSTK=OPSTK<<5!OPERATOR
         OPPSTK=OPPSTK<<5!OPPREC
         -> NEXTOPND
EOE:                                   ! END OF EXPRESSION
                                       ! EMPTY REMAINING OPERATORS
         %WHILE OPSTK#0 %CYCLE
            BINSERT(RPHEAD,RPBOT,OPVAL(OPSTK&31),0,0)
            OPSTK=OPSTK>>5
         %REPEAT
         PTYPE=REAL+1
         TYPE=PTYPE
!         CONCAT(RPHEAD,HEAD)
         %IF HEAD=0 %THEN BOT=RPBOT %ELSE %C
            ASLIST(RPBOT)_LINK=HEAD
         HEAD=RPHEAD;                ! HEAD BACK TO TOP OF LIST
         NOPS=NOPS!OPMASK
         %END
%ROUTINE EXPOP(%INTEGERNAME HEAD,BOT,%INTEGER NOPS,MODE)
!***********************************************************************
!*    EVALUATE A LIST OF OPERAND AND'NOPS' OPERATORS AND LEAVE         *
!*    THE RESULT IN REG                                                *
!*    INHEAD HOLDS THE LIST THE BOTTOM BYTE OF STREAM 1 DEFINES THE    *
!*    ENTRY AS FOLLOWS:-                                               *
!*       0 = SHORT (INTEGER) CONSTANT <18 BITS --S2=CONSTANT           *
!*       1 = OTHER CONSTANT    S2 (+S3 IF NEEDED) = CONSTANT           *
!*       2 = VARIABLE S2 POINT TO AR ENTRY FOR NAME&SUBSCRIPTS         *
!*      (3 = DOPE VECTOR ITEM IF NEEDED)                               *
!*      (4 = CONDITONAL EXPRESSION AS IN ALGOL)                        *
!*       7 = INTERMEDIATE RESULT UNDER LNB  S2=DISPLCMNT FROM LNB      *
!*       8 = INTERMEDIATE RESULT STACKED                               *
!*       9 = INTERMEDIATE RESULT IN A REGISTER S2 = REG                *
!*                                                                     *
!*       10-19 = UNARY OPERATOR S2=OP S3 =EXTRA                        *
!*       20 UP = BINARY OPERATOR                                       *
!*                                                                     *
!*       MODE HAS TYPE & PREC REQD +256 BIT IF NO RESULT REQD          *
!***********************************************************************
%ROUTINESPEC PSEVAL
%ROUTINESPEC CHECKOP(%RECORD(RD)%NAME OP,%INTEGER DONTLOAD)
!
%INTEGERARRAY OPERAND(0:2),STK(0:99)
%RECORD(LISTF)%NAME LIST
%RECORD(RD)%NAME OPND1,OPND2,OPND
%RECORD(TRIPF)%NAME CURRT
 
!
%INTEGER C,D,KK,JJ,COMM,XTRA,INHEAD,NDEPTH,CURR TRIP, %C
         STPTR,CONSTFORM,CONDFORM,SAVEP,INITTRIP
!
! CORULES GIVE INFORMATION ON OPERATORS.
!     BTM 4 BITS HAVE TYPE CONVERSION RULES(SEE COERCET)
!     NEXT 4 BITS HAVE PREC RULES (SEE COERCEP)
!     2**8 SET IF COMMUTATIVE
!     2**9 SET DONT LOAD OPERAND2
!     2**10 SET DONT LOAD OPERAND1
!
%CONSTHALFINTEGERARRAY CORULES(128:148)= %C
                                        X'1FF'{+},X'FF'{-},
                                        X'1F1'{!!},X'1F1'{!},
                                        X'1FF'{*},X'F1'{//},
                                        X'F2'{/},X'1F1'{&},X'41'{>>},
                                        X'41'{<<},X'243'{**},
                                        X'1FF'{COMP},X'FF'{DCOMP},
                                        X'200'{VMY},X'1F1'{COMB},
                                        X'214'{ASSIGN=},
                                        X'254'{ASSIGN<-},X'241'{****},
                                        X'201'{ARR SCALE},
                                        X'001'{ARR INDEX},
                                        X'500'{INDEXED FETCH};
%CONSTINTEGERARRAY PTYPECH(10:19)=0,0,X'11',0,-X'10',X'10',-X'10',0(3);

!
      STPTR=0; NDEPTH=0; CONSTFORM= MODE&512
      INITTRIP=NEXTTRIP
      CONDFORM=MODE&256
      SAVEP=P
      INHEAD=HEAD
      PSEVAL
NEXT: LIST==ASLIST(INHEAD)
      C=LIST_S1; XTRA=LIST_S2
      JJ=C&255; D=INHEAD
      INHEAD=LIST_LINK
      -> OPERATOR %IF JJ>=10
!
! ANY OPERAND WHICH MAY NEED DR OR B OR ACC IN THEIR EVALUATION
! EG FUNCTIONS,ARRAY ELEMENTS ETC ARE FETCHED AND STACKKED FIRST
!
      OPND1==ASLIST(D)
      STK(STPTR)=D
      STPTR=STPTR+1
      ABORT %IF STPTR>99
ANYMORE:
      ->NEXT %UNLESS INHEAD=0
      OPND1==ASLIST(STK(STPTR-1))
      EXPOPND=OPND1
      ->FINISH
OPERATOR:
      %IF JJ<128 %THEN KK=1 %ELSE KK=2;  ! UNARY OR BINARY
      %CYCLE KK=KK,-1,1
         STPTR=STPTR-1
         OPERAND(KK)=STK(STPTR)
      %REPEAT
      COMM=1
      OPND1 == ASLIST(OPERAND(1))
      %IF OPND1_FLAG=8 %START
         NDEPTH=NDEPTH-WORDS(OPND1_PTYPE>>4)
      %FINISH
      %IF JJ>=128 %THEN %START
         OPND2==ASLIST(OPERAND(2))
         %IF OPND2_FLAG=8 %START
            NDEPTH=NDEPTH-WORDS(OPND2_PTYPE>>4)
         %FINISH
      %FINISH %ELSE OPND2==RECORD(0)
      %IF JJ=32 %THEN COMM=2;           ! DSIDED RESULT=2ND OPERAND
                                        ! ALL OTHERS RESULT=1ST OPERAND
      %IF OPND1_FLAG<2 %AND (JJ<128 %OR OPND2_FLAG<2) %THEN %C
         CTOP(JJ,MASK,XTRA,OPND1,OPND2)
      %IF JJ#0 %THEN %START;            ! CODE REQUIRED OP TRIPLE
         %IF JJ<128 %THEN C=0 %ELSE C=CORULES(JJ)
         CURR TRIP=NEW TRIP
         CHECKOP(OPND1,C&(2**10))
         CHECKOP(OPND2,C&(2**9)) %UNLESS JJ<128
         CURRT==TRIPLES(CURR TRIP)
         CURRT_DPTH=NDEPTH
         %IF OPND1_PTYPE=X'31' %THEN CURRT_OPTYPE=X'41' %ELSE %C
            CURRT_OPTYPE=OPND1_PTYPE
         %IF JJ<128 %START;              ! UNARY(TYPECHANGE)OPN
            CURRT_OPERN=JJ
            CURRT_OPTYPE=CURRT_OPTYPE+PTYPECH(JJ)
         %FINISH %ELSE CURRT_OPERN=JJ
         %IF JJ=COMP %OR JJ=DCOMP %THEN MASK=FCOMP(LIST_S2)
         CURRT_CNT=0
         CURRT_FLAGS=1!(C>>1&128)
         %IF OPND1_FLAG<=1 %OR OPND2_FLAG<=1 %THEN %C
            CURRT_FLAGS=CURRT_FLAGS!64;! HAS CONST OPERAND
         %UNLESS OPND1_FLAG=8 %OR 35<=JJ<=36 %THEN %C
            CURRT_FLAGS=CURRT_FLAGS!LOAD OP1
         %IF JJ>=128 %AND OPND2_FLAG#8 %THEN CURRT_FLAGS=CURRT_FLAGS!4
                                        ! PREVENT OPTIMISING BYTE ARRAY SCALE
                                        ! AS THESE CREATE EXTRA WORD
                                        ! WHICH DEFEATS ALGORITHMS
         %IF JJ=39 %AND LIST_S2>>20=1 %THEN %C
            CURRT_FLAGS=CURRT_FLAGS! DONT OPT
         CURRT_X1=LIST_S2
         CURRT_OPND1=OPND1
         %IF JJ>=128 %THEN CURRT_OPND2=OPND2
         OPND1_FLAG=8
         OPND1_PTYPE=CURRT_OPTYPE
         OPND1_UPTYPE=0
         OPND1_D=CURR TRIP
         NDEPTH=NDEPTH+WORDS(CURRT_OPTYPE>>4)
      %FINISH
      STK(STPTR)=OPERAND(COMM)
      STPTR=STPTR+1
      ->ANYMORE
FINISH:
      CHECKOP(EXPOPND,0) %IF EXPOPND_FLAG<8;! DONT UP USE COUNT
      PTYPE=EXPOPND_PTYPE
      TYPE=PTYPE&7; PREC=PTYPE>>4
      P=SAVEP
      ASLIST(BOT)_LINK=ASL
      ASL=HEAD
      HEAD=0; BOT=0
      %RETURN
%ROUTINE PSEVAL
!***********************************************************************
!*    PERFORMS A PSEUDO EVALUATION ON THE EXPRESSION TO DETERMINE      *
!*    THE POSITION OF ANY TYPE CHANGES AND THEN INSERTS                *
!*    THESE UNARY OPERATIONS                                           *
!***********************************************************************
%ROUTINESPEC COERCET(%INTEGER RULES)
%ROUTINESPEC COERCEP(%INTEGER RULES)
%INTEGER TMPHEAD,INHEAD,C,JJ,NEXT
%RECORD(RD)%NAME OPND1
%RECORD(RD)OPND2
%RECORD(LISTF)%NAME CELL
      PRINT LIST(HEAD) %AND ABORT %UNLESS ASLIST(BOT)_LINK=0
      TMPHEAD=0
      INHEAD=HEAD
!
      %WHILE INHEAD#0 %CYCLE
         CELL==ASLIST(INHEAD)
         C=CELL_S1
         NEXT=CELL_LINK
         JJ=C&255;                      ! FLAG
         %IF JJ<10 %START;              ! AN OPERAND
            %IF C>>20&15<=3 %THEN C=C&X'FF0FFFFF'!X'400000'
            PUSH(TMPHEAD,C,CELL_S2,INHEAD)
         %FINISH %ELSE %START;          ! AN OPERATOR
            %IF JJ>=128 %START;          ! BINARY OPERATOR
               POP(TMPHEAD,OPND2_S1,OPND2_D,OPND2_XTRA)
               OPND1==ASLIST(TMPHEAD);  ! MAPPING SAVES POP&PUSH
               C=CORULES(JJ)
               %IF C&15#0 %THEN COERCET(C&15)
               %IF C>>4&15#0 %THEN COERCEP(C>>4&15)
               OPND1_XTRA=INHEAD;       ! IN CASE(FURTHER)TYPE CHANGE
            %FINISH
         %FINISH
         INHEAD=NEXT
      %REPEAT
!
! FINAL COERCION ON RESULT
!
      POP(TMPHEAD,OPND2_S1,OPND2_D,OPND2_XTRA)
      PRINT LIST(HEAD) %AND ABORT %UNLESS TMPHEAD=0
      %IF CONDFORM=0 %START
         %IF MODE&7=1 %AND OPND2_PTYPE&7=2 %THEN FAULT(25,0,0)
         %IF OPND2_PTYPE&7=1 %AND MODE&7=2 %THEN %START
            INSERT AFTER(OPND2_XTRA,FLOAT,0,0);! FLOAT
            OPND2_PTYPE=OPND2_PTYPE+X'11'
            NOPS=NOPS+1
         %FINISH
         C=MODE>>4&15;                  ! TARGET PREC
         %WHILE C<OPND2_PTYPE>>4&15 %CYCLE
            INSERT AFTER(OPND2_XTRA,SHRTN,0,0)
            OPND2_PTYPE=OPND2_PTYPE-X'10'
            NOPS=NOPS+1
         %REPEAT
         %WHILE C>OPND2_PTYPE>>4&15 %CYCLE
            INSERT AFTER(OPND2_XTRA,LNGTHN,0,0)
            OPND2_PTYPE=OPND2_PTYPE+X'10'
            NOPS=NOPS+1
         %REPEAT
      %FINISH
      PRINTLIST(HEAD) %IF PARM_DCOMP#0 %AND PARM_SMAP#0
      BOT=ASLIST(BOT)_LINK %WHILE ASLIST(BOT)_LINK#0
      %RETURN
%ROUTINE COERCET(%INTEGER RULES)
!***********************************************************************
!*         RULES=1 BOTH OPERANDS INTEGER ELSE ERROR                    *
!*         RULES=2 FORCE BOTH OPERAND TO BE OF TYPE REAL               *
!*         RULES=3 OPND1 ONLY TO BE REAL(FOR **)                       *
!*         RULES=4 OPND2 TO BE OPND 1(ASSIGNMENT)                      *
!*         RULES=15  BOTH OPERANDS TO BE OF LARGEST TYPE               *
!***********************************************************************
%INTEGER PT1,PT2
      PT1=OPND1_PTYPE&7
      PT2=OPND2_PTYPE&7
      %IF RULES=4 %THEN PT1=CELL_S2&7;  ! ORIGINAL PT FOR ARRAYS ETC
      %IF (RULES=1 %OR RULES=15 %OR RULES=4) %AND PT1=1=PT2 %C
         %THEN %RETURN
      %IF RULES=1 %OR (RULES=4 %AND PT1=1) %C
         %THEN FAULT(24,0,0) %AND %RETURN
      %IF PT1=1 %THEN OPND1_PTYPE=OPND1_PTYPE+X'11' %AND %C
         INSERT AFTER(OPND1_XTRA,FLOAT,0,0) %AND NOPS=NOPS+1
       %IF PT2=1 %AND (RULES=2 %OR RULES=4 %OR RULES=15) %THEN %START
         OPND2_PTYPE=OPND2_PTYPE+X'11'
         NOPS=NOPS+1
         INSERT AFTER(OPND2_XTRA,FLOAT,0,0)
      %FINISH
%END
%ROUTINE COERCEP(%INTEGER RULES)
!***********************************************************************
!*       RULES DEFINE COERCION AS FOLLOWS:                             *
!*       RULES=1 FORCE OPND2 TO BE OPND1(ASSIGNMENT)                   *
!*       RULES=2 OPERAND 1 TO BE 'STANDARD' INTEGER                    *
!*       RULES=4 OPERAND 2 TO BE 'STANDARD' INTEGER                    *
!*       RULES=5 AS RULES=1 BUT FOR <- ASSIGNMENT                      *
!*       RULES=6 BOTH OPERANDS TO BE 'STANDARD' INTEGER                *
!*       RULES=15 BOTH OPERANDS TO THE LARGEST PRECISION               *
!***********************************************************************
%INTEGER PREC1,PREC2,TPREC,OP
%RECORD(RD)%NAME OPND
      %IF RULES=6 %THEN COERCEP(4) %AND RULES=2
      PREC1=OPND1_PTYPE>>4
      PREC2=OPND2_PTYPE>>4
      %IF RULES=5 %OR RULES=1 %START;   !  ASSIGN
         PREC1=CELL_S2>>4&15;           ! ORIGINAL PREC FOR ARRAY ASSIGN
         %IF PREC2>PREC1 %START
            %CYCLE
               %IF RULES=1 %THEN OP=SHRTN %ELSE OP=JAMSHRTN
               INSERT AFTER(OPND2_XTRA,OP,0,0)
               NOPS=NOPS+1
               OPND2_PTYPE=OPND2_PTYPE-X'10'
               PREC2=PREC2-1
            %REPEAT %UNTIL PREC1=PREC2
            %RETURN
         %FINISH %ELSE RULES=1;         ! IN CASE LENGTHEN NEEDED
      %FINISH
      %IF PREC1=3 %THEN PREC1=4 %AND OPND1_PTYPE=OPND1_PTYPE+X'10'
      %IF PREC2=3 %THEN PREC2=4 %AND OPND2_PTYPE=OPND2_PTYPE+X'10'
      %IF 2<=RULES<=4 %START
         %IF RULES<=2 %THEN OPND==OPND1 %ELSE OPND==OPND2
         %IF OPND_PTYPE=X'51' %THEN %START
            INSERTAFTER(OPND_XTRA,SHRTN,0,0)
            OPND_PTYPE=OPND_PTYPE-X'10'
            NOPS=NOPS+1
         %FINISH
         %RETURN
      %FINISH
      %IF PREC1<PREC2 %THEN TPREC=PREC2 %AND OPND==OPND1 %ELSE %C
         TPREC=PREC1 %AND OPND==OPND2
      %WHILE OPND_PTYPE>>4&15<TPREC %CYCLE
         INSERT AFTER(OPND_XTRA,LNGTHN,0,0);! LENGTHEN
         OPND_PTYPE=OPND_PTYPE+X'10'
         NOPS=NOPS+1
      %REPEAT
%END
%END
%ROUTINE CHECKOP(%RECORD(RD)%NAME OPND,%INTEGER DONTLOAD)
!***********************************************************************
!*       LOAD OPERAND OPND INTO TOP OF NEST(ESTACK)                    *
!***********************************************************************
%INTEGER K,KK
%RECORD(TRIPF)%NAME REFTRIP
%SWITCH SW(0:9)
      K=OPND_FLAG
      PTYPE=OPND_PTYPE
      TYPE=PTYPE&15
      PREC=PTYPE>>4
      %IF K>9 %THEN ABORT
      ->SW(K)
SW(0):                                  ! CONSTANT < 16 BITS
SW(1):                                  ! LONG CONSTANT
      %RETURN
SW(3):                                  ! 128 BIT CONSTANT
      ABORT
SW(2):                                  ! NAME
      %RETURN %IF DONTLOAD#0
      P=OPND_D
      %IF OPND_UPTYPE=0 %AND OPND_XB=0 %AND OPND_PTYPE#X'57' %THEN %C
         OPND_D=OPND_XTRA %AND %RETURN
      CNAME(2)
LDED:
      %IF PREC<4 %THEN OPND_PTYPE=OPND_PTYPE&15!X'40'
      OPND_FLAG=8; OPND_D=TRIPLES(0)_BLINK
SW(8):                                  ! TRIPLE
      REFTRIP==TRIPLES(OPND_D)
      %IF REFTRIP_CNT=0 %THEN REFTRIP_PUSE=CURR TRIP
      REFTRIP_CNT=REFTRIP_CNT+1
      %RETURN
SW(4):                                  ! CONDITIONAL EXPRESSION
      ABORT
SW(5):                                  ! INTEGER AS ADDR(NAME.APP)
      %RETURN %IF DONTLOAD#0
      P=OPND_D
      CNAME(4);                         ! GET 32 BIT ADDRESS
      OPND_PTYPE=X'51';                 ! ADDRESSES ARE INTEGERS
      ->LDED
SW(6):                                  ! OPTIMISED INTERMEDIATE
      ABORT
SW(7):                                  ! I-R IN A STACK FRAME
      %RETURN
SW(9):                                  ! I-R IN A REGISTER
%END
%END;                                  ! OF ROUTINE EXPOP
%INTEGERFN CCOND(%INTEGER CTO,IU,FARLAB,JFLAGS)
!***********************************************************************
!*       COMPILES <IU><SC><RESTOFCOND>%THEN<UI1>%ELSE<UI2>             *
!*       CTO=0 JUMP TO FARLAB MUST BE PLANTED IF COND UNCONDITIONAL    *
!*       CTO#0 JUMP MAY BE OMITTED                                     *
!*       IU=1 FOR %IF   =2 FOR UNLESS. FARLAB TO GO ON UI2             *
!*       THE ROUTINE MAKES FOUR PASSES THROUGH THE CONDITION           *
!*       PASS 1 ANALYSES THE STRUCTURE AND DECIDES TO BRANCH ON TRUE   *
!*       (TF=2)   OR ON FALSE (TF=1) FOR EACH COMPARISON               *
!*       PASS 2 WORKS OUT WHERE THE BRANCHES OF PASS 1 SHOULD GO TO    *
!*       PASS 3 ASSIGNS LABEL NUMBERS                                  *
!*       PASS 4 EVALUATES COMPARISIONS AND PLANTS THE CODE             *
!*                                                                     *
!*       ON ENTRY P POINTS TO <SC> IN<HOLE><SC><RESTOFCOND>            *
!*       RESULT=0 CONDITION COMPILED                                   *
!*       RESULT=1 UNCONDITIONALLY TO 1ST ALTERNATIVE                   *
!*       RESULT=2 UNCONDITIONALLY TO 2ND ALTERNATIVE(FARLAB)           *
!***********************************************************************
!%ROUTINESPEC WRITE CONDLIST
%ROUTINESPEC SKIP SC(%INTEGER REVERSED)
%ROUTINESPEC SKIP COND(%INTEGER REVERSED)
%INTEGERFNSPEC CCOMP
%%ROUTINESPEC JUMP(%INTEGER MASK,LAB,FLAGS)
%ROUTINESPEC NOTE JUMP(%INTEGER LAB)
%ROUTINESPEC LAB UNUSED(%INTEGER LAB)
%ROUTINESPEC OMIT TO(%INTEGER LAB)
!
! FCOMP HAS BC MASKS FOR EACH STRING COMPARATOR.
! THE FIRST 7 ARE TO BRANCH IF TRUE WITH NORMAL COMPARISON
! THE SECOND SEVEN ARE TO BRANCH IF TRUE WITH BACKWARDS COMPARISON
!
!
%INTEGER PIN,PP,II,L,CPTR,CMAX,LL,BITMASK,LLA
%RECORDFORMAT CF(%BYTEINTEGER TF,CMP1,CMP2,LABU,LVL,JMP,REV,JUMPED, %C
                 %INTEGER LABNO,SP1,SP2)
%RECORD(CF)%ARRAY CLIST(0:30)
%RECORD(CF)%NAME C1,C2
!
! PASS 1.   ANALYSES THE CONDITION
!
         PIN=P;                        ! SAVE INITIAL AR POINTER
         CPTR=1; L=3;                  ! LEVEL=3 TO ALLOW 2 LOWER
         C1==CLIST(CPTR);              ! SET UP RECORD FOR FIRST CMPARSN
         C1=0
         SKIP SC(0);                   ! SKIP THE 1ST CMPARSN
         SKIP COND(0);                   ! AND ANY %AND/%OR CLAUSES
         C1_LVL=2;                     ! LEVEL =-1 FOR %IF/%THEN ENTRY
         C1_TF=IU
         CMAX=CPTR+1
         C1==CLIST(CMAX); C1=0
         C1_LVL=1;                     ! LEVEL =-2 FOR ELSE ENTRY
         C1_TF=3-IU;                    ! C1_REV NEVER SET HERE (PDS HOPES)
         C1_LABNO=FARLAB
         PP=P;                         ! SAVE FINAL AR POINTER
         FAULT(108,0,0) %IF CMAX>29;     ! TOO COMPLICATED
!
! PASS 2 WORKS OUT WHERE TO JUMP TO
! THE JUMP IS FORWARD TO THE START OF THE CLAUSE WITH A DIFFERENT
! CONNECTOR (AND/OR) PROVIDED THIS IS AT A LOWER LEVEL THAN THE BRANCH
! AND ALSO AT A LOWER LEVEL THAN THE LOWEST POINT REACHED ENROUTE
!
! ALSO CONTAINS PASS 3 (TRIVIAL)
! ASSIGN LABELS WHERE LABU SHOWS THEY ARE REQUIRED
!
         %CYCLE CPTR=1,1,CMAX-1
            C1==CLIST(CPTR)
            L=C1_LVL; LL=L;            ! LL FOR LOWEST LEVEL ENROUTE
            %CYCLE II=CPTR+1,1,CMAX+1
              C2==CLIST(II)
              %EXIT %IF C1_TF#C2_TF %AND C2_LVL<LL
              %IF C2_LVL<LL %THEN LL=C2_LVL
            %REPEAT
            C1_JMP=II;                 ! CLAUSE TO JUMP TO
            C2_LABU=C2_LABU+1
             %IF C1_CMP2#0 %OR C1_CMP1=8 %START; ! D-SIDED OR RESLN
                                       ! REQIUIRES A LABEL ON THE
               C1_LABU=C1_LABU+1;      ! THE NEXT SIMPLE CONDITION
            %FINISH
            %IF C1_LABU#0 %AND C1_LABNO<=0 %THEN PLABEL=PLABEL-1 %C
                                           %AND C1_LABNO=PLABEL
         %REPEAT
!
! PASS 4 GENERATE THE CODE
! MAINTAIN BIT MASK TO HELP. 2**0 JUMP TO FAR LAB PLANTED
!                            2**1 JUMP TO INTERMEDIATE LAB PLANTED
!
!         WRITE CONDLIST %IF PARM_DCOMP=1
         BITMASK=0
         CPTR=1
         %CYCLE
            C1==CLIST(CPTR)
            LLA=CCOMP
            %IF LLA#0 %START
               OMIT TO(LLA)
               %IF CPTR>=CMAX %THEN %START
                  %IF CTO=0 %THEN ENTER JUMP(15,LLA,B'11')
                  %RESULT=2
               %FINISH
               C1==CLIST(CPTR)
            %FINISH
            %IF C1_LABNO>0 %THEN II=ENTER LAB(C1_LABNO,B'11')
            CPTR=CPTR+1
            %EXIT %IF CPTR>=CMAX
         %REPEAT
!
         P=PP;
         %RESULT=1 %IF BITMASK&1=0
         %RESULT=0
%ROUTINE LAB UNUSED(%INTEGER LAB)
!***********************************************************************
!*       A LABEL IS NOT JUMPED TO AS CONDITION ALWAYS FALSE            *
!*       REMOVE IT FROM LIST                                           *
!***********************************************************************
%INTEGER I
%RECORD(CF)%NAME C1
      %CYCLE I=CPTR,1,CMAX-1
         C1==CLIST(I)
         %IF C1_LABNO=LAB %START
            C1_LABU=C1_LABU-1;          ! COUNT DOWN USE COUNT
            %IF C1_LABU=0 %THEN C1_LABNO=0
            %RETURN
         %FINISH
      %REPEAT
%END
%ROUTINE OMIT TO(%INTEGER LAB)
!***********************************************************************
!*    A JUMP TURNS OUT TO BE UNCONDITIONAL. OMIT CODE FOR SKIPPED BIT  *
!***********************************************************************
%RECORD(CF)%NAME C1
      %CYCLE
         C1==CLIST(CPTR)
         %IF C1_LABNO>0 %START
            %IF C1_LABNO=LAB % %THEN %RETURN
            %IF C1_JUMPED>0 %THEN JUMP(JMPW,LAB,B'11') %AND %RETURN
         %FINISH
         CPTR=CPTR+1
         %EXIT %IF CPTR>=CMAX
      %REPEAT
%END
%ROUTINE SKIP SC(%INTEGER REVERSED)
!***********************************************************************
!*       REVERSED=1 FOR RECURSIVE CALL IN %NOT(SC)                     *
!*       SKIPS OVER A SIMPLE CONDITION. P ON ALT OF<SC>                *
!***********************************************************************
%SWITCH SCALT(1:3)
%INTEGER ALT
      ALT=A(P); P=P+1
      ->SCALT(ALT)
SCALT(1):                               ! <EXP><COMP><EXP><SECONDSIDE>
      C1_SP1=P-PIN
      SKIP EXP
      C1_CMP1=A(P)
      C1_REV=3*REVERSED
      P=P+1; C1_SP2=P-PIN
      SKIP EXP
      %IF A(P)=2 %THEN P=P+1 %ELSE %START
         C1_CMP2=A(P+1);              ! DEAL WITH 2ND HALF OF D-SIDED
         P=P+2; SKIP EXP
      %FINISH
      %RETURN
SCALT(2):                               ! '('<SC><RESTOFCOND>')'
       L=L+1
       SKIP SC(REVERSED)
       SKIP COND(REVERSED)
       L=L-1
      %RETURN
SCALT(3):                               ! %NOT(SC)
      SKIP SC(REVERSED!!1)
%END;                                   ! OF ROUTINE SKIP SC
%ROUTINE SKIP COND(%INTEGER REVERSED)
!***********************************************************************
!*       SKIPS OVER <RESTOFCOND>                                       *
!***********************************************************************
%INTEGER ALT,ALTP
      ALT=A(P);                         ! 1=%AND<ANDC>,2=%OR<ORC>,3=NULL
      P=P+1
      %IF ALT\=3 %THEN %START;          ! NULL ALTERNATIVE NOTHING TO DO
         %UNTIL ALTP=2 %CYCLE;          ! UNTIL NO MORE <SC>S
            C1_LVL=L; C1_TF=ALT
            C1_TF=C1_TF!!(3*REVERSED)
            CPTR=CPTR+1
            C1==CLIST(CPTR); C1=0
            SKIP SC(REVERSED)
            ALTP=A(P); P=P+1
         %REPEAT
      %FINISH
%END
!%ROUTINE WRITE CONDLIST
!%CONSTSTRING(5) %ARRAY CM(0:10)="     ","    =","   >=","    >",
!                       "    #","   <=","    <","   \=","   ->",
!                       "   ==","  \=="
!      PRINTSTRING("
! NO   TF   C1   C2   LABU   LVL  JMP  REV   LABNO JUMPED
!")
!      %CYCLE CPTR=1,1,CMAX
!         C1==CLIST(CPTR)
!         WRITE(CPTR,2)
!         WRITE(C1_TF,4)
!         PRINTSTRING(CM(C1_CMP1))
!         PRINTSTRING(CM(C1_CMP2))
!         WRITE(C1_LABU,6)
!         WRITE(C1_LVL,5)
!         WRITE(C1_JMP,4)
!         WRITE(C1_REV,4)
!         WRITE(C1_LABNO,7)
!         WRITE(C1_JUMPED,6)
!         NEWLINE
!      %REPEAT
!%END
%INTEGERFN CCOMP
!***********************************************************************
!*       COMPILES A COMPARISION: THREE DIFFERENT CASES                 *
!*       1) ARITHMETIC EXPRESSIONS EXPOP IS USED                       *
!*       2) STRING EXPRESSION AD-HOC CODE PLANTED BY THIS ROUTINE      *
!*       3) RESOLUTIONS - CRES CAN BE USED                             *
!*       4) EQUIVALENCES   INTEGER COMPARISONS ON ADDRESSES            *
!*       RESULT=0 CODE COMPILED                                        *
!*       RESULT#0 UNCODITIONAL JUMP TO LAB=RESULT                      *
!***********************************************************************
%ROUTINESPEC ACOMP(%INTEGER TF,DS)
%ROUTINESPEC ADCOMP(%INTEGER TF)
%ROUTINESPEC SCOMP(%INTEGER DS,TF,LAB,%INTEGERNAME WA)
%INTEGER HEAD1,HEAD2,NOPS,TE2,TEX2,P1,P2,FEXIT,IEXIT, %C
         CMP,BOT1,BOT2
%INTEGERARRAY WA(0:3)
!
         HEAD1=0; HEAD2=0; NOPS=0
         BOT1=0; BOT2=0
         FEXIT=CLIST(C1_JMP)_LABNO;    ! FINAL EXIT
         IEXIT=FEXIT;                  ! INTERMEDIATE EXIT (D-SIDED ETC)
         %IF C1_REV!!C1_TF=2 %AND (C1_CMP1=8 %OR C1_CMP2#0) %THEN %C
                      IEXIT=C1_LABNO
!
         P=PIN+C1_SP2
         P2=P; P1=PIN+C1_SP1
         %IF C1_CMP1=8 %THEN %START
                                       ! CONDITIONAL RESOLUTION
                                       ! NB CRES BRANCHES ON FALSE!!
            P=P1
            %IF A(P+3)=4 %AND A(P+4)=1 %START
               P=P+5; CNAME(2);      ! LH STRING TO ANY REG
               %IF A(P)=2 %THEN %START
                  %IF TYPE#5 %THEN FAULT(71,0,FROMAR2(P1+5)) %C
                      %AND %RESULT=0
                  P=P2
                  CRES(IEXIT);         ! FAILURES -> IEXIT
                  NOTE JUMP(IEXIT)
                  %IF IEXIT=FARLAB %THEN BITMASK=BITMASK!1 %ELSE %C
                     BITMASK=BITMASK!2
                  %IF C1_REV!!C1_TF=2 %THEN JUMP(JMPW,FEXIT,B'11')
                  %RESULT=0
               %FINISH
            %FINISH
            FAULT(74,0,0)
            %RESULT=0
         %FINISH
      %IF C1_CMP1>8 %THEN ->ADRCOMP
      MASK=FCOMP(C1_CMP1)
      TE2=TSEXP(TEX2)
      ->STR %IF TYPE=5
                                       ! ARITHMETIC COMPARISIONS
      P=P1+3
      TORP(HEAD1,BOT1,NOPS);            ! FIRST EXPRESSION TO REVERSE POL
      CMP=C1_CMP1
      P=P2+3
      %IF C1_CMP2#0 %THEN %START;       ! IF D-SIDED DEAL WITH MIDDLE
         ACOMP(1,1);                    ! BRANCH IEXIT %IF FALSE
         %IF MASK=15 %THEN %RESULT=IEXIT
         JUMP(MASK,IEXIT,B'11')
         P=P+5;                         ! TO THE THIRD EXPRSN
         CMP=C1_CMP2;                   ! COMPARATOR NO 2
      %FINISH
!
      ACOMP(C1_REV!!C1_TF,0);           ! SECOND OR ONLY COMPARISION
      %IF MASK=15 %THEN %RESULT=FEXIT
      JUMP(MASK,FEXIT,B'11')
      %RESULT=0
STR:                                   ! STRING COMPARISIONS
                                       ! SOME CARE IS NEEDED IN FREEING
                                       ! STRING WK-AREAS SET BY CSTREXP
      P=P1
      WA(1)=0; WA(2)=0; WA(3)=0
      %IF C1_CMP2=0 %AND 7<=FCOMP(C1_CMP1)<=8 %AND A(P2+3)=4 %AND %C
         A(P2+4)=2 %AND A(P2+5)=X'35' %AND A(P2+10)=0 %C
         %AND A(P2+11)=2 %THEN %START;  ! ="" AND #""
         CSTREXP(32)
         PB3(LDB,LDC0,FCOMP(C1_CMP1))
         PB2(LDC0,TLATE2)
         MASK=JTW
         %IF C1_REV!!C1_TF=1 %THEN MASK=REVERSE(MASK)
         JUMP(MASK,FEXIT,B'11')
         %RESULT=0
      %FINISH
      CSTREXP(48);                      ! DO NOT FREE WK-AREA
      WA(1)=VALUE;                      ! SAVE ADDRESS OF WK-AREA
      CMP=C1_CMP1
      P=P2
!
      %IF C1_CMP2#0 %THEN %START;       ! D-SIDED DEAL WITH MIDDLE
         SCOMP(1,1,IEXIT,WA(2))
         P=P+2; CMP=C1_CMP2
         %IF WA(1)#0 %THEN RETURN WSP(WA(1),268) %AND WA(1)=0
      %FINISH
!
      SCOMP(0,C1_REV!!C1_TF,FEXIT,WA(3))
      %CYCLE CMP=1,1,3
         %IF WA(CMP)#0 %THEN RETURN WSP(WA(CMP),268)
      %REPEAT
      %RESULT=0
ADRCOMP:                                ! ADRESS COMPARISONS
      ADCOMP(C1_REV!!C1_TF)
      JUMP(MASK,FEXIT,B'11')
      %RESULT=0
%ROUTINE ADCOMP(%INTEGER TF)
!***********************************************************************
!*    COMPILES AN == OR ADDRESS COMPARISON WHICH CAN NOT BE            *
!*    DOUBLESIDED. BETTER CODE COULD BE GENERATED FOR THE              *
!*    MOST COMMON CASE IE POINTERNAME==VARIABLE                        *
!************************************************************************
%INTEGER TYPEP,PRECP,LHNAME,RHNAME,FNAME,CMP
      LHNAME=A(P1+5)<<8!A(P1+6)
      FNAME=RHNAME
      RHNAME=A(P2+5)<<8!A(P2+6)
      %IF C1_CMP1=10 %THEN CMP=7 %ELSE CMP=1
      PUSH(HEAD1,COMP,CMP,0)
      BOT1=HEAD1
      NOPS=1
      P=P1+1
      ->FLT %UNLESS A(P1+3)=4 %AND A(P1+4)=1 %AND A(P+FROMAR2(P))=2
      P=P1+5; REDUCETAG
      TYPEP=TYPE; PRECP=PREC
      PUSH(HEAD1,X'51'<<16!5,P,LHNAME)
!
      FNAME=LHNAME
      P=P2+1
      ->FLT %UNLESS A(P2+3)=4 %AND A(P2+4)=1 %AND A(P+FROMAR2(P))=2
      P=P2+5; REDUCE TAG
      FAULT(83,LHNAME,RHNAME) %UNLESS TYPEP=TYPE %AND PRECP=PREC
      PUSH(HEAD1,X'51'<<16!5,P,RHNAME)
      EXPOP(HEAD1,BOT1,NOPS,256+X'51')
      %IF TF=1 %THEN MASK=REVERSE(MASK)
      %RETURN
FLT:
      FAULT(80,0,FNAME)
      MASK=7
%END
%ROUTINE ACOMP(%INTEGER TF,DS)
!***********************************************************************
!*       TYPE & PREC DEFINE THE EXPRSN IN REVERSE POLISH IN HEAD1      *
!*       THIS ROUTINE CONVERTS THE NEXT EXPRSN TO REVERSE POLISH AND   *
!*       ADDS OPERATORS FOR TYPE CHANGING(IF REQ) CMPRSN AND JUMP      *
!***********************************************************************
%INTEGER PRECP,TYPEP,REG
         PRECP=PTYPE>>4&15; TYPEP=TYPE
!
! ADD OPERATOR AT BOTTOM. EITHER COMPARE(COMP) OR DS COMPARE(DCOMP)
!
         PUSH(HEAD2,COMP+DS,CMP,0)
         BOT2=HEAD2
         NOPS=NOPS+1;                   ! FLAG COMPARE 
!
! CONVERT NEXT EXPRSN TO REVERSE POLISH AND TO THE SAME TYPE AS THE
! FIRST IF POSSIBLE. MODE=0 INTEGER IF POSSIBLE,=2 REAL, =3 LONGREAL
!
         TORP(HEAD2,BOT2,NOPS)
         %IF TYPEP>TYPE %THEN TYPE=TYPEP
!         CONCAT(HEAD1,HEAD2)
         ASLIST(BOT1)_LINK=HEAD2
         BOT1=BOT2; BOT2=0; HEAD2=0
         EXPOP(HEAD1,BOT1,NOPS,256+16*PRECP+TYPE);  ! PLANT THE CODE
         %IF DS#0 %START
            PUSH(HEAD1,INTEGER(ADDR(EXPOPND)),EXPOPND_D,EXPOPND_XTRA)
            BOT1=HEAD1
            %IF EXPOPND_FLAG=9 %START
               REG=EXPOPND_XB
            %FINISH
         %FINISH
         %IF TF=1 %THEN MASK=REVERSE(MASK)
%END
%ROUTINE SCOMP(%INTEGER DS,TF,LAB,%INTEGERNAME WA)
!***********************************************************************
!*       1ST STRING IS DEFINED BY (ACCR)                               *
!*       THIS ROUTINE EVALUATES THE NEXT STRING EXPRS AND PERFORMS     *
!*       THE COMPARISON & BRANCH.                                      *
!*       DS=0 UNLESS THIS COMPARISON IS THE FIRST HALF OF A DBLE-SIDED *
!***********************************************************************
%INTEGER MASK,D
      PB1(LDC0)
      CSTREXP(48);                   ! SAVE WK-AREA
      WA=VALUE
      %IF DS#0 %START;                  ! D-SIDED SAVE MIDDLE
         GET WSP(D,2)
         PB1(REPL2)
         DSTORE(4,RBASE,D)
      %FINISH
      PB3(LDC0,STLATE,X'52')
      PB1(FCOMP(CMP)-EQUI+EQUSTR)
      MASK=JTW
      %IF TF=1 %THEN MASK=REVERSE(MASK); ! REVERSE MASK TO JMP IF FALS
      JUMP(MASK,LAB,B'11')
      %IF DS#0 %THEN DFETCH(4,RBASE,D);! RETRIEVE MIDDLE FOR D-S
%END
%END
%ROUTINE JUMP(%INTEGER MASK,LAB,FLAGS)
!***********************************************************************
!*    CALLS ENTER JUMP WHILE MAINTAINING BITMASK                       *
!***********************************************************************
      %IF MASK=0 %THEN LAB UNUSED(LAB) %AND %RETURN
      %IF LAB=FARLAB %THEN FLAGS=JFLAGS
      ENTER JUMP(MASK,LAB,FLAGS)
      NOTE JUMP(LAB)
      %IF LAB=FARLAB %THEN BITMASK=BITMASK!1 %ELSE BITMASK=BITMASK!2
%END
%ROUTINE NOTE JUMP(%INTEGER LABEL)
!***********************************************************************
!*    RECORD LABEL JUMPED TO FOR SKIPPING COMPLEX CONDITIONS           *
!***********************************************************************
%INTEGER I
%RECORD(CF)%NAME C
      %CYCLE I=1,1,CMAX
         C==CLIST(I)
         %IF C_LABNO=LABEL %THEN C_JUMPED=C_JUMPED+1 %AND %EXIT
      %REPEAT
%END
%END;                                  ! OF CCOND
%INTEGERFN REVERSE(%INTEGER MASK)
!***********************************************************************
!*       REVERSE THE MASK FOR A JCC(MASK<=15),JAT(>15) OR JAF(>31)     *
!***********************************************************************
      %IF MASK=0 %OR MASK=15 %THEN %RESULT=MASK!!15
      %RESULT=MASK!!X'8F'
%END

%INTEGERFN ENTER LAB(%INTEGER LAB,FLAGS)
!***********************************************************************
!*       ENTER A NEW LABEL ON THE LABEL LIST FOR THE CURRENT LEVEL     *
!*       2**0  OF FLAGS  = 1  CONDITIONAL ENTRY                        *
!*       2**1  OF FLAGS  = 1  UPDATE ENVIRONMENT                       *
!*       2**2  OF FLAGS  = 1  REPLACE ENV     =0  MERGE ENV            *
!*       THE LABEL LIST                                                *
!*       S1 =   USE BITS<<8 ! LABEL ADDR                               *
!*       S2 =   UNFILLED JUMPS LIST                                    *
!*       S3 = LAB NO - RESET TO FFFF WHEN USED FOR INTERNAL LABELS     *
!*       RESULT = 1 LABEL ENTERED                                      *
!*       RESULT = 0 CONDITIONAL LABEL NOT REQUIRED                     *
!***********************************************************************
%INTEGER CELL,OLDCELL
%RECORD(TRIPF)%NAME CURRT
%RECORD(LISTF)%NAME LCELL
      CELL=CURRINF_LABEL; OLDCELL=0
      %WHILE CELL>0 %CYCLE
         LCELL==ASLIST(CELL)
         %EXIT %IF LCELL_S3=LAB
         OLDCELL=CELL; CELL=LCELL_LINK
      %REPEAT
!
      %IF CELL<=0 %THEN %START;         ! LABEL NOT KNOWN
         %IF FLAGS&1#0 %THEN %RESULT=0; ! CONDITIONAL ENTRY
         PUSH(CURRINF_LABEL,0,0,LAB)
         CELL=CURRINF_LABEL
         LCELL==ASLIST(CELL)
      %FINISH
!
! LABEL HAS BEEN REFERENCED - FILL IN ITS ADDRESS
!
      %IF LCELL_S1&LABSETBIT# 0 %THEN %START
         FAULT(2,0,LAB);                ! LABEL SET TWICE
      %FINISH %ELSE %START
         LCELL_S1=LCELL_S1!LABSETBIT;   ! FLAG AS SET
      %FINISH
!
! NOW FILL JUMPS TO THIS LABEL - JUMP LIST FORMAT GIVEN IN 'ENTER JMP'
!
      CURRT==TRIPLES(UCONSTTRIP(TLAB,0,0,LAB))
      CURRT_OPND1_XTRA=CELL
!
! NEED ANOTHER TRIPLE HERE TO REMOVE THE TEMPORARY LABLES ?
!
      %RESULT=1
%END
%ROUTINE ENTER JUMP(%INTEGER TFMASK,LAB,FLAGS)
!***********************************************************************
!*       IF LAB HAS BEEN ENCOUNTERED THEN PLANT A JCC OTHERWISE ENTER  *
!*       THE LABEL IN THE LABEL LIST AND ATTACH THE JUMP TO IT SO IT   *
!*       CAN BE PLANTED WHEN THE LABEL IS FOUND                        *
!*       THE LABEL LIST IS DESCRIBED UNDER 'ENTER LAB'                 *
!*       THE JUMP SUB-LIST HAS THE FORM                                *
!*       S1= ADDR OF JUMP                                              *
!*       S2=SHORT OR LONG FLAG                                         *
!*       S3=LINE NO OF JUMP FOR DIAGNOSTICS                            *
!*                                                                     *
!*       FLAGS BITS SIGNIFY AS FOLLOWS                                 *
!*       2**0 =1  JUMP IS KNOWN TO BE SHORT                            *
!*       2**1 =1  ENVIRONMENT MERGEING REQUIRED(NOT IMPLEMENTED)       *
!***********************************************************************
%INTEGER CELL,I
%RECORD(TRIPF)%NAME CURRT
%RECORD(LISTF)%NAME LCELL
      %IF LAB<MAX ULAB %THEN FLAGS=0;! NO MERGE
      CELL=CURRINF_LABEL
      %WHILE CELL>0 %CYCLE
         LCELL==ASLIST(CELL)
         %IF LAB=LCELL_S3 %THEN %EXIT
         CELL=LCELL_LINK
      %REPEAT
      -> FIRSTREF %IF CELL<=0
      -> NOT YET SET %IF LCELL_S1&LABSETBIT=0
      LCELL_S1=LCELL_S1!X'1000000';      ! FLAG LABEL AS USED
      CURRT==TRIPLES(UCONSTTRIP(BJUMP,0,0,LAB))
      CURRT_OPND1_XTRA=CELL;            ! LAB CELL FOR BJUMPS
      CURRT_X1=TFMASK
      %RETURN
FIRSTREF:                              ! FIRST REFERENCE TO A NEW LABEL
      PUSH(CURRINF_LABEL,LABUSEDBIT,0,LAB)
      CELL=CURRINF_LABEL
      LCELL==ASLIST(CELL)
NOT YET SET:                           ! LABEL REFERENCED BEFORE
      I=FJUMP
      CURRT==TRIPLES(UCONSTTRIP(I,0,0,LAB))
      CURRT_X1=TFMASK;                   ! CONDITIONAL OR NOT ETC
      PUSH(LCELL_S2,0,FLAGS&1,LINE)
      CURRT_OPND1_XTRA=LCELL_S2;        ! JUMP CELL FOR FJUMPS
%END
%ROUTINE REMOVE LAB(%INTEGER LAB)
!***********************************************************************
!*    REMOVES A ALBEL FROM THE CURRENT LABEL LIST WHEN KNOWN TO        *
!*    BE REDUNDANT. MAINLY USED FOR CYCLE LABELS                       *
!***********************************************************************
!
! SOME SORT OF TRIPLE IS NEEDED HERE. CAN NOT REMOVE THE LAB TILL CODE GENERATED
!
%END
%ROUTINE CREATE AH(%INTEGER MODE)
!***********************************************************************
!*       CREATES AN ARRAYHEAD IN THE ESTACK BY MODIFYING THE           *
!*       HEAD ALREADY THERE AS FOLLOWS:-                               *
!*       MODE=0 (ARRAYMAPPING)  ETOS-4&5 HAS 32BIT ADDR OF FIRST ELEMNT*
!*       MODE=1 (ARRAYS IN RECORDS)ETOS-4&5 HAS 32BIT RELOCATION FACTOR*
!***********************************************************************
      %IF MODE=0 %START
         ERASE(2);                      ! IS LOST
         PB1(EXCH2);                    ! ADDRESS OVER DV
      %FINISH %ELSE %START
         PB1(EXCH2);                    ! DV TO TOP
         PB1(PERMD);                    ! DV ADDRESS TO BOTTOM
         PB2(LOPS,2);                   ! 32 BIT ADD
      %FINISH
%END;                                   ! OF ROUTINE CREATE AH
%ROUTINE CSNAME(%INTEGER Z)
!***********************************************************************
!*       COMPILE A SPECIAL NAME - PTYPE=10006 (=%ROUTINE %LABEL)       *
!*       THEIR TRUE PTYPE IS IN GLOBAL ARRAY TAGS_S2.                  *
!*       SNINFO HAS A FOUR BYTE RECORD FOR EACH NAME (%BI FLAG,PTR,    *
!*       %SI XTRA). THE TOP BITS OF FLAG CATEGORISE AS FOLLOWS:-       *
!*       2**7 SET FOR IMPLICITLY SPECIFIED CONSTRUCT A %SPEC           *
!*       2**6 SET FOR IOCP CALL                                        *
!*       2**5 SET FOR BUILT IN MAPPING FUNCTIONS                       *
!*       2**4 SET IF AD-HOC CODE PLANTED BY THIS ROUTINE               *
!*       2**3 SET IF FIRST PARAMETER IS OF %NAME TYPE                  *
!*       2**2-2**0 HOLD NUMBER OF PARAMS                               *
!*                                                                     *
!*       THE FULL SPECS ARE AS FOLLOWS:-                               *
!*       0=%ROUTINE SELECT INPUT(%INTEGER STREAM)                      *
!*       1=%ROUTINE SELECT OUTPUT(%INTEGER STREAM)                     *
!*       2=%ROUTINE NEWLINE                                            *
!*       3=%ROUTINE SPACE                                              *
!*       4=%ROUTINE SKIP SYMBOL                                        *
!*       5=%ROUTINE READ STRING(%STRINGNAME S)                         *
!*       6=%ROUTINE NEWLINES(%INTEGER N)                               *
!*       7=%ROUTINE SPACES(%INTEGER N)                                 *
!*       8=%INTEGERFN NEXT SYMBOL                                      *
!*       9=%ROUTINE PRINT SYMBOL(%INTEGER SYMBOL)                      *
!*       10=%ROUTINE READ SYMBOL(%NAME SYMBOL)                         *
!*       11=%ROUTINE READ(%NAME NUMBER)                                *
!*       12=%ROUTINE WRITE(%INTEGER VALUE,PLACES)                      *
!*       13=%ROUTINE NEWPAGE                                           *
!*       14=%INTEGERFN ADDR(%NAME VARIABLE)                            *
!*       15=%LONGREALFN ARCSIN(%LONGREAL X)                            *
!*       16=%INTEGERFN INT(%LONGREAL X)                                *
!*       17=%INTEGERFN INTPT(%LONRGREAL X)                             *
!*       18=%LONGREALFN FRACPT(%LONGREAL X)                            *
!*       19=%ROUTINE PRINT(%LONGREAL NUMBER,%INTEGER BEFORE,AFTER)     *
!*       20=%ROUTINE PRINTFL(%LONGREAL NUMBER,%INTEGER PLACES)         *
!*       21=%REALMAP REAL(%INTEGER VAR ADDR)                           *
!*       22=%INTEGERMAP INTEGER(%INTEGER VAR ADDR)                     *
!*       23=%LONGREALFN MOD(%LONGREAL X)                               *
!*       24=%LONGREALFN ARCCOS(%LONGREAL X)                            *
!*       25=%LONGREALFN SQRT(%LONGREAL X)                              *
!*       26=%LONGREALFN LOG(%LONGREAL X)                               *
!*       27=%LONGREALFN SIN(%LONGREAL X)                               *
!*       28=%LONGREALFN COS(%LONGREAL X)                               *
!*       29=%LONGREALFN TAN(%LONGREAL X)                               *
!*       30=%LONGREALFN EXP(%LONGREAL X)                               *
!*       31=%ROUTINE CLOSE STREAM(%INTEGER STREAM)                     *
!*       32=%BYTEINTEGERMAP BYTE INTEGER(%INTEGER VAR ADDR)            *
!*       33=%INTEGERFN EVENTINF                                        *
!*       34=%LONGREALFN RADIUS(%LONGREAL X,Y)                          *
!*       35=%LONGREALFN ARCTAN(%LONGREAL X,Y)                          *
!*       36=%BYTEINTEGERMAP LENGTH(%STRINGNAME  S)                     *
!*       37=%ROUTINE PRINT STRING(%STRING(255) MESSAGE)                *
!*       38=%INTEGERFN NL                                              *
!*       39=%LONGREALMAP LONG REAL(%INTEGER VAR ADDR)                  *
!*       40=%ROUTINE PRINT CH(%INTEGER CHARACTER)                      *
!*       41=%ROUTINE READ CH(%NAME CHARACTER)                          *
!*       42=%STRINGMAP STRING(%INTEGER VAR ADDR)                       *
!*       43=%ROUTINE READ ITEM(%STRINGNAME ITEM)                       *
!*       44=%STRING(1)%FN NEXT ITEM                                    *
!*       45=%BYTEINTEGERMAP CHARNO(%STRINGNAME STR,%INTEGER CHARREQD)  *
!*       46=%STRING(1)%FN TOSTRING(%INTEGER SYMBOL)                    *
!*       47=%STRING(255)%FN SUBSTRING(%STRINGNAME S,%INTEGER BEG,END)  *
!*       48=%RECORDMAP RECORD(%INTEGER REC ADDR)                       *
!*       49=%ARRAYMAP ARRAY(%INTEGER A1ADDR,%ARRAYNAME FORMAT)         *
!*       50=%INTEGERFN SIZEOF(%NAME X)                                 *
!*       51=%INTEGERFN IMOD(%INTEGER VALUE)                            *
!*       52=%LONGREALFN PI                                             *
!*       53=%INTEGERFN EVENTLINE                                       *
!*       54=%LONGINTEGERMAP LONGINTEGER(%INTEGER ADR)                  *
!*       55=%LONGLONGREALMAP LONGLONGREAL(%INTEGER ADR)                *
!*       56=%LONGINTGEREFN LENGTHENI(%INTEGER VAL)                     *
!*       57=%LONGLONGREALFN LENGTHENR(%LONGREAL VAL)                   *
!*       58=%INTEGERFN SHORTENI(%LONGINTEGER VAL)                      *
!*       59=%LONGREALFN SHORTENR(%LONGLONGREAL VAL)                    *
!*       60=%INTEGERFN NEXTCH                                          *
!*       61=%HALFINTEGERMAP HALFINTEGER(%INTEGER ADDR)                 *
!*       62=%ROUTINE PPROFILE                                          *
!*       63=%LONGREALFN FLOAT(%INTEGER VALUE)                          *
!***********************************************************************
%INTEGERFNSPEC OPTMAP
%SWITCH ADHOC(1:16)
%CONSTINTEGERARRAY SNINFO(0:NO OF SNS)=%C
                    X'41080001',X'41090001',X'408A0001',X'40A00001',
                    X'40010001',X'800D0000',X'11010001',X'11010001',
                    X'10020024',X'41030001',X'19030001',X'80130001',
                    X'80170014',X'408C0001',X'19050024',X'80010002',
                    X'11040024',X'11040024',X'80010005',X'80090006',
                    X'80060007',X'2100003E',X'2100003E',X'11060024',
                    X'80010008',X'80010009',X'8001000A',X'8001000B',
                    X'8001000C',X'8001000D',X'8001000E',X'8015000F',
                    X'2100003E',X'100D0024',X'80030010',X'80030011',
                    X'1907003E',X'41070001',X'10080024',X'2100003E',
                    X'41050001',X'19030001',X'2100003E',X'19030001',
                    X'10020024',X'1A07003E',X'11090024',X'800F0012',
                    X'110A0018',X'120B1000',X'80130013',X'11060024',
                    X'100C0024',X'100D0024',X'2100003E'(2),
                    X'110E0024'(4),
                    X'10020024',X'2100003E',X'100F0001',X'11100024';
%CONSTSTRING(11)%ARRAY SNXREFS(0:20)=%C
                  "READSTRING", "S#READ",   "S#IARCSIN", "S#INT",
                  "S#INTPT" , "S#FRACPT", "S#PRINT" , "S#PRINTFL",
                  "S#IARCCOS","S#ISQRT" , "S#ILOG"  , "S#ISIN",
                  "S#ICOS"  , "S#ITAN"  , "S#IEXP"  , "CLOSESTREAM",
                  "S#IRADIUS","S#IARCTAN","S#SUBSTRING","S#SIZEOF",
                  "S#WRITE" ;
!
! SNPARAMS HOLDS NUMBER AND PTYPE OF FORMAL PARAMETER FOR IMPLICITLY
! SPECIFIED EXTERNAL ROUTINES. A POINTER IN SNINFO MEANS THAT NO
! DUPLICATES NEED TO BE RECORDED.
!
%CONSTHALFINTEGERARRAY SNPARAMS(0:25)=0,
               1,LRLPT,       2,LRLPT,LRLPT,  2,LRLPT,X'51',
               3,LRLPT,X'51',X'51',   1,X'435',   3,X'435',X'51',X'51',
               1,X'400',     1,X'51',      2,X'51',X'51';
! KEY TO PARAMETER TABLE
!     0  X0    == (NO PARAMS)
!     1  X1    == (%LONGREAL X)
!     3  X3    == (%LONGREAL X,Y)
!     6  X6    == (%LONGREAL X,%INTEGER I)
!      9 X9    == (%LONGREAL X,%INTEGER I,J)
!     13 XD    == (%STRINGNAME S)
!     15 XF    == (%STRINGNAME S,%INTEGER I,J)
!     19 X13   == (%NAME X)
!     21 X15   == (%INTEGER I)
!     23 X17   == (%INTEGER I,J)
!
!
%CONSTBYTEINTEGERARRAY WRONGZ(0:15)=27,29,23,29,29,23,82,109(5),
                                        23,27,109(2);
%ROUTINESPEC RTOS
%RECORD(LISTF)%NAME LCELL
%INTEGER ERRNO,FLAG,POINTER,PIN,SNNO,SNNAME,NAPS,SNPTYPE,JJ,%C
         XTRA,IOCPEP,B,D,SNINF,P0,OPHEAD,ERRVAL,EXPHEAD,EXPBOT,NOPS
      SNNAME=FROM AR2(P)
      SNNO=K;                           ! INDEX INTO SNINFO
      TESTAPP(NAPS);                    ! COUNT ACTUAL PARAMETERS
      PIN=P; P=P+2
      SNPTYPE=ACC
      SNINF=SNINFO(SNNO)
      XTRA=SNINF&X'FFFF'
      POINTER=(SNINF>>16)&255
      FLAG=SNINF>>24
!
! THE IMPLICITLY SPECIFIED ROUTINE ARE THE EASIEST OF ALL TO DEAL WITH.
! JUST SET UP THE EXTERNAL SPEC & PARAMETERS. THEN A RECURSIVE CALL
! OF CNAME THEN FINDS THE ROUTINE UNDER ITS TRUE COLOURS AND COMPILES
! THE CALL. ALL CALLS EXCEPT THE FIRST ARE DEALT WITH DIRECTLY BY CNAME.
! ALL NONTRIVIAL ROUTINES SHOULD BE DEALT WITH IN THIS MANNER
! XTRA HAS INDEX INTO ARRAY OF EXTERNAL NAMES SO THAT THESE
! CAN EASILY BE CHANGED.
!
      %IF FLAG&X'80'#0 %THEN %START
!         CXREF(SNXREFS(XTRA),PARM_DYNAMIC,2,JJ);! JJ SET WITH REF DISPLACEMENT
         JJ=ADDR(SNXREFS(XTRA))
!         %IF SNNO=26 %THEN LOGEPDISP=JJ
!         %IF SNNO=30 %THEN EXPEPDISP=JJ
         OPHEAD=0; P0=SNPARAMS(POINTER)
         K=OPHEAD; D=1
         %WHILE D<=P0 %CYCLE
            PTYPE=SNPARAMS(POINTER+D)
            UNPACK
            %IF NAM=0 %THEN ACC=BYTES(PREC) %ELSE ACC=8
            %IF PTYPE=X'35' %THEN ACC=256;!STRING BY VALUE
            INSERTAT END(OPHEAD,PTYPE<<16,ACC<<16,0)
            D=D+1
         %REPEAT
         LCELL==ASLIST(TAGS(SNNAME))
         LCELL_S1=1<<4!14!SNPTYPE<<16;  ! I=1 & J=14
         LCELL_S2=JJ;                   ! RT ENTRY DISPLACEMENT
         LCELL_S3=OPHEAD<<16!P0;        ! K & KFORM(=NPARAMS)
         P=PIN; CNAME(Z);           ! RECURSIVE CALL
         P=P-1; %RETURN;                ! DUPLICATES CHECK OF <ENAME>
      %FINISH
!
! ALL ROUTINES EXCEPT THE IMPLICITS REQUIRE A CHECK THAT THE USE OF THE
! NAME IS LEGAL AND THAT THE CORRECT NO OF PARAMETERS(BOTTOM 2 BITS OF
! FLAG) HAS BEEN SUPPLIED. THE CHECK IS TRIVIAL - THE PROBLEM
! IS TO GET THE RIGHT ERROR NUMBER.
! XTRA HAS A BITMASK OF ALLOWED USES(IE ALLOWED Z VALUES)
!
      ERRVAL=NAPS-FLAG&3
      %IF ERRVAL>0 %THEN ERRNO=19 %AND ->ERREXIT
      %IF ERRVAL<0 %THEN ERRNO=18 %AND ERRVAL=-ERRVAL %AND ->ERREXIT
      JJ=1<<Z
      %IF JJ&XTRA=0 %THEN %START;       ! ILLEGAL USE
         ERRNO=WRONGZ(Z)
         ->ERR EXIT
      %FINISH
!
! A NUMBER OF INPUT-OUTPUT ROUTINES ARE MAPPED ONTO CALLS OF IOCP.
! THIS ARRANGEMENT HAS THE ADVANTAGE OF REQUIRING ONL 1 EXTERNAL REF
! IN THE GLA BUT HAS THE DISADVANTAGE THAT THE I-O ROUTINES CAN NOT
! BE PASSED AS RT-TYPE PARAMETERS AS WELL AS REQUIRING MESSY CODE
! HEREABOUTS.  SNINF_PTR HOLD EITHER:-
!       1) THE IOCP ENTRY POINT NO
!   OR  2) THE SYMBOL TO BE OUTPUT WITH 2**7 BIT SET
!
! THIS SECTION DEALS WITH SELECT INPUT,SELECT OUTPUT,NEWLINE,NEWPAGE
!                         SPACE,SKIP SYMBOL,PRINT SYMBOL,PRINT STRING
!                         AND PRINT CH
!
      %IF FLAG&X'40'#0 %THEN %START
         IOCPEP=POINTER
         %IF FLAG&3#0 %THEN %START;     ! RT HAS PARAMS
            P=P+1
            %IF SNNO=37 %THEN CSTREXP(32) %ELSE CSEXP(X'51')
         %FINISH
         %IF IOCPEP>127 %THEN %START
            PBW(LDCW,IOCPEP&127)
            PB2(LOPS,1)
            IOCPEP=5
         %FINISH
         CIOCP(IOCPEP);                 ! PLANT CALL OF IOCP
         P=P+1
         ->OKEXIT
      %FINISH
!
! THE BUILT-IN MAPS (INTEGER ETC BUT NOT RECORD OR ARRAY)
!
      %IF FLAG&X'20'#0 %THEN %START
         SNPTYPE=X'1C00'+SNPTYPE;       ! ADD MAP BITS
         %IF PARM_OPT=0 %AND OPTMAP#0 %THEN ->OKEXIT
         %IF Z=1 %THEN  BIMSTR=1;       ! SPECIAL FLAG FOR STORE VIA MAP
         P=P+1
         CSEXP(X'51'); P=P+1
         %IF Z=1 %THEN BIMSTR=0
         JJ=SNPTYPE>>4&15
         %IF  SNPTYPE&X'FF'=X'31' %THEN PB1(LDC0);! BYTE INTEGER DIFFERENT
         DISP=0; ACCESS=3; BASE=0
         OLDI=0;                        ! FOR CHECK IN == ASSGNMNT
         ->OKEXIT
      %FINISH
!
! ADHOC CODING IS REQUIRED FOR THE REMAINING ROUTINES APART FROM
! A CHECK FOR NAMETYPE PARAMETERS. THE SWITCH NO IS KEPT IN POINTER
!
      P=P+1
      %IF FLAG&8#0 %AND %C
         (A(P+3)#4 %OR A(P+4)#1 %OR A(P+FROM AR2(P+1)+1)#2) %THEN  %C
         ERRNO=22 %AND ERRVAL=1 %AND ->ERREXIT
      ->ADHOC(POINTER)
ADHOC(1):                               ! NEWLINES(=6) & SPACES(=7)
      %IF SNNO=6 %THEN JJ=10 %ELSE JJ=32
      EXPHEAD=0; NOPS=2
      PUSH(EXPHEAD,ORL,0,0);            ! OPERATOR '!'
      EXPBOT=EXPHEAD
      PUSH(EXPHEAD,X'510000',JJ,0);     ! CONST JJ
      PUSH(EXPHEAD,LSHIFT,0,0);         ! OPERATOR '<<'
      PUSH(EXPHEAD,X'510000',8,0);      ! CONST 8
      P=P+3; TORP(EXPHEAD,EXPBOT,NOPS)
      EXPOP(EXPHEAD,EXPBOT,NOPS,X'51'); ! EVAL REPTN<<8!SYMBOL IN GR1
      CIOCP(17)
      P=P+1
      ->OKEXIT
ADHOC(2):                               ! NEXTSYMBOL(=8) & NEXTITEM(=44)
                                        ! ALSO NEXTCH(=60)
      %IF SNNO=60 %THEN JJ=18 %ELSE JJ=2
      CIOCP(JJ);                        ! LEAVES THE SYMBOL IN GR1
      PB1(MES)
      %IF SNNO=44 %THEN ->TOST;         ! TREAT AS TOSTRING
      ->OKEXIT
ADHOC(3):                               ! READSYMBOL(=10),CH(=41)&ITEM(=43)
      %IF SNNO=41 %THEN JJ=4 %ELSE JJ=1
      PB1(LDCN)
      CIOCP(JJ);                        ! SYMBOL OR CH TO GR1
      P=P+5
      %IF SNNO=43 %THEN %START
         CNAME(4);                      ! 32 BIT ADRESS
         PB2(LDC0,MES)
         TYPE=5; RTOS
         PB2(LDC0,LDC0+1)
         PB3(STLATE,X'63',SAS)
      %FINISH  %ELSE %START
         PB1(MES)
         REDUCE TAG
         EXPHEAD=0; NOPS=1
         PUSH(EXPHEAD,VASS,FROMAR2(P)<<16!PTYPE,0); ! ASSIGN
         EXPBOT=EXPHEAD
         PUSH(EXPHEAD,X'41'<<16!9,0,0);! ITEM IN ETOS
         PUSH(EXPHEAD,PTYPE<<16!2,P,0)
         FAULT(25,0,0) %UNLESS TYPE=1
         EXPOP(EXPHEAD,EXPBOT,NOPS,PTYPE&255!256)
      %FINISH
      P=PIN+6+FROM AR2(PIN+4)
      ->OKEXIT
ADHOC(4):                               ! INT(=16) AND INTPT (=17)
      CSEXP(LRLPT)
      %IF SNNO=16 %THEN JJ=23 %ELSE JJ=16
      PB2(ROPS,JJ)
      P=P+1
      ->OKEXIT
ADHOC(5):                               ! ADDR(=14)
      P=P+5; CNAME(4);              ! FETCH ADDRESS MODE
      P=P+2; ->OKEXIT
ADHOC(6):                               ! MOD(=23), IMOD(=51)
      %IF SNNO=51 %THEN %START
         CSEXP(X'51'); PB2(LOPS,2)
      %FINISH %ELSE %START
         CSEXP(X'62'); PB2(ROPS,24)
      %FINISH
      P=P+1
      ->OKEXIT
ADHOC(7):                               ! CHARNO(=45) & LENGTH(=36)
      P=P+5
      CNAME(2)
      B=BML; D=DML
      ERRNO=22; ERRVAL=1
      ->ERREXIT %UNLESS TYPE=5 %AND (ROUT=0 %OR NAM>=2)
      %IF NAM=0 %AND LITL=1 %THEN FAULT(43,0,FROMAR2(PIN+8))
      P=P+2
      %IF SNNO#36 %THEN %START
         CSEXP(X'41')
         P=P+1
      %FINISH %ELSE PB1(LDC0)
      DISP=0; ACCESS=3
      STNAME=-1 %IF Z=1;                ! CANT REMEBER NAME
      SNPTYPE=SNPTYPE+X'1C00'
      ->OKEXIT
ADHOC(12):                              ! PI(=52)
ADHOC(8):                               ! NL(=38). THIS FN IS PICKED OFF
      P=P+1
      ->OKEXIT;                         ! ERROR EG NL=A+B
ADHOC(9):                               ! TOSTRING(=46)
      CSEXP(X'41');                     ! RET EXPSN
      P=P+1
TOST: RTOS
      STRFNRES=0
      SNPTYPE=X'1035';                  ! TYPED AS STRING FN
      ->OKEXIT
ADHOC(10):                              ! RECORD(=48)
      CSEXP(X'51')
      P=P+1
      OLDI=0; ACC=X'FFFF'
      SNPTYPE=SNPTYPE+X'1C00';          ! ADD MAP BITS
      ->OKEXIT
ADHOC(11):                              ! ARRAY(=49)
      CSEXP(X'51');                     ! ADDR(A(0)) TO NEST
      ERRNO=22; ERRVAL=2
      ->ERREXIT %UNLESS A(P+4)=4 %AND A(P+5)=1
      P=P+6; CNAME(12)
      ->ERREXIT %UNLESS A(P)=2 %AND ARR>0
      P=P+2
      CREATE AH(0)
      %RETURN
ADHOC(13):                              ! EVENTINF(=33) & EVENTLINE
      D=CURRINF_ONINF
      FAULT(16,0,SNNAME) %IF D=0
      D=D+4 %IF SNNO#33
      DFETCH(4,RBASE,D)
      ->OKEXIT
ADHOC(14):                              ! LENGTHEN AND SHORTEN
      D=(SNNO&3)*8
      CSEXP(X'52415251'>>D&255)
      P=P+1
      ->OKEXIT
ADHOC(15):                              ! PPROFILE(IGNORED UNLESS PARM SET)
      PPJ(0,22) %UNLESS PARM_PROF=0
      ->OKEXIT
ADHOC(16):                              ! FLOAT
      CSEXP(LRLPT)
      P=P+1
OKEXIT:                                 ! NORMAL EXIT
      PTYPE=SNPTYPE; UNPACK
      %RETURN
ERREXIT:                                ! ERROR EXIT
      FAULT(ERRNO,ERRVAL,SNNAME)
      BASE=0; DISP=0; ACCESS=0; AREA=0
      PTYPE=SNPTYPE; UNPACK
      P=PIN+2; SKIP APP
      P=P-1; %RETURN
%INTEGERFN OPTMAP
!***********************************************************************
!*       LOOK FOR EXPRESSION LIKE INTEGER(ADDR(X)) AND AVOID USING DR  *
!***********************************************************************
%INTEGER VARNAME,REXP,PP,CVAL,OP
         PP=P+2; REXP=FROM AR2(PP)+PP;  ! TO REST OF EXP
         VARNAME=FROM AR2(PP+4);             ! SHOULD BE ADDR
         %RESULT=0 %UNLESS A(PP+2)=4 %AND A(PP+3)=1
         COPY TAG(VARNAME);             ! CHECK IT WAS ADDR
         ->WASADR %IF PTYPE=SNPT %AND K=14 %AND A(PP+6)=1
         %RESULT=0
WASADR:  PP=PP+10
         %RESULT=0 %UNLESS A(PP)=4 %AND A(PP+1)=1 %AND %C
            A(PP+4)=2=A(PP+5) %AND A(PP+6)=2=A(PP+7) %AND A(PP+8)=2
         VARNAME=FROM AR2(PP+2); COPY TAG(VARNAME)
         %RESULT=0 %UNLESS PTYPE&X'FF0C'=0
         %IF A(REXP)=2 %THEN P=REXP+2 %ELSE %START
            OP=A(REXP+1)
            %RESULT=0 %UNLESS 1<=OP<=2 %AND A(REXP+2)=2 %AND %C
               A(REXP+3)=X'41' %AND A(REXP+6)=2
            CVAL=FROM AR2(REXP+4)
            %IF OP=1 %THEN K=K+2*CVAL %ELSE K=K-2*CVAL
            %RESULT=0 %IF K<0
            P=REXP+8
         %FINISH
         BASE=I
         DISP=K; ACCESS=0
         %RESULT=1

%END
%ROUTINE RTOS
!***********************************************************************
!*       PLANTS CODE TO CONVERT A SYMBOL IN ETOS TO A ONE              *
!*       CHARACTER STRING IN A TEMPORARARY VARIABLE.                   *
!***********************************************************************
%INTEGER KK
      GET WSP(KK,1);                    ! GET 1 WORD WK AREA
      STRINGL=1; DISP=KK
      PBW(LDCW,256)
      PB3(MPI,LDC0+1,ADI)
      DSTORE(2,RBASE,KK)
      DFETCHAD(YES,RBASE,KK)
%END
%END;                                   ! OF ROUTINE CSNAME
%ROUTINE AATORP(%INTEGERNAME NOPS,HEAD1,BOT1,%INTEGER ARRP,BS,DP)
!***********************************************************************
!*    DOES THE HARD WORK OF ARRAY ACCESS BY PRODUCING REVERSE POLISH   *
!*    EXPRESSION OF THE INDEX EXPRESSIONS & MULTIPLIERS                *
!***********************************************************************
%INTEGER HEAD2,PTYPEP,KK,PP,JJ,SOLDI, %C
      TYPEP,ARRNAME,Q,PRECP,ELSIZE,NAMINF,BOT2,DVD,VMYOP,VMYOPPT
      PP=P; TYPEP=TYPE
      JJ=J; PTYPEP=PTYPE; PRECP=PREC; SOLDI=OLDI
      %IF TYPE<=2 %THEN ELSIZE=BYTES(PRECP) %C
                             %ELSE ELSIZE=ACC
      %IF ELSIZE>4095 %OR (TYPE=5 %AND NAM#0) %THEN ELSIZE=0
      DVD=SNDISP;                       ! LOCATION OF DV IF CONSTANT
      %IF DVD>0 %THEN VMYOPPT=X'51' %ELSE VMYOPPT=X'61'
      VMYOPPT=VMYOPPT<<16;              ! FOR OPTIMISER PASS ONLY
      ARRNAME=FROM AR2(P);              ! NAME OF ENTITY
      NAMINF=TAGS(ARRNAME)
      FAULT(87,0,ARRNAME) %IF ARR=3;   ! ARRAYFORMAT USED AS ARRAY
      NAMINF=-2 %AND DVD=0 %IF ARRP>2;  ! ARRAYS IN RECORDS 
      TEST APP(Q);                      ! COUNT NO OF SUBSCRIPTS
!
! CHECK CORRECT NO OF SUBSCRIPTS PROVIDED. HOWEVER ENTITIES DECLARED
! AS %<TYPE>ARRAYNAME HAVE NO DIMENSION . THIS SECTION SETS THE
! DIMENSION FROM THE FIRST USE OF THE NAME.
!
      %IF JJ=0 %THEN %START;            ! 0 DIMENSIONS = NOT KNOWN
         REPLACE1(TCELL,FROM1(TCELL)!Q);! DIMSN IS BOTTOM 4 BITS OF TAG
         JJ=Q
      %FINISH
      %IF JJ=Q#0 %THEN %START;          ! IN LINE CODE
!
! FOR IN-LINE CODE WE SET UP A CHAIN OF REVERSE POLISH OPERATIONS TO
! EVALUATE THE VARIOUS SUBSCRIPTS,MULTIPLY BY THE MULTIPLIERS AND
! ADD THEM TOGETHER.
!
         HEAD2=0;                       ! CLEAR LISTHEADS
!
! NOW PROCESS THE SUBSCRIPTS CALLINR TORP TO CONVERT THE EXPRESSIONS
! TO REVERSE POLISH AND ADDING THE EXTRA OPERATIONS.
!
         BINSERT(HEAD1,BOT1,X'51'<<16!7,BS<<16!DP,0)
         P=PP+3
         %CYCLE KK=1,1,JJ;                ! THROUGH THE SUBSCRIPTS
            P=P+3; BOT2=0
            TORP(HEAD2,BOT2,NOPS);      ! SUBSCRIPT TO REVERSE POLISH
            P=P+1
!
! MULTIPLIERS ARE DOPE VECTOR ITEMS (OPTYPE=3)
!
! N SUBSCRIPTS WILL REQUIRE (N-1) MULTIPLICATIONS AND ADDITIONS
!
            NOPS=NOPS+2
            VMYOP=KK<<24!JJ<<16!DVD
            %IF KK>1 %OR PARM_ARR#0 %START
               BINSERT(HEAD2,BOT2,VMYOPPT,VMYOP,BS<<16!DP);! MULTIPLIER
               BINSERT(HEAD2,BOT2,VMY,PTYPEP<<16!ARRNAME,0);! DOPE VECTOR MULTIPLY
            %FINISH
            BINSERT(HEAD2,BOT2,COMB,0,0) %IF KK>1;! COMBINE WITH PREVIOUS
                                        ! VMY RESULT
            ASLIST(BOT1)_LINK=HEAD2
            BOT1=BOT2; HEAD2=0
         %REPEAT
         %UNLESS ARRP=2 %OR PARM_COMPILER#0 %START;! BASE ADJUST
            BINSERT(HEAD1,BOT1,VMYOPPT,JJ<<16!DVD,BS<<16!DP)
            BINSERT(HEAD1,BOT1,BADJ,PTYPEP<<16!ARRNAME,0)
         %FINISH
         BINSERT(HEAD1,BOT1,BSADD,BS<<16!DP!ELSIZE<<20,0);! SCALE
         NOPS=NOPS+2
      %FINISH %ELSE %START
         BINSERT(HEAD1,BOT1,X'51'<<16,0,0)
         %IF JJ>Q %THEN FAULT(20,JJ-Q,ARRNAME) %C
            %ELSE FAULT(21,Q-JJ,ARRNAME)
         P=P+2; SKIP APP
      %FINISH
      ACC=ELSIZE
      PTYPE=PTYPEP; J=JJ
%END
%ROUTINE CANAME(%INTEGER Z,ARRP,BS,DP)
!***********************************************************************
!*       BS & DP DEFINE THE POSITION OF THE ARRAY HEAD                 * 
!*       ARRP=1 FOR ARRAYS,2 FOR VECTORS,3 FOR ARRAYS IN RECORDS       *
!*       BASIC DISP = DISPMNT OF A(0) FOR VECTORS OR ARRAYS IN RECORDS *
!***********************************************************************
%INTEGER HEAD1,BOT1,NOPS,ELSIZE,PTYPEP,JJ,SOLDI
      NOPS=0; HEAD1=0; BOT1=0
      AATORP(NOPS,HEAD1,BOT1,ARRP,BS,DP)
      SOLDI=OLDI
      PTYPEP=PTYPE; JJ=J; ELSIZE=ACC
      EXPOP(HEAD1,BOT1,NOPS,X'51');     ! EVALUATE THE REVERSE POLISH LIST
                                        ! CONSTANT ACCEPTABLE AS RESULT
      BASE=BS; DISP=DP; ACCESS=3
      ACC=ELSIZE; PTYPE=PTYPEP; UNPACK; J=JJ
      %IF TYPE=5 %AND NAM>0 %THEN BML=BS %AND DML=DP+12
      OLDI=SOLDI;                       ! FOR NAME==A(EL) VALIDATION
%END;                                   ! OF ROUTINE CANAME
%ROUTINE CNAME(%INTEGER Z)
!***********************************************************************
!*       THIS IS THE MAIN ROUTINE FOR PROCESSING NAMES.CANAME,CSNAME   *
!*       AND CRNAME ARE ONLY CALLED FROM HERE,THE NAME (AND ANY PARAMS *
!*       OR SUBNAMES) ARE ACCESSED BY P WHICH IS ADVANCED.             *
!*       Z SPECIFIES ACTION AS FOLLOWS:-                               *
!*       Z=0 COMPILE A ROUTINE CALL                                    *
!*       Z=1 ARRANGE  A 'STORE' OPERATION FROM ESTACK                  *
!*       Z=2 FETCH NAME TO ESTACK                                      *
!*       Z=3 GET 32 BIT ADDRESS(48BIT FOR BYTES) FOR PASSING BY NAME   *
!*       Z=4 SET 20 BIT ADDRESS(36BIT FOR BYTES) OF NAME IN REG        *
!*       Z=5  AS Z=2                                                   *
!*       Z=6 STORE ETOS (CONTAINS POINTER) INTO POINTER VARIABLE       *
!*       Z=7->10  NOT NOW USED                                         *
!*       Z=11 FETCH 32 BIT ADDRESS OF ARRAYHEAD                        *
!*       Z=12 FETCH ARRAYHEAD TO ESTACK                                *
!*       Z=13 GET 4 WORD ROUTINE DISCRIPTOR                            *
!*              (INTERNAL ROUTINES FIRST CREATE THE DISCRIPTOR)        *
!*                                                                     *
!***********************************************************************
%INTEGER JJ, KK, LEVELP, DISPP, NAMEP, PP, SAVESL, FNAME
%SWITCH S, FUNNY(11:13), SW(0:8)
      PP=P
      FNAME=A(P)<<8+A(P+1)
      %IF Z=1 %OR Z=6 %THEN STNAME=FNAME
      COPYTAG(FNAME)
      %IF I=-1 %THEN %START
         FAULT(16, 0, FNAME)
         I=RLEVEL;  J=0;  K=FNAME
         KFORM=0; SNDISP=0; ACC=4
         PTYPE=X'57';  STORE TAG(K, N)
         K=N;  N=N+4;  COPYTAG(FNAME);  ! SET USE BITS!
      %FINISH
      SAVESL=ACC
      JJ=J;  JJ=0 %IF JJ=15
      NAMEP=FNAME
      LEVELP=I;  DISPP=K
      FAULT(43, 0, FNAME) %IF LITL=1 %AND ROUT=0=NAM %AND %C
         (Z=1 %OR Z=3 %OR (Z=4 %AND TYPE<5 %AND ARR=0))
      ->NOT SET %IF TYPE=7
      %IF (Z=0 %AND (ROUT#1 %OR 0#TYPE#6)) %OR (Z=13 %AND ROUT=0) %C
          %THEN FAULT(27,0,FNAME) %AND ->NOT SET
      ->FUNNY(Z) %IF Z>=10
      ->RTCALL %IF ROUT=1
      ->SW(TYPE)
SW(6):
      FAULT(5, 0, FNAME)
      ->NOT SET
SW(4):                                  !RECORD FORMAT NAME
      FAULT(87,0,FNAME)
SW(7):
NOT SET:                                ! NAME NOT SET
      BASE=I;  DISP=K;  ACCESS=0
      PTYPE=X'51';  UNPACK
      P=P+2; SKIP APP;  ->CHKEN
FUNNY(11):                              ! SET 32 BIT ADRESS OF ARRAYHEAD
FUNNY(12):                              ! MOVE ARRAYHEAD TO ESTACK
      ->SW(3) %IF TYPE=3 %AND (ARR=0 %OR A(P+2)=1)
      %IF PTYPE=SNPT %THEN CSNAME(12) %AND ->CHKEN
      %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
      %IF Z=11 %THEN DFETCHAD(YES,I,K) %ELSE DFETCHAD(NO,I,K) %AND %C
         PB2(ROPS,37)
      ->CHKEN
S(12):S(11):                            ! ARRAYS IN RECORDS BY NAME
      ->CHKEN
FUNNY(13):                              ! LOAD ADDR FOR RT-TYPE
         %IF PTYPE=SNPT %THEN CSNAME(Z) %AND P=P+1 %AND->CHKEN
         DISP=MIDCELL; BASE=I
         %IF NAM&1#0 %THEN %START
            DFETCH(8,BASE,DISP);        ! RT TYPE COPY POINTER
         %FINISH %ELSE %START
            %IF J=14 %THEN %START;      ! EXTERNAL ROUTINE PASSED
               PWW(LVRD,0,X'0100');     ! NB BYTES FLIPPED IN WORD 2!
               GXREF(STRING(DISP),0,0,CA-5)
            %FINISH %ELSE %START
               PWW(LVRD,0,DISP&255!(BASE+1)<<8);! LEVEL OF BODY NOT DECLN
            %FINISH
         %FINISH
         %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP; ->CHKEN
SW(3):                                 ! RECORD
         CRNAME(Z, 2*NAM, I, K, NAMEP)
         ->S(Z) %IF Z>=10
         ->STRINREC %IF TYPE=5 %AND Z#6
         ->NOT SET %IF TYPE=7
         NAMEOP(Z,BYTES(PREC),NAMEP)
         STNAME=NAMEP %IF Z=1 %OR Z=6
         ->CHKEN
SW(5):                                  ! TYPE =STRING
!
! ALL STRING OPERATIONS ARE ON THE RELEVANT DESCRIPTOR. Z=2 &Z=5
! REQUIRE A CURRENT LENGTH(IE MODIFIED) DESCRIPTOR. OTHER OPERATIONS
! REQUIRE THE MAX LENGTH DESCRIPTOR (IE UNMODIFIED HEADER)
!
      %IF Z=6 %THEN ->SW(1)
      ->STRARR %IF ARR>=1
      %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
      BASE=I; ACCESS=2*NAM; DISP=K
SMAP: %IF NAM#1 %THEN BML=-1 %AND DML=SAVESL-1 %C
         %ELSE BML=I %AND DML=K+4
      %IF Z=2 %THEN Z=4
      NAMEOP(Z,4,NAMEP)
      %IF Z=3 %START
         %IF BML<0 %THEN PBW(LDCW,DML)%ELSE DFETCH(2,BML,DML)
      %FINISH
      ->CHKEN
STRARR:                                 ! STRINGARRAYS &  ARRAYNAMES
      CANAME(Z, ARR, I, K)
      ->SMAP %UNLESS Z=3 %AND NAM#0
      NAMEOP(3,4,NAMEP)
      DFETCH(4,LEVELP,DISPP+4);          ! DV POINTER
ADDLMAX:                                ! PUT LMAX (16 BITS) OVER PTR
      PB1(TLATE1)
      PB1(SIND0+2)
      PB1(LDC0+1)
      PB1(SBI)
      ->CHKEN
      ->CHKEN
STRINREC:                               ! STRINGS IN RECORDS
      ->SMAP %UNLESS Z=3 %AND NAM#0 %AND ARR#0
      NAMEOP(3,4,NAMEP)
      DFETCH(2,BASE,DISP);              ! LEFT SET BY CENAME
      ->ADDLMAX
!
! SECTION TO DEAL WITH ALL NAMES INVOLVING ROUTINE CALL
!
RTCALL:                                 ! FIRST CHECK
         %IF TYPE=0 %AND Z#0 %THEN FAULT(23, 0, FNAME) %AND ->NOT SET
                                        ! RT NAME IN EXPRSN
         %IF PTYPE=SNPT %THEN %START
            CSNAME(Z);                  ! SPECIAL NAME
            ->BIM %IF ROUT=1 %AND NAM>1 %AND Z#0
            ->CHKEN
         %FINISH
         CRCALL(FNAME);  P=P+1;         ! DEAL WITH PARAMS
         ->CHKEN %IF PTYPE&15=0
         ->UDM %IF NAM>1;               ! MAPS
         %UNLESS Z=2 %OR Z=5 %THEN %START;   ! FUNCTIONS
            FAULT(29, 0, FNAME);  BASE=0
            ACCESS=0;  DISP=0
         %FINISH
         %IF TYPE=5 %THEN %START;       ! STRING FNS
            PB1(MES2);                  ! PICKUP 32BIT ADDR OF RESULT
         %FINISH %ELSE %START
            STACKUNDUMP(WORDS(PREC))
         %FINISH
         ->CHKEN
UDM:                                    ! USER DEFINED MAPS
         PB1(MES2);                     ! GET RESULT = 32 BIT ADDR
         %IF TYPE=1 %AND PREC=3 %THEN PB1(LDC0)
         DISP=0
         ACCESS=3
         BASE=0
BIM:                                    ! BUILT IN MAPS
         ->CHKEN %IF TYPE=3;            ! MAP RECORD USE VERY LIMITED
         NAMEP=-1
         STNAME=-1
         %IF TYPE=5 %THEN SAVESL=256 %AND ->SMAP
         KK=Z; KK=2 %IF Z=5
         NAMEOP(Z,BYTES(PREC),NAMEP)
         ->CHKEN
SW(0):                                  ! %NAME PARAMETERS NO TYPE
                                        ! ALLOW FETCH ADDR OPERATIONS
                                        ! AND SPECIAL FOR BUILTIN MAPS
         %UNLESS 3<=Z<=4 %THEN %START
            FAULT(90,0,FNAME);  TYPE=1
         %FINISH
SW(1):                                  ! TYPE =INTEGER
SW(2):                                  ! TYPE=REAL
         %IF ARR=0 %OR (Z=6 %AND A(P+2)=2) %THEN %START
            BASE=I; ACCESS=2*NAM
            DISP=K
            %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
         %FINISH %ELSE %START
            CANAME(Z, ARR, I, K)
            NAM=0
         %FINISH
         NAMEOP(Z,BYTES(PREC),NAMEP)
         ->CHKEN
!
                                        ! GENERAL FETCHING & STORING 
                                        !SECTION
!
CHKEN:   %WHILE A(P)=1 %CYCLE
            FAULT(69,FROMAR2(P+1),FNAME)
            P=P+3; SKIP APP
         %REPEAT
         P=P+1
%END

%ROUTINE NAMEOP(%INTEGER Z, SIZE, NAMEP)
!***********************************************************************
!*    FETCH OR STORE ETOS FROM OR TO VARIABLE DEFINED BY AREA ACCESS   *
!*    BASE AND DISP.                                                   *
!***********************************************************************
%SWITCH MOD(0:15),BIGACC(0:11)
%RECORD(TRIPF)%NAME CURRT
%INTEGER KK, OPTION, PTRSIZE
      KK=Z;  KK=2 %IF Z=5
      PTRSIZE=4
      %IF (TYPE=1 %AND PREC=3) %THEN PTRSIZE=6
      %IF Z=6 %THEN %START
         FAULT(82,0,NAMEP) %UNLESS NAM!ARR#0 %AND ROUT=0 %C
            %AND (ACCESS>=8 %OR ACCESS=2)
         KK=3;  SIZE=4; PTRSIZE=4
         %IF ACCESS>=8 %THEN ACCESS=ACCESS-4 %ELSE ACCESS=0
      %FINISH
      KK=KK&3
      OPTION=ACCESS<<2!KK
      ->BIGACC(ACCESS)
BIGACC(0):BIGACC(3):
      ->MOD(OPTION)
BIGACC(5):
BIGACC(1):  ABORT;                      ! NO LONGER USED?
!

! ACCESS
! ******
! THIS VARIABLE DEFINES HOW TO ACCESS ANY IMP VARIABLE:-
! =0 VARIABLE DIRECTLY ADDRESSED IN 'BASE' BY 'DISP'
! =1 VARIABLE ADDRESSED BY SHORTPOINTER ON ESTACK
! =2 POINTER TO VARIABLE DIRECTLY ADDRESS BY 'BASE' & 'DISP'
! =3 POINTER AS IN =2 ALREADY ON ESTACK
! =4 VARIABLE 'XDISP' INTO RECORD AT BY 'BASE' &'DISP'
! =5 VARIABLE 'XDISP' INTO RECORD ADDRESSED BY POINTER MODIFIED AS =1
! =6 VAR 'XDISP' INTO RECORD ADDRESSED BY POINTER AT 'BASE' & 'DISP'
! =7 AS =6 BUT POINTER ALREADY IN ESTACK
! =8-11 AS 4-7 BUT THERE IS A POINTER TO ITEM AT 'XDISP' INTO RECORD
! POINTER HERE MEANS 32 BIT NORMALLY BUT BYTES MUSTBE AND STRING MAY
! HAVE TO BE 48 BIT
!
MOD(0):                                 ! ACCESS=0 FETCH ADDRESS
MOD(3):                                 ! ACCESS=0 SET DESCRIPTOR
      CURRT==TRIPLES(UNAMETRIP(GETAD,X'51',0,NAMEP))
      CURRT_OPND1_XTRA=NAMEP
      %RETURN
MOD(1):                                 ! ACCESS=0 STORE
!      ABORT
      %RETURN
MOD(2):                                 ! ACCESS=0 FETCH
      CURRT==TRIPLES(UNAMETRIP(PRELOAD,PTYPE,0,NAMEP))
      CURRT_OPND1_XTRA=NAMEP
      %RETURN
BIGACC(2):                              ! ALL ACCESS=2
      DFETCH(PTRSIZE,BASE,DISP);        ! GET 32 BIT ADDRESS
      ACCESS=3; ->MOD(KK+12);           ! NOW AS ACCESS=3
MOD(12):                                ! ACCESS=3 FETCH ADDRESS
      %IF TYPE=1 %AND PTRSIZE>4 %THEN PB3(LDC0+2,DVI,ADI)
MOD(15):                                ! ACCESS=3 SET DESCRIPTOR
      %RETURN
MOD(14):                                ! ACCESS=3 FETCH
      %IF PREC=3 %THEN PB2(TLATE2,LDB) %AND %RETURN
      %IF PREC=4 %THEN PB2(TLATE1,LDIND) %AND %RETURN
      %IF PREC=5 %THEN PB2(TLATE1,LDDW) %AND %RETURN
      PB1(TLATE1)
      PB2(ROPS,37)
      %RETURN
MOD(13):                                ! ACCESS=3 STORE
      %IF PREC=3 %START
         PB4(MMS2,EXCH,MES,EXCH)
         PB4(MES,EXCH,TLATE3,STB)
         %RETURN
      %FINISH
      %IF PREC=5 %START;                ! DOUBLE WORDS
         PB3(EXCH2,TLATE3,STDW)
         %RETURN
      %FINISH
      %IF PREC=6 %START
         PB1(PERMD)
         PTLATE(5)
         PB2(ROPS,38);                  ! STQ
      %FINISH
                                        ! SINGLE WORD
      CAB
      PB2(TLATE2,STIND)
      %RETURN
BIGACC(4):                              ! ALL ACCESS=4
      DISP=DISP+XDISP
      ACCESS=0
      ->MOD(KK);                        ! REDUCES TO ACCESS=0
BIGACC(6):                              ! ALL ACCESS=6
      DFETCH(4,BASE,DISP)
                                        ! REDUCED TO ACCESS=7
                                        ! SO DROP THROUGH
BIGACC(7):                              ! ALL ACCESS=7
      NAMEP=0; ACCESS=1
      %IF TYPE=1 %AND PREC=3 %THEN PBW(LDCW,XDISP!!1) %ELSE %C
         PBW(INCW,XDISP>>1) %AND PTRSIZE=4
      ->MOD(KK+12);                      ! REDUCED TO ACCESS=3
BIGACC(8):                              ! ALL ACCESS=8
      DISP=DISP+XDISP
      NAMEP=0
      ->BIGACC(2)
BIGACC(10):                             ! ALL ACCESS=10
      DFETCH(4,BASE,DISP)
                                        ! HAS BECOME ACESS=11
BIGACC(11):                             ! ALL ACCESS=11
      NAMEP=0
      ACCESS=9;  DISP=XDISP
BIGACC(9):                              ! ALL ACCESS=9
      PBW(INCW,XDISP>>1)
      PB1(LDDW)
      ACCESS=3; NAMEP=0
      ->MOD(KK+12);                     ! HAS REDUCED TO ACCESS=3
%END
%ROUTINE CRCALL(%INTEGER RTNAME)
!***********************************************************************
!*       COMPILE A ROUTINE OR FN CALL                                  *
!*       THE PROCEDURE CONSIST OF THREE PARTS:-                        *
!*       A) PLANT THE PARAMETER (IF ANY)                               *
!*       B) ENTER THE ROUTINE OR FN                                    *
!*       C) FORGET ANY REGISTERS WHICH HOLD ENTITIES THAT CAN BE       *
!*          ALTERED BY THE CALLED PROCEDURE.                           *
!***********************************************************************
%SWITCH FPD(0:3)
%INTEGER II,III,QQQ,JJ,JJJ,NPARMS,PT,LP,PSIZE,TWSP,PARMNO,ERRNO,PP,%C
         TYPEP,PRECP,NAMP,TL,CLINK,RDISP
%RECORD(LISTF)%NAME LCELL
      PT=PTYPE; JJJ=J; TL=OLDI
      TWSP=0
      LP=I; CLINK=K
      TYPEP=TYPE; PRECP=PREC; NAMP=NAM
      RDISP=MIDCELL
!
! NOW CHECK THAT THE RIGHT NUMBER OF PARAMETERS HAVE BEEN PROVIDED
!
      TEST APP(NPARMS)
      P=P+2
      %IF KFORM#NPARMS %THEN %START
                                        ! WRONG NO OF PARAMETERS GIVEN
         %IF KFORM=0 %THEN ERRNO=17 %ELSE %START
            %IF NPARMS<KFORM %THEN ERRNO=18 %ELSE ERRNO=19
         %FINISH
         FAULT(ERRNO,IMOD(KFORM-NPARMS),RTNAME)
         SKIP APP; P=P-1
         %RETURN
      %FINISH
!
      %IF TYPEP#0 %START;               ! LEAVE RESULT HOLE FOR FNS
         %IF NAM>=2 %THEN II=4 %ELSE %IF TYPEP=5 %THEN II=4 %ELSE %C
            II=BYTES(PRECP)
         PB2(ATPB,II//2)
      %FINISH
      PARMNO=0
      ->FIRST PARM
!
BAD PARM:                               ! BAD PARAMETER FAULT IT
      P=PP
      FAULT(22,PARMNO,RTNAME)
      SKIP EXP
NEXT PARM:CLINK=LCELL_LINK
FIRSTPARM:->ENTRY SEQ %IF CLINK=0;      ! DEPART AT ONCE IF NO PARAMS
      LCELL==ASLIST(CLINK)
      PSIZE=LCELL_S2>>16
      PARMNO=PARMNO+1
      P=P+1; PP=P
      PTYPE=LCELL_S1>>16
      UNPACK
      II=TYPE;III=PREC
      JJ=(NAM<<1!ARR)&3
      ->BAD PARM %UNLESS (JJ=0 %AND ROUT=0) %OR %C
        (A(P+3)=4 %AND A(P+4)=1 %AND A(P+FROMAR2(P+1)+1)=2)
!
! RT TYPE PARAMS, PASS 4 WORDS AS SET UP  BY QCODE INSTRN LVRD
!
      %IF ROUT=1 %THEN %START
         FPTR=(FPTR+3)&(-4)
         II=PTYPE; P=P+5
         CNAME(13);                  ! SET UP 4 WDS IN ACC
         ->BAD PARM %IF II&255#PTYPE&255;! PREC&TYPE SIMILAR
         P=P+1
         STACKDUMP(4)
         ->NEXT PARM
      %FINISH
      ->FPD(JJ)
FPD(0):                                ! VALUE PARAMETERS
      %IF TYPE=5 %THEN %START
         PB2(LDTP,LDC0);                ! POINTER TO DEST
         PBW(LDCW,(PSIZE+1)>>1)
         PB1(ATPW);                     ! SPACE CALIMED
         CSTREXP(32)
         PB1(LDC0)
         PBW(LDCW,PSIZE-1)
         PB2(TLATE3,SAS)
         ->NEXT PARM
      %FINISH
      %IF TYPE=3 %START;                ! RECORDS BY VALUE
         II=TSEXP(III);                 ! CHECK FOR ZERO AS RECORD VALUE
         %IF II=1 %AND III=0 %START
            JJ=0
         %FINISH %ELSE %START
            P=PP;                       ! RESET NEEDED AFTER TSEXP
            ->BAD PARM %UNLESS A(P+3)=4 %AND A(P+4)=1 %AND %C
               A(P+FROMAR2(P+1)+1)=2
            P=P+5
            CNAME(3)
            P=P+1
            JJ=1
            ->BAD PARM %UNLESS ACC=PSIZE
         %FINISH
         PB2(LSSN,LDTP)
         PBW(LDCW,PSIZE>>1)
         PB1(ATPW)
         BULKM(JJ,PSIZE,0)
         ->NEXT PARM
      %FINISH
      CSEXP(III<<4!II)
      STACKDUMP((PSIZE+1)>>1)
      ->NEXT PARM
!
FPD(2):                                 ! NAME PARAMETERS
      P=P+5
      %IF II#0 %START;                  ! NOT A GENERAL NAME
         CNAME(3)
         %IF TYPE=5 %THEN PERM;         ! LMAX TO BOTTOM OUT LAST
         %IF PREC=3 %AND (TYPE=5 %OR TYPE=1) %THEN STACKDUMP(3) %ELSE %C
            STACKDUMP(2)
         ->BAD PARM %UNLESS II=TYPE %AND III=PREC
         FPTR=FPTR+4
      %FINISH %ELSE %START
         %IF TYPE#0 %START;             ! NOT GENERAL NAME PASSED AS NAME
            CNAME(4)
            STACKDUMP(2)
            PWW(LDDC,PTYPE,ACC)
            STACKDUMP(2)
         %FINISH %ELSE %START;          ! NAME AS GENERAL NAME
            FNAME=FROM AR2(P)
            COPY TAG(FNAME)
            DFETCH(8,I,K);              ! FETCH THE 4 WORDS
            STACKDUMP(4);               ! AND STUFF THEM OFF
         %FINISH
         FPTR=FPTR+8
      %FINISH
      P=P+1
      ->NEXT PARM
FPD(1):FPD(3):                          ! ARRAY NAME (&VALUE)
!
! FOR ARRAYNAME PARAMETERS THE NO OF DIMENSIONS OF THE ARRAY IS
! DEDUCED FROM THE FIRST CALL AND STORED IN STREAM3 OF THE PARAMETER
! LIST. ON ANY SUBSEQUENT CALL ONLY ARRAYS OF THE SAME DIMENSION CAN
! BE PASSED
!
      FPTR=(FPTR+3)&(-4)
      P=P+5
      CNAME(12)
      STACKDUMP(4)
      P=P+1
      ->BAD PARM %UNLESS 1<=ARR<=2 %AND II=TYPE %AND III=PREC
      QQQ=FROM1(TCELL)&15;              ! DIMENSION OF ACTUAL(IF KNOWN)
      JJ=LCELL_S1&15;                   ! DIMENSION OF FORMAL
      %IF JJ=0 %THEN JJ=QQQ %AND LCELL_S1=LCELL_S1!JJ
      %IF QQQ=0 %THEN QQQ=JJ %AND REPLACE1(TCELL,FROM1(TCELL)!JJ)
      ->BAD PARM %UNLESS JJ=QQQ
      FPTR=FPTR+16
      ->NEXT PARM
ENTRY SEQ:                              ! CODE FOR RT ENTRY
!
! RETURN ANY STRING WSPACE HERE. CAN BE USED AGAIN FOR RESULT
!
      %WHILE TWSP#0 %CYCLE
         POP(TWSP,QQQ,JJ,III)
         RETURN WSP(QQQ,268)
      %REPEAT
      %IF JJJ=14 %THEN %START;          ! EXTERNAL
         CURRINF_NMDECS=CURRINF_NMDECS!2
         PB3(CALLXB,1,0)
         GXREF(STRING(RDISP),0,0,CA-3)
      %FINISH %ELSE %START
         %IF NAMP&1=0 %THEN %START;!      INTERNAL RT CALLS
            PB2(CALL,RDISP&255)
         %FINISH %ELSE %START
            DFETCH(8,LP,RDISP)
            PB1(CALLV)
         %FINISH
      %FINISH
!
! CHECK THE PRESERVED REGS 4-RBASE AND FORGET IF CONTENTS 
! ARE VULNERABLE TO A ROUTINE CALL
!
      ROUT=1; TYPE=TYPEP; NAM=NAMP
      PREC=PRECP; PTYPE=PT
%END
%INTEGERFN TSEXP(%INTEGERNAME VALUE)
%SWITCH SW(1:3)
%INTEGER PP,REXP,KK,SIGN,CT
         TYPE=1; PP=P
         REXP=2-A(P+1+FROM AR2(P+1))
         P=P+3
         SIGN=A(P)
         ->TYPED %UNLESS SIGN=4 %OR A(P+1)=2
         ->SW(A(P+1))
SW(1):                                  ! NAME
         P=P+2; REDUCE TAG
         ->TYPED
SW(2):                                  ! CONSTANT
         CT=A(P+2); TYPE=CT&7
         ->TYPED %UNLESS CT=X'41' %AND SIGN#3
         KK=FROMAR2(P+3)
         ->TYPED %UNLESS REXP=0 %AND 0<=KK<=255
         VALUE=KK
         P=P+6
         %IF SIGN#2 %THEN %RESULT=1
          VALUE=-VALUE; %RESULT=-1
SW(3):                                  ! SUB EXPRN
TYPED:   P=PP; %RESULT=0
%END
%ROUTINE SKIP EXP
!***********************************************************************
!*       SKIPS OVER THE EXPRESSION POINTED AT BY P. USED FOR ERROR     *
!*       RECOVERY AND TO EXTRACT INFORMATION ABOUT THE EXPRESSION.     *
!***********************************************************************
%INTEGER OPTYPE, PIN, J
         PIN=P
         P=P+3;                         ! TO P<+'>
         %CYCLE;                        ! DOWN THE LIST OF OPERATORS
           OPTYPE=A(P+1);               ! ALT OF P<OPERAND>
           P=P+2
           %IF OPTYPE=0 %OR OPTYPE>3 %THEN ABORT
           %IF OPTYPE=3 %THEN SKIP EXP; ! SUB EXPRESSIONS
!
           %IF OPTYPE=2 %THEN %START;   ! OPERAND IS A CONSTANT
              J=A(P)&7;                 ! CONSTANT TYPE
              %IF J=5 %THEN P=P+A(P+1)+2 %ELSE P=P+1+BYTES(A(P)>>4)
           %FINISH
!
           %IF OPTYPE=1 %THEN %START;   ! NAME
              P=P-1
              P=P+3 %AND SKIP APP %UNTIL A(P)=2 ;! TILL NO ENAME
              P=P+1
           %FINISH
!
           P=P+1
           %IF A(P-1)=2 %THEN %EXIT;    ! NO MORE REST OF EXP
         %REPEAT
         %END;                        ! OF ROUTINE SKIP EXP
%ROUTINE SKIP APP
!***********************************************************************
!*       SKIPS ACTUAL PARAMETER PART                                   *
!*       P IS ON ALT OF P<APP> AT ENTRY                                *
!***********************************************************************
%INTEGER PIN
         PIN=P
         P=P+1 %AND SKIP EXP %WHILE A(P)=1 
         P=P+1
          %END
         %ROUTINE NO APP
            P=P+2
            %IF A(P)=1 %THEN %START;    ! <APP> PRESENT
               FAULT(17,0,FROM AR2(P-2))
               SKIP APP
            %FINISH %ELSE P=P+1;         ! P NOW POINTS TO ENAME
         %END
%ROUTINE TEST APP(%INTEGERNAME NUM)
!***********************************************************************
!*       THIS ROUTINE COUNTS THE NUMBER OF ACTUAL PARAMETERS           *
!*       WHICH IT RETURNS IN NUM.                                      *
!***********************************************************************
%INTEGER PP, Q
         Q=0;  PP=P;  P=P+2;            ! P ON NAME AT ENTRY
         %WHILE A(P)=1 %CYCLE;          ! NO (MORE) PARAMETERS
            P=P+1;  Q=Q+1
            SKIP EXP
         %REPEAT
         P=PP;  NUM=Q
%END
%ROUTINE SETLINE
!***********************************************************************
!*       UPDATE THE STATEMENT NO                                       *
!***********************************************************************
%INTEGER I
      %IF PARM_LINE#0 %START
         I=UCONSTTRIP(SLINE,X'41',0,LINE<<16!CURRINF_DIAGINF+2)
      %FINISH
      %IF PARM_PROF#0 %THEN %START
         I=PROFAAD+4+4*LINE
      %FINISH
%END
%ROUTINE STORE TAG(%INTEGER KK, SLINK)
%INTEGER Q, QQ, QQQ, I, TCELL
%RECORD(LISTF)%NAME LCELL
         TCELL=TAGS(KK)
         Q=PTYPE<<16!LEVEL<<8!RBASE<<4!J
         ABORT %UNLESS (KFORM!ACC)>>16=0
         QQQ=SLINK<<16!KFORM
         QQ=SNDISP<<16!ACC
         %IF FROM1(TCELL)>>8&63=LEVEL %THEN %START
            FAULT(7,0,KK)
            Q=FROM1(TCELL)&X'C000'!Q;! COPY USED BITS ACCROSS
            REPLACE123(TCELL,Q,QQ,QQQ)
         %FINISH %ELSE %START
            I=ASL; %IF I=0 %THEN I=MORE SPACE
            LCELL==ASLIST(I)
            ASL=LCELL_LINK
            LCELL_LINK=TAGS(KK)!CURRINF_NAMES<<18
            LCELL_S1=Q; LCELL_S2=QQ; LCELL_S3=QQQ
            TAGS(KK)=I
            CURRINF_NAMES=KK
         %FINISH
%END
%ROUTINE COPY TAG(%INTEGER TNAME)
!***********************************************************************
!*    A TAG IS A LIST CELL POINTED AT BY TAGS(NAME)                    *
!*    S1 HAS PTYPE<<16!USEBITS(2)!TEXT LEVEL(OLDI6)!RTLEVE(4)!DIMEN    *
!*    S2 HAS SECONDARY DISP(SIGNED)<<16! ACC OR ITEM SIZE IN BYTES     *
!*    S3 HAS PRIMARY DISP(K)<<16!KFORM WHICH IS POINTER TO FORMAT      *
!*                SIDE CHAIN FOR ITEMS OF TYPE RECORD                  *
!*    LINK HAS PTR TO TAG OF NAME HIDDEN WHEN THIS ONE DECLARED        *
!***********************************************************************
%INTEGER QQQ,KK
%RECORD(LISTF)%NAME LCELL
         TCELL=TAGS(TNAME)
         %IF TCELL=0 %THEN %START;        ! NAME NOT SET
           TYPE=7; PTYPE=X'57'; PREC=5
           ROUT=0; NAM=0; ARR=0; LITL=0; ACC=4
           I=-1; J=-1; K=-1; OLDI=-1
         %FINISH %ELSE %START
            LCELL==ASLIST(TCELL)
            KK=LCELL_S1
            LCELL_S1=KK!X'8000'
            MIDCELL=LCELL_S2
            QQQ=LCELL_S3
            PTYPE=KK>>16; USEBITS=KK>>14&3
            OLDI=KK>>8&63; I=KK>>4&15; J=KK&15
            SNDISP=MIDCELL&X'FFFF0000'//X'10000'
            ACC=MIDCELL&X'FFFF'
            K=QQQ>>16
            KFORM=QQQ&X'FFFF'
            LITL=PTYPE>>14
            ROUT=PTYPE>>12&3
            NAM=PTYPE>>10&3
            ARR=PTYPE>>8&3
            PREC=PTYPE>>4&15
            TYPE=PTYPE&15
         %FINISH
%END
%ROUTINE REDUCE TAG
!***********************************************************************
!*       AS COPY TAG FOR NAME AT A(P) EXCEPT:-                         *
!*       1) SPECIAL NAMES HAVE THEIR CORRECT PREC & TYPE SUBSTITUTED   *
!*       2) RECORD ELEMENTS HAVE THE SUBNAME PARTICULARS RETURNED      *
!***********************************************************************
%INTEGER SUBS,QQ,PP
         COPY TAG(FROMAR2(P))
         %IF PTYPE=SNPT %THEN %START
            PTYPE=ACC;  UNPACK
            ROUT=1
         %FINISH;                       ! TO AVOID CHECKING PARAMS
         %IF TYPE=3 %THEN %START
            PP=P; QQ=COPY RECORD TAG(SUBS); P=PP
         %FINISH
%END
! LAYOUT OF PTYPE
! ****** ** *****
! PTYPE REQUIRES 16 BITS TO DEFINE A VARIABLE AND CAN BE REGARDED AS
! AS TWO BYTEINTEGERS:=
! UPPER ONE(UPTYPE):= LITL<<6!ROUT<<4!NAM<<2!ARR
! LOWER ONE(PTYPE) :=PREC<<4!TYPE
! OFTEN (EG IN EXPOP) ONLY THE LOWER PART IS REQUIRED AS FUNCTIONS
! ETC ARE PREFETCHED AND STACKED.
! LITL:= 1=CONST,2=EXTERNAL,3=EXTRINSIC(OR DYNAMIC), 0=NONE OF THESE
! ROUT:= 1 FOR ROUTINE OR FN OR MAP, =0 NONE OF THESE
! NAM := 2 FOR MAPS AND 'REFREFS',=1 FOR NAMES ,=0 DIRECTLY ADDRESSED
! ARR :=1 FOR ARRAYS =0 SCALARS
! PREC IS DESCRIPTOR SIZE CODE FOR EACH PRECISION:-
!     :=0 BITS,=3 BYTES, =5 WORDS, =6 D-WRDS, =7,QUAD WRDS
! TYPE:= THE VARIABLE TYPE 
!     :=0 (TYPE GENERAL),=1 INTEGER, =2 REAL, =3 RECORD
!     :=4 (RECORDFORMAT),=5 STRING,  =6 LABEL/SWITCH. =7 NOT SET
!
%ROUTINE UNPACK
         LITL=PTYPE>>14
         ROUT=PTYPE>>12&3
         NAM=PTYPE>>10&3
         ARR=PTYPE>>8&3
         PREC=PTYPE>>4&15
         TYPE=PTYPE&15
%END
%ROUTINE PACK(%INTEGERNAME PTYPE)
      PTYPE=(((((LITL&3)<<2!ROUT&3)<<2!NAM&3)<<2!ARR&3)<<4! %C
         PREC&15)<<4!TYPE&15
%END
%ROUTINE EVEN ALIGN
!***********************************************************************
!*    SETS N TO EVEN WORD BOUNDARY. SINCE FRAMES ARE DOUBLE            *
!*    WORD ALIGNED THIS MEANS 64 BIT QUANTITIES ARE 64 BIT ALIGNED     *
!*    AND CAN BE REFERNCED IN A SINGLE CORE CYCLE                      *
!***********************************************************************
      %IF N&7=4 %THEN RETURN WSP(N,1) %AND N=N+4
%END
%ROUTINE BYTECUT(%INTEGER ODDEVEN)
!***********************************************************************
!*    ETOS HAS A WORD. EXTRACT HIGH OR LOW ORDER BYTE                  *
!***********************************************************************
      %IF ODDEVEN=0 %THEN %START
         PB2(LDCB,-8)
         PB2(ROTSHI,0)
      %FINISH %ELSE %START
         PBW(LDCW,255)
         PB1(LAND)
      %FINISH
%END
%ROUTINE DSTORE(%INTEGER SIZE,LEVEL,DISP)
!***********************************************************************
!*    STORE SIZE(BYTES) FROM DISP(BYTES) IN DISPLAY 'LEVEL'            *
!***********************************************************************
%INTEGER LEVELCODE,WDISP,OPCODE,WSTORE
      ABORT %UNLESS 0<=DISP<=4096
      WDISP=DISP//2
      WSTORE=SIZE
      %IF LEVEL=0 %THEN LEVELCODE=0 %AND OPCODE=STOW %ELSE %C
         %IF LEVEL=RLEVEL %THEN LEVELCODE=1 %AND OPCODE=STLW %ELSE %C
         LEVELCODE=2 %AND OPCODE=STIW
      %IF SIZE=1 %START;                ! BYTE STORE VIA ARRAY METHOD
         %IF LEVELCODE=2 %THEN PB2W(LIAW,RLEVEL-LEVEL,WDISP) %C
            %ELSE PBW(OPCODE-2,WDISP)
         PB1(EXCH)
         PB1(LDC0+(1!!DISP&1))
         PB1(EXCH)
         PB1(STB)
         %RETURN
      %FINISH
      %WHILE WSTORE>0 %CYCLE
         %IF WSTORE>=4 %AND LEVELCODE#2 %START;! OPTIMISE WITH ST DOUBLES
            PBW(STODW-2*LEVELCODE,WDISP)
            WSTORE=WSTORE-4
            WDISP=WDISP+2
         %FINISH %ELSE %START
            %IF LEVELCODE=2 %THEN PB2W(OPCODE,RLEVEL-LEVEL,WDISP) %C
               %ELSE PBW(OPCODE,WDISP)
            WSTORE=WSTORE-2
            WDISP=WDISP+1
         %FINISH
      %REPEAT
%END
%ROUTINE DFETCHAD(%INTEGER SEGNO,LEVEL,DISP)
!***********************************************************************
!*    FETCH ADDRESS OF DISP(BYTES) IN DISPLAY 'LEVEL'                  *
!***********************************************************************
%INTEGER LEVELCODE,WDISP,OPCODE
      WDISP=DISP//2
      %IF LEVEL=0 %THEN LEVELCODE=0 %AND OPCODE=LOAW%ELSE %C
         %IF LEVEL=RLEVEL %THEN LEVELCODE=1 %AND OPCODE=LLAW %ELSE %C
         LEVELCODE=2 %AND OPCODE=LIAW
      PB1(LSSN) %IF SEGNO=YES
      %IF LEVELCODE=2 %THEN PB2W(OPCODE,RLEVEL-LEVEL,WDISP) %C
         %ELSE PBW(OPCODE,WDISP)
%END
%ROUTINE DFETCH(%INTEGER SIZE,LEVEL,DISP)
!***********************************************************************
!*    FETCH SIZE(BYTES) FROM DISP(BYTES) IN DISPLAY 'LEVEL'            *
!***********************************************************************
%INTEGER LEVELCODE,WDISP,OPCODE,WFETCH
      WDISP=DISP//2+(SIZE-1)>>1
      WFETCH=SIZE
      %IF SIZE=8 %START
         DFETCHAD(NO,LEVEL,DISP)
         PB2(ROPS,37);                  ! FETCH LONREAL
         %RETURN
      %FINISH
      %IF LEVEL=0 %THEN LEVELCODE=0 %AND OPCODE=LDOW %ELSE %C
         %IF LEVEL=RLEVEL %THEN LEVELCODE=1 %AND OPCODE=LDLW %ELSE %C
         LEVELCODE=2 %AND OPCODE=LDIW
      %IF SIZE=4 %AND LEVELCODE=2 %THEN %START
         DFETCHAD(NO,LEVEL,DISP)
         PB1(LDDW)
         %RETURN
      %FINISH
      %WHILE WFETCH>0 %CYCLE
         %IF WFETCH>=4 %AND LEVELCODE#2 %START;! NO LD INTERMEDIATE AS YET!
            PBW(LDODW-2*LEVELCODE,WDISP-1)
            WDISP=WDISP-2
            WFETCH=WFETCH-4
         %FINISH %ELSE %START
            %IF LEVELCODE=2 %THEN PB2W(OPCODE,RLEVEL-LEVEL,WDISP) %C
               %ELSE PBW(OPCODE,WDISP)
            WFETCH=WFETCH-2
            WDISP=WDISP-1
         %FINISH
      %REPEAT
      %IF SIZE=1 %THEN BYTECUT(DISP&1)
%END
%ROUTINE BULKM(%INTEGER MODE,L,D2)
!***********************************************************************
!*       PLANT CODE TO MOVE L BYTES (L KNOWN AT COMPILE TIME) FROM     *
!*        ETOS-2,ETOS-3 TO ETOS,ETOS-1                                 *
!*       IF MODE =0 SET L BYTES TO D2(0 OR X'80')                      *
!*                                                                     *
!*       L MAY BE GREATER THAN 4095                                    *
!***********************************************************************
%INTEGER W2
      %IF MODE=0 %START;                ! CLEAR
         W2=D2<<8!D2
         PB1(REPL2) %UNLESS L=2
         PBW(LDCW,D2)
         PB2(TLATE2,STIND);             ! CLEAR FIRST WORD
         L=L-2
         %RETURN %IF L=0
         PB3(REPL2,INCB,1);             ! FOR PROPAGATION
      %FINISH
      PB1(EXCH2);                       ! PARAMS WRONG WAY UP
      %IF L<=511 %START
         PB2(STLATE,X'31')
         PB2(MOVB,L>>1)
      %FINISH %ELSE %START
         PBW(LDCW,L>>1)
         PB3(STLATE,X'42',MOVW)
      %FINISH
%END;                                   ! OF ROUTINE BULK M
%END;                                  ! OF ROUTINE CSS

%INTEGERFN NEWTRIP
!***********************************************************************
!*    SETS UP A NEW TRIPLE AND LINKS IT IN
!***********************************************************************
%RECORD(TRIPF)%NAME CURRT
%INTEGER I
      CURRT==TRIPLES(NEXT TRIP)
      I=NEXT TRIP
      NEXT TRIP=NEXT TRIP+1
      CURRT=0
      CURRT_BLINK=TRIPLES(0)_BLINK
      TRIPLES(0)_BLINK=I
      TRIPLES(CURRT_BLINK)_FLINK=I
      %RESULT=I
%END
%INTEGERFN UCONSTTRIP(%INTEGER OPERN,OPTYPE,FLAGS,CONST)
!***********************************************************************
!*    SETS UP A UNARY TRIPLE WITH CONSTANT OPERAND                     *
!***********************************************************************
%RECORD(TRIPF) %NAME CURRT
%INTEGER CELL
      CELL = NEW TRIP
      CURRT == TRIPLES(CELL)
      CURRT_OPERN = OPERN
      CURRT_OPTYPE = OPTYPE
      CURRT_FLAGS = FLAGS
      CURRT_OPND1_S1 = X'00510000'
      CURRT_OPND1_D = CONST
      %RESULT = CELL
%END
%INTEGERFN UNAMETRIP(%INTEGER OPERN,OPTYPE,FLAGS,NAME)
!***********************************************************************
!*    SETS UP A UNARY TRIPLE WITH ONE NAME OPERAND                     *
!***********************************************************************
%RECORD(TAGF) %NAME TAGINF
%RECORD(TRIPF) %NAME CURRT
%INTEGER CELL
      TAGINF == ASLIST(TAGS(NAME))
      CELL = NEW TRIP
      CURRT == TRIPLES(CELL)
      CURRT_OPERN = OPERN
      CURRT_OPTYPE = OPTYPE
      CURRT_FLAGS = FLAGS
      CURRT_OPND1_S1 = TAGINF_PTYPE<<16!2
      CURRT_OPND1_D = NAME
      CURRT_OPND1_XTRA = NAME
      %RESULT = CELL
%END
%INTEGERFN UTEMPTRIP(%INTEGER OPERN,OPTYPE,FLAGS,TEMP)
!***********************************************************************
!*    SETS UP A UNARY TRIPLE WITH LOCAL TEMPORARY OPND                 *
!***********************************************************************
%INTEGER CELL
%RECORD(TRIPF)%NAME CURRT
      CELL=NEWTRIP
      CURRT==TRIPLES(CELL)
      CURRT_OPERN=OPERN
      CURRT_OPTYPE=OPTYPE
      CURRT_FLAGS=FLAGS
      CURRT_OPND1_S1=OPTYPE<<16!LOCALIR
      CURRT_OPND1_D=TEMP
      %RESULT=CELL
%END
%INTEGERFN URECTRIP(%INTEGER OPERN,OPTYPE,FLAGS,%RECORD(RD)%NAME OPND1)
!***********************************************************************
!*    SETS UP A BINARY TRIPLE WITH  COMPLETE OPERANDS PROVIDED         *
!***********************************************************************
%INTEGER CELL
%RECORD(TRIPF) %NAME CURRT,REFT
      CELL=NEWTRIP
      CURRT==TRIPLES(CELL)
      CURRT_OPERN=OPERN
      CURRT_OPTYPE=OPTYPE
      CURRT_FLAGS=FLAGS
      CURRT_OPND1=OPND1
      %IF OPND1_FLAG=REFTRIP %START
         REFT==TRIPLES(OPND1_D)
         %IF REFT_CNT=0 %THEN REFT_PUSE=CELL
         REFT_CNT=REFT_CNT+1
      %FINISH
      %RESULT=CELL
%END
%INTEGERFN BRECTRIP(%INTEGER OPERN,OPTYPE,FLAGS,%RECORD(RD)%NAME OPND1,OPND2)
!***********************************************************************
!*    SETS UP A BINARY TRIPLE WITH  COMPLETE OPERANDS PROVIDED         *
!***********************************************************************
%INTEGER CELL
%RECORD(TRIPF) %NAME CURRT,REFT
      CELL=NEWTRIP
      CURRT==TRIPLES(CELL)
      CURRT_OPERN=OPERN
      CURRT_OPTYPE=OPTYPE
      CURRT_FLAGS=FLAGS
      CURRT_OPND1=OPND1
      CURRT_OPND2=OPND2
      %IF OPND1_FLAG=REFTRIP %START
         REFT==TRIPLES(OPND1_D)
         %IF REFT_CNT=0 %THEN REFT_PUSE=CELL
         REFT_CNT=REFT_CNT+1
      %FINISH
      %IF OPND2_FLAG=REFTRIP %START
         REFT==TRIPLES(OPND2_D)
         %IF REFT_CNT=0 %THEN REFT_PUSE=CELL
         REFT_CNT=REFT_CNT+1
      %FINISH
      %RESULT=CELL
%END
%ROUTINE GET WSP(%INTEGERNAME PLACE,%INTEGER SIZE)
!***********************************************************************
!*       FIND OR CREATE A TEMPORARY VARIABLE OF 'SIZE' WORDS           *
!***********************************************************************
%INTEGER J,K,L,F
         F=SIZE>>31;                    ! TOP BIT SET FOR MANUAL RETURN
                                        ! OTHERWISE NOTE IN TWSP LIST
                                        ! FOR AUTOMATIC RETURN
         SIZE=SIZE<<1>>1
         %IF SIZE>4 %THEN SIZE=0
         POP(CURRINF_AVL WSP(SIZE),J,K,L)
         %IF K<=0 %THEN %START;        ! MUST CREATE TEMPORARY
            K=N
            %IF SIZE=0 %THEN N=N+268 %ELSE N=N+SIZE<<2
         %FINISH
         PLACE=K
         PUSH(TWSPHEAD,K,SIZE,0) %UNLESS F#0
         %END
%ROUTINE RETURN WSP(%INTEGER PLACE,SIZE)
!***********************************************************************
!*    RETURNS WORKSPACE TO ORDERED FREE LIST. ADDRESSABLE CELLS        *
!*    ARE PUT AT THE TOP. NON-ADDRESSABLE ON THE BACK                  *
!***********************************************************************
      ABORT %UNLESS PLACE<=N %AND PLACE&1=0
      %IF SIZE>4 %THEN SIZE=0
      %IF PLACE<511 %THEN PUSH(CURRINF_AVL WSP(SIZE),0,PLACE,0) %C
         %ELSE INSERT AT END(CURRINF_AVL WSP(SIZE),0,PLACE,0)
%END
%ROUTINE REUSE TEMPS
%INTEGER  JJ,KK,QQ
         %WHILE TWSPHEAD#0 %CYCLE
            POP(TWSPHEAD,JJ,KK,QQ)
            RETURN WSP(JJ,KK)
         %REPEAT
%END
%END;                                   ! OF SUBBLOCK CONTAINING PASS2
%INTEGERFN FROMAR2(%INTEGER PTR)
      %RESULT=A(PTR)<<8!A(PTR+1)
%END
%INTEGERFN FROMAR4(%INTEGER PTR)
      %RESULT=A(PTR)<<24!A(PTR+1)<<16!A(PTR+2)<<8!A(PTR+3)
%END
%ENDOFPROGRAM