!
! m88p205f.3.i Sep93 pds Change in CRNAME to return correct size
! when recordarrayelement in a record has a record as a subname
!
! m88p205f.i 3Mar 92 PDS
! changes to allow record alignment to go to pass4 on record assignment
externalroutine ICL9CEZRS6IMP
constinteger RELEASE=4
include "hostcodes.inc"
!
CONSTINTEGER HOST=mips
CONSTINTEGER TARGET=MIPS
CONSTINTEGER STANDARDPT=X'51'
CONSTINTEGER MINAPT=X'51';              ! MINIMUM PTYPE FOR WHICH ARITHMETIC
                                        ! OPERATORS ARE AVAILABLE
CONSTINTEGER MINAPREC=MINAPT>>4
CONSTHALFINTEGERARRAY TYPEFLAG(0:12)=0,
                                        X'51'{%INTEGER},
                                        X'52'{%REAL},
                                        X'8009'{%LONG SOMETHING},
                                        X'4031'{%BYTE},
                                        X'35'{%STRING},
                                        X'6051'{%HALF->%INTEGER+WARNING},
                                        X'4041'{%SHORT},
                                        X'33'{%RECORD},
                                        0,
                                        X'61'{%LONG INTEGER FAULT},
                                        X'62'{%LONG REAL},
                                        X'72'{%LONGLONGREAL WARN};
!
! 2****15 SET FOR RELAY TO LOWER PART OF TYPEFLAGS
! 2****14 SET TO SKIP NEXT AR ENTRY FOR BYTE(INTEGER?) ETC
! 2****13 SET IF A DIFFERENT PRECISION USED GIVES WARNING
! 2****12 SET FOR COMBINATION WE CANT SUPPORT GIVES FAULT99
!
CONSTBYTEINTEGERARRAY PTRSIZE(0:127)= C
                                        8,0(15)                 {PREC=0},   
                                        0(16)                   {PREC=1},
                                        0(16)                   {PREC=2},
                                        8,4,0,4,0,8,0,4,0(8)    {PREC=3},
                                        8,4,0(14)               {PREC=4},
                                        8,4,4,0(13)             {PREC=5},
                                        8,0,4,0(13)             {PREC=6},
                                        8,0(15)                 {PREC=7};
CONSTBYTEINTEGERARRAY PTRROUNDING(0:3*128-1)=C
                  3(128)                {ALL PTRS IN RECORDS},
                  3(128)                {ALL PTRS IN STACK FRAMES},
                  3(128)                {ALL PTRS IN PARAMETERS};
CONSTINTEGER SFRAMEMISALIGN=0;          ! NEEDED ONLY FOR 2900 WHERE PRECALL
                                        ! MISALIGNS STACK FRAMES !
CONSTINTEGER AHEADPT=X'61';             ! PTYPE OF ARRAYHEAD WHEN USED AS SCALAR
CONSTINTEGER AHEADSIZE=8;               ! SIZE OF ARRAY HEAD(BYTES)
CONSTINTEGER MINPARAMSIZE=4;            ! MINIMUM STACKABLE PARAMETER(BYTES)
CONSTINTEGER RTPARAMPT=X'51';           ! PTYPER OF RTPARAM WHEN USED AS SCALAR
CONSTINTEGER RTPARAMSIZE=4;             ! SIZE OF RT PARAMETER (BYTES)
CONSTINTEGER ARRAYROUNDING=7;           ! ALL ARRAYS TO 4 BYTE BNDR
CONSTINTEGER ARRAYINRECROUNDING=0;      ! ARRAYS IN RECORDS TO 4 BYTE BOUNDARY
CONSTINTEGER STRVALINWA=YES;            ! STRING VALUE PARAMETERS STACKED
CONSTINTEGER STRRESINWA=YES;            ! STRING&RECORD FN RESULTS STACKED
CONSTINTEGER RECVALINWA=NO;            ! Record values passed via work area
!
CONSTBYTEINTEGERARRAY RNDING(0:3*128-1)= C
                  {VALUES FOR SCALARS PTYPES 0->X'7F' IN SITUATIONS}
                  {FIRST SITUATION IS IN RECORDS}
                  {SECOND SITUATION IS IN STACK FRAMES}
                  {THIRD SITUATION IS AS PARAMETERS}

         0(16)                          {PREC=0},
         0(16)                          {PREC=1},
         0(16)                          {PREC=2},
         0(3),3,0,0,0(10)               {PREC=3},
         0,1,0(14)                      {PREC=4},
         0,3,3,0(13)                    {PREC=5},
         0,7,7,0(13)                    {PREC=6},
         0,7,7,0(13)                    {PREC=7},


         0(16)                          {PREC=0},
         0(16)                          {PREC=1},
         0(16)                          {PREC=2},
         0(3),3,0,1,0(10)               {PREC=3},
         0,1,0(14)                      {PREC=4},
         0,3,3,0(13)                    {PREC=5},
         0,7,7,0(13)                    {PREC=6},
         0,7,7,0(13)                    {PREC=7},


         0(16)                          {PREC=0},
         0(16)                          {PREC=1},
         0(16)                          {PREC=2},
         0,3,0,3,0,3,0(10)              {PREC=3},
         0,3,0(14)                      {PREC=4},
         0,3,3,0(13)                    {PREC=5},
        0,7,7,0(13)                     {PREC=6},   {for non-SPARC}
         {0,3,3,0(13)                   PREC=6,}    {for SPARC and RS6000}
         0,7,7,0(13)                    {PREC=7};

CONSTBYTEINTEGERARRAY BYTES(0:7)=0(3),1,2,4,8,16;
CONSTBYTEINTEGERARRAY WORDS(0:7)=0(3),1,1,2,4,8;
CONSTINTEGER DAREA=6;                   ! SPECIAL DIAGS AREA ON PERQ
CONSTINTEGER DVAREA=4;                  ! CONST DOPE VECTORS IN sst
CONSTINTEGER LHSADDRFIRST=NO;           ! EVALUATE LHS ADDR BEFORE RHS ON ASSNMNT
CONSTINTEGER JRNDBODIES=NO;             ! NO NEED TO JUMP ROUNT RT BODIES
CONSTINTEGER STACK DOWN=YES
CONSTINTEGER PARAMSBWARDS=NO;           ! YES FOR REVERSED PARAMETERS
CONSTINTEGER DISPLAY NEEDED=YES;        ! DISPLAY NEEDED IN LOCAL SPACE
CONSTINTEGER DISPLAY ROUNDING=7;       ! Display on D-W bndry
CONSTINTEGER DISPLAY C1=4;              ! 4 bytes per routine level on RS6000
CONSTINTEGER DISPLAY C0=4;              ! 4 for globals
CONSTINTEGER RTPARAM1OFFSET=0;          ! OFFSET FROM LNB TO PARAM1
CONSTINTEGER ALPHA=0;                   ! post parmeter linkage
!
! END OF CONCATENATED DEFINITIONS
!
!
! Recent Source Changes
!**********************
!
!*                                                                p205e.i
!* 06/12/91 - Changes (pds) to base dictionary size directly on workfile
!*              and/or MAXDICT. Source file size is poor indicator in view
!*              of many large includes.
!*
! Oct 89   Version 5
! Chnages (mostly in CRCALL) to pass record values via work area & pointer
! for risc chips. Controlled by const integer in steering file
!
! DEc88 Version 3 produced
! Changes to note included procedures for Gould and others
! Also change to allow LINT &LINTPT to compile when lonlongs are treated as longs
!
! 8May87 Changes in FPlist so that RT Parameters are aligned according
!        the rules of array Rnding
!
!
! Warning this module has the revised triples spec.
!
! In first attempt at Triple Imp considerable use was made of constant operands
! to pass information from Pass2 to GEN. Although for specialised operations%c
like
! passing Labels this still applies, this adhocery has caused problems with%c
arrays
! and pointers particularly in mapped records. The operands for four triples
! have thus been redefined in a more standard way.
!
! GETPTR    X1 is now (ptype of passed)<<16! DIMENSION
!           Opnd2 is either a 32 bit const with the size (ACC) as value or
!           the ptr or arrayhead as normal operand.
!
! VMY       X1 is now dim<<28!maxdim<<24!array name(where known)
!           Opnd2 is either a 32 bit const with DV offset into const area or
!           the arrayhead as a standard operand
!
! AINDX     X1 is ELSIZE<<20 !spare
!           Opnd2 is arrayhead as standard operand
!           NOTE:- The Operands have been swopped for consistency with norm.
!
! BADJ      X1 is arrayptype<<16!no of Dimensions (latter in case of backward%c
dvs)
!           Opnd2 exactly as for VMY
!

!!{GT:}%include "impcompdate.inc"
   const string (9) LADATE="Apr 95";    ! LAST ALTERED
   const integer MAXRECSIZE=x'ffff'
   const integer NO OF SNS=67
   const integer LRLPT=X'62'
!
   const integer MAXLEVELS=31,CONCOP=13
!
!
! FIRST THE OPERAND FLAG CONSTANTS
!
CONSTINTEGER SCONST=0;                  ! CONST UPTO 64 BITS value is carried
                                        ! in opnd_d and opnd_xtra
CONSTINTEGER LCONST=1;                  ! CONST LONGER THAN SCONST const can be
                                        ! found elsewhere(at top of ar) by
                                        ! meanse of base&offset inf in_d and _xtra
CONSTINTEGER DNAME=2;                   ! NAME BY DICTIONARY NO the base and disp in
                                        ! the dictionary after adjusting by
                                        ! possible offset for item in
                                        ! in records lead to the variable
CONSTINTEGER ARNAME=3;                  ! NAME BY AR POINTER opnd_d the ar pointer
                                        ! this form local to pass2
                                        ! and used to identify functions
                                        ! with params before the call
                                        ! is planted
CONSTINTEGER VIAPTR=4;                  ! VIA TRIPLE WITHOFFSET TO POINTER
                                        ! At an offset(_xtra) from address in
                                        ! referenced triple can be found a
                                        ! pointer to the required operand
CONSTINTEGER INDNAME=5;                 ! INDIRECT VIA DICTIONARY base&disp
                                        ! in dictionary identify a pointer
                                        ! variable at possible offset from
                                        ! this pointer
CONSTINTEGER INDIRECT=6;                ! INDIRECT VIA TRIPLE WITH OFFSET
                                        ! the refenced triple has computed
                                        ! the (32bit) address of an item
                                        ! an offset may have to be applied
                                        ! before the fetch or store
CONSTINTEGER LOCALIR=7;                 ! BASE DISP REF IN CURRENT STACK FRAME
                                        ! opnd_b=base<<16!offset used only for
                                        ! compiler generated temporaries
CONSTINTEGER REFTRIP=8;                 ! REFERENCE TO A TRIPLE the operand is the result of 
                                        ! triple opnd_d
CONSTINTEGER INAREG=9;                  ! REGISTER OPERAND this form is local to the
                                        ! code generating pass(es)
CONSTINTEGER developped=10;             ! also local to generator
CONSTINTEGER DEVADDR=11;                ! ALSO LOCAL TO GENERATOR
CONSTINTEGER BTREFMASK=1<<REFTRIP!1<<INDIRECT!1<<VIAPTR
CONSTINTEGER REFER NEEDED=1<<INDIRECT!1<<VIAPTR
!
! NOW THE DEFINITIONS OF ONE OPERAND TRIPLES <128
!
CONSTINTEGER RTHD=1;                    ! ROUTINE-BLOCK HEADING
CONSTINTEGER RDSPY=2;                   ! ROUTINE ENTRY SET DISPLAY
CONSTINTEGER RDAREA=3;                  ! ROUTINE LEAVE DIAGNOSTIC SPACE
CONSTINTEGER RDPTR=4;                   ! SET DIAGNOSTIC POINTER
CONSTINTEGER RTBAD=5;                   ! ROUTINE-FN BAD EXIT
CONSTINTEGER RTXIT=6;                   ! "%RETURN"
CONSTINTEGER XSTOP=7;                   ! EXECUTE "%STO"
CONSTINTEGER NOTL=10;                   ! LOGICAL NOT
CONSTINTEGER LNEG=11;                   ! LOGICAL NEGATE
CONSTINTEGER IFLOAT=12;                 ! CONVERT INTEGER TO REAL
CONSTINTEGER MODULUS=13;                ! AS USED BY IMOD&RMOD
CONSTINTEGER SHRTN=14;                  ! SHORTEN TO LOWER PRECISION
CONSTINTEGER LNGTHN=15;                 ! LENGTHEN TO HIGHER PRECISION
CONSTINTEGER JAMSHRTN=16;               ! SHORTEN FOR JAM TRANSFER
CONSTINTEGER NULLT=18;                  ! FOR REDUNDANT TRIPLES
CONSTINTEGER PRELOAD=19;                ! PREFETCH FOR OPTIMISATION REASONS
CONSTINTEGER SSPTR=21;                  ! STORE STACK POINTER
CONSTINTEGER RSPTR=22;                  ! RESTORE STACK POINTER
CONSTINTEGER ASPTR=23;                  ! ADVANCE STACK PTR
CONSTINTEGER DARRAY=24;                 ! DECLARE ARRAY(IE STORE HD)
CONSTINTEGER SLINE=25;                  ! UPDATE LINE NO
CONSTINTEGER STPCK=26;                  ! CHECK FOR ZERO STEPS
CONSTINTEGER FORPRE=27;                 ! PREAMBLE FOR "FOR"
CONSTINTEGER FORPOST=28;                ! POSTAMBLE FOR "FOR"
CONSTINTEGER FORPR2=29;                 ! FOR SECOND PREAMBLE
CONSTINTEGER PRECL=30;                  ! PREPARATION FOR CALL
CONSTINTEGER RCALL=31;                  ! THE CALL
CONSTINTEGER RCRFR=32;                  ! RECOVER FN RESULT
CONSTINTEGER RCRMR=33;                  ! RECOVER MAP RESULT
CONSTINTEGER GETAD=35;                  ! GET ADDRESS OF NAME
CONSTINTEGER RTOI1=36;                  ! REAL TO INTEGER AS INT
CONSTINTEGER RTOI2=37;                  ! REAL TO INTEGER INTPT
CONSTINTEGER ITOS1=38;                  ! INTEGER TO STRING AS TOSTRING
CONSTINTEGER MNITR=39;                  ! %MONITOR
CONSTINTEGER PPROF=40;                  ! PRINT PROFILE
CONSTINTEGER RTFP=41;                   ! TURN RT INTO FORMAL PARAMETER
CONSTINTEGER ONEV1=42;                  ! ON EVENT 1 PRIOR TO TRAP
CONSTINTEGER ONEV2=43;                  ! ON EVENT 2 AFTER TRAP
CONSTINTEGER DVSTT=44;                  ! START OF DOPE VECTOR
CONSTINTEGER DVEND=45;                  ! END OF DV EVALUATE TOTSIZE ETC
CONSTINTEGER FOREND=46;                 ! END OF FOR LOOP
CONSTINTEGER DMASS=47;                  ! assign via bim warning to opt only
CONSTINTEGER RTOI3=48;                  ! real to integer as TRUNC
!
! CODES FOR USER WRITTEN ASSEMBLER. NATURALLY THESE ARE NOT
! MACHINE INDEPENDENT
!
CONSTINTEGER UCNOP=50;                  ! FOR CNOPS
CONSTINTEGER UCB1=51;                   ! ONE BYTE OPERATIONS
CONSTINTEGER UCB2=52;                   ! FOR 2 BYTE OPERATIONE
CONSTINTEGER UCB3=53;                   ! FOR 3 BYTE OPERATIONS
CONSTINTEGER UCW=54;                    ! FOR WORD OPERATIONS
CONSTINTEGER UCBW=55;                   ! FOR OPC,BYTEWORD OPERATIONE
CONSTINTEGER UCWW=56;                   ! FOR OPC,WORD,WORD OPERAIONS
CONSTINTEGER UCLW=57;                   ! FOR LONGWORD OPERATIONS
CONSTINTEGER UCB2W=58;                  ! FOR OPC,B1,B2,WORD OPERATIONS
CONSTINTEGER UCNAM=59;                  ! FOR ACESS TO NAMES FROM ASSEMBLER
!
! NOW THE BINARY OPERATIONS
!
CONSTINTEGER ADD=128;                   ! ADDITION
CONSTINTEGER SUB=129;                   ! SUBTRACTION
CONSTINTEGER NONEQ=130;                 ! INTEGER NONEQUIVALENCE
CONSTINTEGER ORL=131;                   ! LOGICAL OR
CONSTINTEGER MULT=132;                  ! MULTIPLICATION
CONSTINTEGER INTDIV=133;                ! INTEGER DIVISION
CONSTINTEGER REALDIV=134;               ! REAL DIVISION
CONSTINTEGER ANDL=135;                  ! LOGICAL AND
CONSTINTEGER RSHIFT=136;                ! LOGICAL RIGHT SHIFT
CONSTINTEGER LSHIFT=137;                ! LOGICAL LEFT SHIFT
CONSTINTEGER REXP=138;                  ! REAL EXPONENTIATION
CONSTINTEGER COMP=139;                  ! COMPARISONS
CONSTINTEGER DCOMP=140;                 ! FIRST PART OF DSIDED(NEEDED?)
CONSTINTEGER VMY=141;                   ! VECTOR MULTIPLY
CONSTINTEGER COMB=142;                  ! COMBINE (IE ADD OF LA) ON VMY RESULTS
CONSTINTEGER VASS=143;                  ! VARAIABLE ASSIGN WITH CHECKING
CONSTINTEGER VJASS=144;                 ! VARIABLE JAMMED ASSIGN
CONSTINTEGER IEXP=145;                  ! INTEGER EXPONENTIAITION
CONSTINTEGER BADJ=146;                  ! BASE ADJUST ARRAY INDEX
CONSTINTEGER AINDX=147;                 ! INDEX ARRAY(COMBINE BS&IX)
CONSTINTEGER IFETCH=148;                ! NO LONGER USED
CONSTINTEGER LASS=149;                  ! ASSIGN LOCAL TEMPORARY
CONSTINTEGER FORCK=150;                 ! VALIDATE FOR
CONSTINTEGER PRECC=151;                 ! PRELIMINARY CONNCATENATION
CONSTINTEGER CONCAT=152;                ! CONCATENATION
CONSTINTEGER IOCPC=153;                 ! CALL IOCP
CONSTINTEGER PASS1=154;                 ! PRIMARY PARAMETER ASSIGNMENT
CONSTINTEGER PASS2=155;                 ! PARAMETER PASSING POINTER PARAMS
CONSTINTEGER PASS3=156;                 ! PARAMETERPASSING ARRAY PARAMETERS
CONSTINTEGER PASS4=157;                 ! PASS A FORMAL PROCEDURE
CONSTINTEGER PASS5=158;                 ! PASS AN UNTYPE(%NAME) PARAMETER
CONSTINTEGER PASS6=159;                 ! PASS STRFN OR RECFN RESULT AREA
CONSTINTEGER BJUMP=160;                 ! BACKWARDS JUMPS
CONSTINTEGER FJUMP=161;                 ! FORWARD JUMPS
CONSTINTEGER REMLB=162;                 ! REMOVE LAB FROM LABELIST
                                        ! NEEDS TO BE TRIPLE IF COMBINED
                                        ! LABEL LIST IS USED
CONSTINTEGER TLAB=163;                  ! TO ENTER A LABEL
CONSTINTEGER DCLSW=164;                 ! DECLARE A SWITCH ARRAY
CONSTINTEGER SETSW=165;                 ! SET A SWITCH TO "CA"
CONSTINTEGER GOTOSW=166;                ! GO TO A SWITCH LABEL
CONSTINTEGER STRASS1=167;               ! STRING GENERAL ASSIGNMET
CONSTINTEGER STRASS2=168;               ! STRING FIXED LENGTH ASSNMENT
CONSTINTEGER STRJT=169;                 ! STRING JAM TRANSFER
CONSTINTEGER AHASS=170;                 ! ASSIGNMENT OF ARRAYHEADS
CONSTINTEGER PTRAS=171;                 ! ASSIGNMENT OF POINTERS
CONSTINTEGER MAPRES=172;                ! ASSIGN MAPPING FN RESULT
CONSTINTEGER FNRES=173;                 ! ASSIGN FN RESULT
CONSTINTEGER SCOMP=174;                 ! STRING COMPARISON
CONSTINTEGER SDCMP=175;                 ! FIRST PART OF STRING D-SIDED
CONSTINTEGER PRES1=176;                 ! PRE RESOLUTION 1
CONSTINTEGER PRES2=177;                 ! PRE RESOLUTION 2
CONSTINTEGER RESLN=178;                 ! STRING RESOLUTION
CONSTINTEGER RESFN=179;                 ! RESOLUTION FINALE
CONSTINTEGER SIGEV=180;                 ! SIGNAL EVENT
CONSTINTEGER RECASS=181;                ! WHOLE RECORD ASSIGNMENT
CONSTINTEGER AAINC=182;                 ! ARRAY ADDRESS ADJUST FOR
                                        ! RECORD RELATIVE TO ABSOLUTE
CONSTINTEGER AHADJ=183;                 ! MODIFY HEAD FOR MAPPING
CONSTINTEGER CTGEN=184;                 ! CREATE TYPE GENERAL PARAMETER
CONSTINTEGER GETPTR=185;                ! POINTER FOR PASSING BY NAME
CONSTINTEGER SINDX=186;                 ! INDEX STRING IE CHARNO
                                        ! SAME AS AINDX FOR ALL TARGETS
                                        ! BUT PNX !
CONSTINTEGER ZCOMP=187;                 ! COMPARISONS WITH ZERO
                                        ! GENERATED BY OPTIMISER
CONSTINTEGER CLSHIFT=188;               ! CONSTANT LOGICAL SHIFT
                                        ! GENERATED BY OPTIMISER
CONSTINTEGER CASHIFT=189;               ! CONSTANT ARITHMETIC SHIFT
                                        ! GENERATED BYOPTIMISER
CONSTINTEGER DVBPR=190;                 ! GENERATE DV ENTRY FOR BOUND PAIR
CONSTINTEGER RSTORE=191;                ! REGISTER TO STORE OPERATION
CONSTINTEGER MULTX=192;                 ! MULTIPLY AND EXTEND PRECISION
!
! RECORDFORMAT FOR ALL THE OPTION AND FLAG VARAIBLES
!
! amended to remove non-alined longreal prior to bootstrapping to gould
!
RECORDFORMAT PARMF(INTEGER BITS1,BITS2,TTOPUT,
      BYTEINTEGER LET,DYNAMIC,LINE,TRACE,ARR,DBUG,CHK,DIAG,OPT,FREE,
      LIST,CPRMODE,COMPILER,Z,Y,PROF,INHCODE,DCOMP,FAULTY,X,STACK,MAP,QUOTES,S2,
      INTEGER LPOPUT,SP0)
RECORDFORMAT LEVELF(INTEGER RBASE, DIAGINF, RAL, FLAG, L, M, NMDECS, ONWORD, ONINF,
         LABEL, JROUND, UNATT FORMATS, PSIZE, ENTRYAD, DISPLAY, AUXSBASE, 
         NAMES, SNMAX,SN,RESSIZE,CLEVEL,SET, iblkid, EXITLAB, CONTLAB, S3,
       INTEGERARRAY AVL WSP(0:4))

IF 1<<host&unsignedshorts=0 START
RECORDFORMAT RD((INTEGER S1 OR SHORT PTYPE,BYTE XB,FLAG),
      ((INTEGER D OR REAL R),
      INTEGER XTRA OR SHORT H0,H1,H2,H3 OR BYTE B0,B1,B2,B3,B4,B5,B6,B7))
RECORDFORMAT TAGF((SHORTINTEGER PTYPE,UIOJ,SNDISP,ACC,SLINK,KFORM OR C
      INTEGER S1,S2,S3),INTEGER LINK)
RECORDFORMAT TRIPF(BYTE OPERN,OPTYPE,CNT,DPTH,
      SHORTINTEGER FLAGS,PUSE,FLINK,BLINK,INTEGER X1,
      RECORD(RD) OPND1,OPND2)
RECORDFORMAT LISTF((SHORTINTEGER PTYPE,(SHORT UIOJ OR BYTE XB,FLAG),
      SHORT SNDISP,ACC,SLINK,KFORM OR  INTEGER S1,S2,S3),INTEGER LINK)
FINISH ELSE START
RECORDFORMAT RD((INTEGER S1 OR HALF PTYPE,BYTE XB,FLAG),
      ((INTEGER D OR REAL R),
      INTEGER XTRA OR HALF H0,H1,H2,H3 OR BYTE B0,B1,B2,B3,B4,B5,B6,B7))
RECORDFORMAT TAGF((HALFINTEGER PTYPE,UIOJ,SNDISP,ACC,SLINK,KFORM OR C
      INTEGER S1,S2,S3),INTEGER LINK)
RECORDFORMAT TRIPF(BYTE OPERN,OPTYPE,CNT,DPTH,
      HALFINTEGER FLAGS,PUSE,FLINK,BLINK,INTEGER X1,
      RECORD(RD) OPND1,OPND2)
RECORDFORMAT LISTF((HALFINTEGER PTYPE,(HALF UIOJ OR BYTE XB,FLAG),
      HALF SNDISP,ACC,SLINK,KFORM OR  INTEGER S1,S2,S3),INTEGER LINK)
FINISH
RECORDFORMAT WORKAF(INTEGER NNAMES,CCSIZE,DSIZE,ASL MAX,ASL CUR BTM,CONST PTR,
      CONST BTM,LASTTRIP,WKFILEAD,WKFILEK,FILE ADDR,RELEASE,AASL0,CONST LIMIT,
      RTCOUNT,ARTOP,AMAINEP,DICTBASE,OPTCNT,INCLHEAD,S2,S3,S4,
      INTEGERNAME LINE,N,S5,STRING(9)LADATE,
      BYTEINTEGERARRAYNAME CC,A,LETT,
      INTEGERARRAYNAME WORD,TAGS,CTABLE,
      RECORD(LEVELF)ARRAYNAME LEVELINF,
      INTEGERARRAY PLABS,PLINK(0:31),
      RECORD(LISTF)ARRAYNAME ASLIST)
!
! TRIPF_FLAGS SIGNIFY AS FOLLOWS
CONSTINTEGER LEAVE STACKED=2****0;      ! SET LEAVE RESULT IN ESTACK
CONSTINTEGER LOADOP1=2****1;            ! OPERAND 1 NEEDS LOADING
CONSTINTEGER LOADOP2=2****2;            ! OPERAND 2 NEEDS LOADING
CONSTINTEGER NOTINREG=2****3;           ! PREVENT REG OPTIMISNG
                                        ! OF TEMPS OVER LOOPS&JUMPS
CONSTINTEGER USE ESTACK=2****4;         ! KEEP DUPLICATE IN ESTACK
CONSTINTEGER USE MSTACK=2****5;         ! PUT DUPLICAT ON MSTACK
CONSTINTEGER CONSTANTOP=2****6;         ! ONE OPERAND IS CONSTANT(FOR FOLDING)
CONSTINTEGER COMMUTABLE=2****7;         ! OPERATION IS COMMUTABLE
CONSTINTEGER BSTRUCT=2****12;           ! Proc contains inner blks or RTs
CONSTINTEGER USED LATE=2****13;         ! I-RESULT USED AFTER LAB OR A LONG WAY AHEAD
CONSTINTEGER ASS LEVEL=2****14;         ! ASSEMBLER LEVEL OPERATION
CONSTINTEGER DONT OPT=2****15;          ! DONT DUPLICATE THIS RESULT
                                        ! USED FOR BYTE PTR & OTHER SODS!
!
RECORDFORMAT EMASFHDRF(INTEGER ENDRA,STARTRA,FBYTESIZE,W3,W4,W5,W6,W7)
                                        ! FORMAT FOR ARRAY HEADS
! %END %OF  %FILE "ERCC07.TRIMP_TFORM1S"
   const integer SNPT=X'1006';           ! SPECIALNAME PTYPE
   const integer UNASSPAT=X'80808080'
   const integer LABUSEDBIT=X'01000000'
   const integer LABSETBIT=X'02000000'
   const integer MAXDICT=X'100';         ! PARM MAXDICT BIT
!
   integer I,K,DUMMYFORMAT,P1SIZE,STARSIZE,ASL,ARSIZE,OLDLINE,NEXTP,SNUM,
      RLEVEL,NMAX,PLABEL,LEVEL,PROFAAD,LAST INST,LINE,N,BFFLAG,RBASE,Q,R,
      FNAME,STMTS,FILE SIZE,BIMSTR,MAX ULAB,SFLABEL,NEXTTRIP
   integer name SSTL,USTPTR
   integer curlinead,nextlinead,currentSSalt
   string (31) MAINEP
!
   external integer array CAS(0:12)
   external record (PARMF) PARM
   external record (WORKAF) WORKA
   if HOST=IBM or HOST=AMDAHL or HOST=IBMXA or HOST=Vax start
      external integer map spec COMREG alias "s#comregmap"(integer N)
   finish else if HOST=Gouldor Host=M88k or Host=RS6 or Host=MIPS  then Start
      externalintegermapspec COMREG  (integer N)
   else
      external integer map spec COMREG alias "s#comreg"(integer N)
   finish
   const integer BYTESPERKFORSOURCE=256;    ! FRACTION OF KB IN WK FILE
                                         ! THATS IS ALLOCATE FOR SOURCE (&LPUT)
   begin
      record (EMASFHDRF) name SHDR,WHDR
      worka = 0
      WORKA_FILE ADDR = COMREG(46);      ! SOURCE FILE IF CLEAN
      PARM = 0
      PARM_BITS1 = COMREG(27)
      PARM_BITS2 = COMREG(28)! MAXDICT
      PARM_TTOPUT = COMREG(40)
      PARM_LPOPUT = COMREG(23)
      WORKA_WKFILEAD = COMREG(14)
      COMREG(24) = 16;                   ! failure as return code
      WHDR == RECORD(WORKA_WKFILEAD)
      WORKA_WKFILEK = WHDR_FBYTESIZE>>10
      if WORKA_FILE ADDR<=0 then start
         if WORKA_FILE ADDR<-1 then FILESIZE = IMOD(WORKA_FILE ADDR) else c
            FILESIZE = 64000
         WORKA_FILE ADDR = 0
      finish else start
         SHDR == RECORD(WORKA_FILE ADDR)
         FILE SIZE = SHDR_ENDRA
      finish
!
! Derive nnames form workfile K ignoring source size because of includes
!
! Note if nnames goes over 4095 the linking of arrayname parameters
! in sw(11) goes wong as their are only 12 bits left intags_uioj
! this is an absolute limit unless pds in prepared to be very ingenious
!

      WORKA_NNAMES = 1023
      if WORKA_WKFILEK>513 then WORKA_NNAMES=2047
     if WORKA_WKFILEK>1000 or PARM_BITS2&MAXDICT#0  then WORKA_NNAMES = 4095
      ASL = 3*WORKA_NNAMES
!      %if ASL>4095 %and (HOST#EMAS %or PARM_BITS2&MAXDICT=0) %then ASL = 4095
      WORKA_ASL MAX = ASL
      ARSIZE = WORKA_WKFILEK*(1024-BYTESPERKFORSOURCE)-300
   end
   byte integer array format AF(0:ARSIZE)
   byte integer array name A
   record (LISTF) array ASLIST(0:ASL)
   integer array TAGS(0:WORKA_NNAMES)
   integer array WORD(0:WORKA_NNAMES)
   integer array DVHEADS(0:12)
   record (LEVELF) array LEVELINF(0:MAXLEVELS)
  recordformat swdataform(integer lseen,default,integerarray slabs(0:1023))
   externalroutinespec free(integer ad)
   externalintegerfnspec malloc(integer space)
   external routine spec INITASL(record (LISTF) array name A,
      integer name B)
 externalroutinespec printtrips(record(tripf)arrayname trops)
 externalroutinespec phex (integer val)
   external integer fn spec MORE SPACE
!%externalintegerfnspec NEWCELL
   external routine spec INSERTATEND(integer name S, integer A,B,C)
   external routine spec INSERT AFTER(integer name S, integer A,B,C)
   external routine spec POP(integer name C,P,Q,R)
   external routine spec PUSH(integer name C, integer S1,S2,S3)
   external integer fn spec FIND(integer LAB,LIST)
   external routine spec BINSERT(integer name T,B, integer S1,S2,S3)
   external routine spec CLEARLIST(integer name HEAD)
   external routine spec FILL DTABREFS(integer name HEAD)
   external routine spec CXREF(string (255) NAME, integer MODE,XTRA,
      integer name AT)
   external routine spec IMPABORT
   external routine spec PROLOGUE(record (LISTF) array name ALIST)
   external routine spec EPILOGUE(integer STMTS)
   external routine spec PDATA(integer AREA,BNDRY,L,AD)
   external routine spec PRDATA(integer AREA,BNDRY,L,REP,AD)
   external integer fn spec PINITOWN(integer PTYPE,ACC,
      record (RD) name INIT, string name XNAME)
   external integer fn spec POWNARRAYHEAD(integer PTYPE,J,LB,SIZE,
      AOFFSET,AAREA,DVOFFSET, string (31) XNAME)
   external routine spec FAULT(integer A,B,C)
   external routine spec WARN(integer N,V)
   external routine spec TRIP OPT(record (TRIPF) array name T,
      integer  first TRIP)
   external routine spec MOVE BYTES(integer LENGTH,FBASE,FOFF,TOBASE,TOOFF)
   external routine spec CTOP(integer name OP,MASK, integer XTRA,
      record (RD) name OPND1,OPND2)
   if HOST#TARGET start
      external routine spec REFORMATC(record (RD) name OPND)
      external routine spec CHANGE SEX(integer BASEAD,OFFSET,L)
   finish
   external routine spec GENERATE(record (TRIPF) array name T,
      integer CURRLEVEL, routine GETWSP(integer name PL, integer SIZE))
externalstringfnspec printname (integer jj)
   external routine spec PRINTLIST(integer HEAD)
                                         ! START OF COMPILATION
   K = host//10
      if k=0 then k=1
   K = BYTESPERKFORSOURCE//K;             ! DISTINGUISH BYTE&WORD ADDRESSED%c
                                         HOSTS
                                         ! ALLOW FOR BYTE & WORD ADDRESS M-CS
   A == ARRAY(WORKA_WKFILE AD+K*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.         *
!***********************************************************************
      external integer fn spec PASSONE
      WORKA_CCSIZE = BYTESPERKFORSOURCE*(WORKA_WKFILEK-1);  ! CCSIZE ALWAYS AS%c
                                                            BYTES
      byte integer array format CCF(0:WORKA_CCSIZE)
      byte integer array name CC
      CC == ARRAY(WORKA_WKFILEAD+32,CCF)
      WORKA_CC == CC
      WORKA_A == A
      WORKA_WORD == WORD
      WORKA_TAGS == TAGS
      WORKA_LINE == LINE
      WORKA_N == N
      WORKA_RELEASE = RELEASE
      WORKA_LADATE = LADATE
      WORKA_AASL0 = ADDR(ASLIST(0))
      WORKA_AMAINEP = ADDR(MAINEP)
      WORKA_LASTTRIP = WORKA_CCSIZE//40-2;  ! 40 IS SIZE OF THE TRIP ARRAY
      if WORKA_LASTTRIP>699 then WORKA_LASTTRIP = 699
      WORKA_OPTCNT = 0;                  ! ZERO COUNT OF OPTIMISATIONS
      worka_const ptr=1;                ! leaving zero for dont knows
      WORKA_ASLIST == ASLIST
      PLABEL = 24999
      N = 12;
      MAX ULAB = WORKA_NNAMES+16384;     ! LARGEST VALID USER LABEL
      LAST INST = 0
      SFLABEL = 20999
      RLEVEL = 0; NMAX = 0; BFFLAG = 0
      RBASE = 1
      SSTL == CAS(4); USTPTR == CAS(5)
      STMTS = 1; SNUM = 0
      BIMSTR = 0
      WORKA_RTCOUNT = 1;                 ! ROUTINE 0 RESERVED FOR MAIN PROG
      MAINEP = "s#go";                   ! DEFAULT MAIN ENTRY
      INITASL(ASLIST,ASL)
      cycle I = 0,1,12
         CAS(I) = 0; 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
   if PARM_FAULTY#0 start
      COMREG(24) = 8
      COMREG(47) = PARM_FAULTY
      return
   finish
   begin
!***********************************************************************
!*    SECOND OR TRIPLES GENERATING PASS                                *
!***********************************************************************
      record (LEVELF) name CURRINF
      integer TWSPHEAD,FORCNT,FORDPTH,FORCECNT,internalblockid
      if HOST=EMAS or HOST=IBM or HOST=AMDAHL or HOST=IBMXA start
                                         ! LPUT BASED WORKFILE USED FOR OBJECT
         record (TRIPF) array TRIPLES(0:WORKA_LASTTRIP)
      finish else start
         record (TRIPF) array format TRIPLESFORM(0:WORKA_LASTTRIP)
         record (TRIPF) array name TRIPLES
         TRIPLES == ARRAY(WORKA_WKFILEAD+32,TRIPLESFORM)
      finish
      integer array format CF(0:12*WORKA_NNAMES)
      integer array name CTABLE
!%routinespec NOTE CREF(%integer CA)
!%routinespec STORE CONST(%integername D,%integer L,AD)
!%integerfnspec WORD CONST(%integer VALUE)
      routine spec REUSE TEMPS
      routine spec GET WSP(integer name PLACE, integer SIZE)
      routine spec RETURN WSP(integer PLACE,SIZE)
      routine spec COMPILE A STMNT
      routine spec outsym(integer sym)
      routinespec force line
      routine spec outstring(string(255) str)
      routinespec outint(integer id)
      integer fn spec NEW TRIP
      integer fn spec FROMAR4(integer PTR)
      integer fn spec FROMAR2(integer PTR)
      integer fn spec UCONSTTRIP(integer OPERN,OPTYPE,FLAGS,CONST)
      integer fn spec ULCONSTTRIP(integer OPERN,OPTYPE,FLAGS,CONST1,CONST2)
      integer fn spec UNAMETRIP(integer OPERN,OPTYPE,FLAGS,NAME)
      integer fn spec UTEMPTRIP(integer OPERN,OPTYPE,FLAGS,TEMP)
      integer fn spec BRECTRIP(integer OPERN,OPTYPE,FLAGS,
         record (RD) name OPND1,OPND2)
      integer fn spec URECTRIP(integer OPERN,OPTYPE,FLAG,
         record (RD) name OPND1)
      routine spec KEEPUSECOUNT(record (RD) name OPND)
      routine spec CSS(integer P)
       recordformat outform(integer line,length,lastnl,prevlast,bytearrayname l)
      ownbyteintegerarray lspace(0:128*1024)
      ownrecord(outform) opline
      constinteger breakoplines=99

      opline=0
      opline_l==lspace
      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'
      TWSPHEAD = 0
      FORCNT = 0;                        ! COUNTS FORS TO DETECT NESTING
      FORDPTH = 0;                       ! COUNTS DEPTH OF NESTED FORS
      FORCECNT = 0;                      ! UPDATED WHEN TRIPLES FORCED OUT
                                         ! KEPT SO THAT GLAENING IS POSSIBLE
      internalblockid=0
      PROLOGUE(ASLIST)
      LINE = 0
      NEXTTRIP = 1
      TRIPLES(0) = 0
      NEXTP = 1; LEVEL = 1; STMTS = 0
      CURRINF == LEVELINF(LEVEL)
      RLEVEL = 0; RBASE = 0
      CURRINF = 0
      CURRINF_CLEVEL = LEVEL
      CURRINF_NAMES = -1
!      %if target=gould %then currinf_maxpp = 8;  ! max parameters passed
      while A(NEXTP+3)!A(NEXTP+4)#0 cycle
         COMPILE A STMNT
      repeat
      outsym(NL)
      outstring("/* end of automatic translation */")
      outsym(NL)
      force line
      LINE = 99999
      EPILOGUE(STMTS)

      if PARM_FAULTY#0 start
         COMREG(24) = 8
         STMTS = PARM_FAULTY
      else
         COMREG(24) = 0
      finish
      COMREG(47) = STMTS
      if HOST=PERQ start
         *RETURN;                        ! JUMP WONT REACH!
      finish else ->P2END
integerfn insert curly(integer cad,at)
!***********************************************************************
!*  Adds in a curly bracket comment                                    *
!*  Checks for the case of a C macro (Ist char #) %and reinserts       *
!*  The 'comment' unchanged                                            *
!***********************************************************************
integer i,j,k,scount,res
ownbytearray save (1:64*1024)
      scount=0
      if at >opline_length then at=opline_length { should not happen }
      for i=at,1,opline_length-1 cycle
          scount=scount+1
          save(scount)=opline_l(i)
      repeat
      opline_length=at

      if byteinteger(curlinead)#'#' { C macro } start
         outsym(9)            { Tab }
         outstring("/*")
      else
         outsym('{')
      finish
      j=cad
      i=0
      cycle
         j=j+1; i=i+1
         if byteinteger(j)=NL or byteinteger(j)='}' start
            if byteinteger(curlinead)#'#' { C macro } start
               outstring("*/")
            else
               if byteinteger(j)='}' then outsym('}')
            finish
            res=i+1
            exit
          else
             opline_l(opline_length)=byteinteger(j)
             opline_length=opline_length+1
          finish
        repeat
      for i=1,1,scount cycle
        opline_l(opline_length)=save(i)
        opline_length=opline_length+1
      repeat
      result=res
end
integerfn locate curly(integer cad)
!***********************************************************************
!* Try to find where to insert a curly comment by counting commas      *
!***********************************************************************
integer ccount,firstc,i,bcount,commaafter
      ccount=0; bcount=0; commaafter=0
!
! first check if there is a comma after the curly comment
!
     i=cad
     i=i+1 until byteinteger(i)='}' or byteinteger(i)=NL
     if byteinteger(i)='}' start
        i=i+1
        i=i+1 while byteinteger(i)=' '
        if byteinteger(i)=',' then commaafter=1 and ccount=1
     finish
      for i=cad,-1,curlinead cycle
         if byteinteger(i)=',' start
            if ccount=0 then firstc=i
            ccount=ccount+1
         finish
      repeat
      if ccount=0 then result=opline_length
      if commaafter=0 start
         for i=firstc,1,cad-1 cycle
             if 33<=byteinteger(i)<=127 then bcount=bcount+1
             if byteinteger(i)='{' or byteinteger(i)='}' then bcount=bcount+1
         repeat
      finish
      for i=0,1,opline_length cycle
         if opline_l(i)=',' or opline_l(i)=';' start
            ccount=ccount-1
            if ccount=0 then -> next
         finish
      repeat
      result=opline_length
next:
!printstring("locate "); write(commaafter,1); write(bcount,0)
!     write(opline_l(i),4);  write(opline_l(i+1),4); newline
      if commaafter#0 then result=i
      if bcount=0 then result=i+1
      for i=i,1,opline_length cycle
        if 33<=opline_l(i)<=127 then bcount=bcount-1
        if bcount=0 then start
            i=i+1 while i<opline_length-1 andc
               ('a'<=opline_l(i+1)<='z' or 'A'<=opline_l(i+1)<='Z' orc
                 '0'<=opline_l(i+1)<='9' or opline_l(i+1)='_') andc
               ('a'<=opline_l(i)<='z' or 'A'<=opline_l(i)<='Z' orc
                 '0'<=opline_l(i)<='9' or opline_l(i)='_')
            if opline_l(i+1)='*' and opline_l(i)='/' then i=i-1
            if opline_l(i+1)='/'  and opline_l(i)='*' then i=i+1
             if opline_l(i+1)='*' and opline_l(i+2)='/' then i=i+2
!printstring("locate2 ");     write(opline_l(i),4);  write(opline_l(i+1),4); newline
            result=i+1
        finish
      repeat
      result=opline_length
end
routine curly check(integer mode)
owninteger last linead
integer i,at

!printstring("checking curly"); write(nextlinead,6); write(curlinead,6)
!write(last linead,6); printsymbol(byteinteger(curlinead));
!printsymbol(byteinteger(curlinead+1)); printsymbol(byteinteger(curlinead+2)); 
!printsymbol(byteinteger(curlinead+3)); printsymbol(byteinteger(curlinead+4));newline
!         %if nextlinead=curlinead %start
!           i=curlinead
!           i=i+1 %while byteinteger(i)=' '
!           %if byteinteger(i)='{' %then warn(12,0)
!        %finish
         if nextlinead>curlinead and curlinead#last linead  c
           and nextlinead-curlinead <=2047 start
            for i=curlinead,1,nextlinead-1 cycle
               if byteinteger(i)='{' then start
                 at=locate curly(i)
                 i=i+insert curly(i,at)
!                 %if mode=1 %then warn(12,0)
               finish
            repeat
           last linead=curlinead     { avoid multiple copies of curlies }
         finish
end
!*
routine force line
!***********************************************************************
!*   Push out current line after dealing with any missed or            *
!*   faulty lines and merging back any {} comments                     *
!***********************************************************************
integer i,at
externalintegerspec filesseen
      if filesseen=0 or line <20000 start { omit include ifiles if any }
!printstring("Force line"); write(nextlinead,5); write(curlinead,5); write(lastlinead,5); newline
!      %for i=curlinead,1,nextlinead %cycle
!          printsymbol(byteinteger(i))
!      %repeat
!      newline
!      %for i=0,1,opline_length-1 %cycle
!           printsymbol(opline_l(i))
!      %repeat
!     newline
!        printstring("  end of force line daignostics"); newline
         curlycheck(0)
         return if opline_length=0
         for i=0,1,opline_length-1 cycle
            print symbol(opline_l(i))
         repeat
         newline
      finish
      i=opline_length-1
      i=i-1 while I>0 and (opline_l(i)='}' or opline_l(i)=NL )
	if i>=0 then opline_prevlast=opline_l(i)
      opline_length=0
      opline_lastnl=-1
end
routine outsym(integer sym)
      if sym=NL then opline_lastnl=opline_length
      opline_l(opline_length)=sym
      opline_length=opline_length+1
      if currentSSalt=12{Const integers and constlists } and sym=',' c
         and opline_length-opline_lastnl > breakoplines>>1 start
         outsym(NL); return
      finish
      if opline_length-opline_lastnl > breakoplines start
         if opline_l(opline_lastnl+1)#'#' start
            if sym=' ' or sym=',' or sym=')' then outsym(NL)
         finish
      finish
end {outsym}
!*
routine outsep
!***********************************************************************
!*    Outputs a semicolon avoiding obvious duplicates                  *
!***********************************************************************
integer i
      i=opline_length-1
      while i>=0 and c
         (opline_l(i)=NL or opline_l(i)='}') cycle
         i=i-1
      repeat
!      printstring("Outsep i,l(i),prev="); write(i,1); space
!      printsymbol(opline_l(i))%if i>=0
!      space; printsymbol(opline_prevlast); newline
      if i>=0 and opline_l(i)=';' then return
      if i<0 and opline_prevlast=';' then return
      outsym(';')
end {outsep}
!*
routine outstring(string(255) s)
integer i,j,sym
      j=opline_length
      for i=1,1,length(s) cycle
         sym=charno(s,i)
         if sym=NL then start
            opline_l(j)='¬'; opline_l(j+1)='n'; j=j+2
         finish else if sym='"' start
            opline_l(j)='¬'; opline_l(j+1)='"'; j=j+2
         else
            opline_l(j)=sym
            j=j+1
         finish
      repeat
      opline_length=j
end
routine outcommentend
      if opline_l(opline_length-1)#'*' start
{GT:}    ! Let 'indent' take care of this ...
         !outsym(' ') %while opline_length-opline_lastnl <78
      finish
      outstring("*/")
end
string(255)fn validname(string(255) name)
!***********************************************************************
!* Check name is not a C reserved word. If so amaned it                *
{GT:} ! Should also check for std library names???
!***********************************************************************
constinteger nr=34+1
conststring(11)array rnames(0:nr)="sizeof","auto","static","extern","register",
                                    "typedef","char","short","long","int",
                                    "unsigned","float","double","void","enum",
                                    "struct","union","if","else","while",
                                    "do","for","switch","case","default",
                                    "break","continue","return","goto","abs",
                                    "fabs","volatile","asm","const","signed",
                    { AND NOW LIBS }"exit"
integer i
      for i=0,1,nr cycle
         if name=rnames(i) then start
            charno(name,1)=charno(name,1)-32
            result=name
         finish
      repeat
      result=name
end
!*
routine revisename(string(255)name name)
integer i
     {if parm_quotes#0 %then} return
     for i=1,1,length(name) cycle
        if 'a'<=charno(name,i)<='z' then charno(name,i)=charno(name,i)-32
     repeat
end
!*
routine outname(integer id)
!***********************************************************************
!*    produce name text from an id                                     *
!***********************************************************************
integer i,ad
record(listf)name lcell
string(255) name
      i=worka_word(id)
      ad=addr(worka_lett(i))
      name=string(ad)
      lcell==aslist(worka_tags(id))
      if lcell_ptype&x'ff00'=x'4000' and lcell_uioj&x'f0'=0 c
         then revisename(name)
      name=validname(name) unless lcell_ptype=x'156'   { Dont revise switches CmcP }
      outstring(name)
      if opline_length-opline_lastnl > breakoplines start
         if opline_l(opline_lastnl+1)#'#' then outsym(NL)
      finish
end
!*
routine outswadname(integer id)
!***********************************************************************
!*   output a sw name adjusting it if in an inner block
!***********************************************************************
integer i,ad
record(listf)name lcell
string(255) name
      i=worka_word(id)
      ad=addr(worka_lett(i))
      name=string(ad)
      lcell==aslist(worka_tags(id))
      if lcell_ptype&x'ff00'=x'4000' and lcell_uioj&x'f0'=0 c
         then revisename(name)
      outstring(name)
      if currinf_iblkid>0 start
         outsym('_'); outint(currinf_iblkid)
      finish
end

integerfn possible typename(integer id,stringname typename)
!***********************************************************************
!*   if id ends in "...type" set typename to ..._type                  *
!***********************************************************************
integer i,ad,j
string(255) name,firstpart,s,t
      i=worka_word(id)
      ad=addr(worka_lett(i))
      name=string(ad)
      j=0;
      while name -> s.("type").name cycle
         if j=0 then firstpart=s else firstpart=firstpart."type".s
        j=j+1
      repeat
      if name="" and length(firstpart)>3 start      { ended in ...type }
         typename=firstpart."_type"
         result=1
      else
         typename="not_a_valid_type_name"
         result=0
      finish
end

routine outrevisablename(integer id)
!***********************************************************************
!*    produce name text from an id  and revise without tag check       *
!***********************************************************************
integer i,ad
string(255) name
      i=worka_word(id)
      ad=addr(worka_lett(i))
      name=string(ad)
      revisename(name)
      outstring(validname(name))
      if opline_length-opline_lastnl > breakoplines start
         if opline_l(opline_lastnl+1)#'#' then outsym(NL)
      finish
end
!*
routine out formatname(integer kf)
integer i,kk
record(listf)name lcell
string(255) s
      for i=0,1,worka_nnames cycle
         kk=tags(i)
         if kk#0 start
            lcell==aslist(kk)
            if lcell_ptype&15=4 and lcell_kform=kf start
               if possible typename(i,s)>0 start
                  outstring(s)
               else
                  if lcell_ptype=4 then outstring("struct ") else outstring("union ")
                  outname(i)
               finish
               return
            finish
         finish
       repeat
       outstring(" ? unknown format name ?")
!      %monitor
end
!*
!*
routine out extern(integer extern)
      if extern&3=0 start
         outstring("static const ")
      finish else if extern=1 start
        outstring("static ")
      finish else if extern=3 start
        outstring("extern ")
      finish
end
routine outhex(integer value)
CONSTSTRING(1)ARRAY HEX(0:15)="0","1","2","3","4",
               "5","6","7","8","9","A","B","C","D","E","F"
INTEGER I,digit
STRING(8)RES
      RES=""
      FOR I=8<<2-4,-4,0 CYCLE
         digit=VALUE>>I&15
          if res#"" or digit#0 then RES=RES.HEX(digit)
      REPEAT
      if res="" then res="0"
      outstring("0x".res)
end

routine outtype(integer type,kf)
      if type=x'31' start
         outstring("unsigned char ")
      finish else if type=x'41' start
         outstring("short int ")
      finish else if type=x'51' start
         outstring("int ")
      finish else if type=x'61' start
         outstring("INT64 ")
      finish else if type=x'52' start
         outstring("float ")
      finish else if type=x'62' start
         outstring("double ")
      finish else if type=x'72' start
         outstring("long double ")
      finish else if type=x'35'  start
          outstring("char * ")
      finish else if type=x'33' start
          outformatname(kf)
         outsym(' ')
      else
         outstring("void ")
{GT:DEBUG outstring("/*");outhex(type);outstring("*/")}
      finish
end {outtype }
!*
routine outxtype(integer xtype,kf)
integer rout,nam,arr,type
       rout=xtype>>12&1
       nam=xtype>>10&3
       arr=xtype>>8&3
       type=xtype&7
       outtype(xtype&255,kf)
       if (rout#0 or arr#0 or nam&1#0) and type#5 then outsym('*')
end

routine outlhex(integer msh,lsh)
CONSTSTRING(1)ARRAY HEX(0:15)="0","1","2","3","4",
               "5","6","7","8","9","A","B","C","D","E","F"
INTEGER I,digit
string(16)res
      RES=""
      FOR I=8<<2-4,-4,0 CYCLE
         digit=msh>>I&15
          if res#"" or digit#0 then RES=RES.HEX(digit)
      REPEAT
      FOR I=8<<2-4,-4,0 CYCLE
         digit=lsh>>I&15
          if res#"" or digit#0 then RES=RES.HEX(digit)
      REPEAT
      if res="" then res="0"
      outstring("0x".res)
end
{GT: outhex moved higher up}
!*
routine outint(integer value)
!***********************************************************************
!*    SIMPLE MINDED ALL IMP VERSION NOT USING STRINGS                  *
!***********************************************************************
INTEGER SIGN,WORK,PTR
BYTEINTEGERARRAY CH(0:15)
      if value=x'80000000' then outhex(value) and return
      SIGN=' '
      IF VALUE<0 THEN SIGN='-' AND VALUE=-VALUE
      PTR=0
      CYCLE
         WORK=VALUE//10
         CH(PTR)=VALUE-10*WORK
         VALUE=WORK
         PTR=PTR+1
      REPEATUNTIL VALUE=0
      WORK=PTR-1
      OUTSYM(SIGN) if sign='-'
      outSYM(CH(PTR)+'0') FOR PTR=WORK,-1,0
end
!*
routine outinternames(integer info)
!***********************************************************************
!* output any intermediate (union) names needed to access              *
!* elements of imps more general record as C struct                    *
!************************************************************************

integer k,id
      for k=12,-4,0 cycle
         id=info>>k&15
         if id#0 start
            if id&8#0 then start
               outstring("s")
               outint(id&7)
            else
               outstring("u")
               outint(id&7-1{ union update })
            finish
            outsym('.')
         finish
      repeat
end
!*
ROUTINESPEC OUTFL (LONGREAL X, INTEGER N)
ROUTINE PRINT (LONGREAL X, INTEGER N,M)
!***********************************************************************
!*       PRINTS A REAL NUMBER (X) ALLOWING N PLACES BEFORE THE DECIMAL *
!*       POINT AND M PLACES AFTER.IT REQUIRES (M+N+2) PRINT PLACES     *
!*       UNLESS (M=0) WHEN  (N+1) PLACES ARE REQUIRED.                 *
!*                                                                     *
!*       A LITTLE CARE IS NEEDED TO AVOID UNNECESSARY LOSS OF ACCURACY *
!*       AND TO AVOID OVERFLOW WHEN DEALING WITH VERY LARGE NUMBERS    *
CONSTLONGREAL DZ=0
!***********************************************************************
LONGREAL Y,Z,ROUND,FACTOR
INTEGER I,J,L,MORIG
BYTEINTEGER SIGN
      M=M&63;                           ! DEAL WITH STUPID PARAMS
      MORIG=M
      IF N<0 THEN N=1; N=N&31;          ! DEAL WITH STUPID PARAMS
      X=X+DZ;                           ! NORMALISE
      SIGN=' ';                         ! '+' IMPLIED
      IF X<0 THEN SIGN='-'
      Y=MOD(X);                         ! ALL WORK DONE WITH Y
      ROUND=0.5/10**M;                  ! ROUNDING FACTOR
      IF Y>1.0*10**16 OR N=0 THENSTART;       ! MEANINGLESS FIGURES GENERATED
         IF N>M THEN M=N;               ! FOR FIXED POINT PRINTING
         OUTFL(X,M);                 ! OF ENORMOUS NUMBERS
         RETURN;                        ! SO PRINT IN FLOATING FORM
      FINISH
      I=0; Z=1; Y=Y+ROUND
      UNTIL Z>Y CYCLE;                  ! COUNT LEADING PLACES
         I=I+1; Z=10*Z;                 ! NO DANGER OF OVERFLOW HERE
      REPEAT
      OUTSYM(SIGN)
      J=I-1; Z=10**J
      FACTOR=1/10
      CYCLE
         UNTIL J<0 CYCLE
            L=INT PT(Y/Z);              ! OBTAIN NEXT DIGIT
            Y=Y-L*Z; Z=Z*FACTOR;        ! AND REDUCE TOTAL
            OUTSYM(L+'0')
            J=J-1
         REPEAT
         IF M=0 THENEXIT;             ! NO DECIMAL PART TO BE O/P
         OUTSTRING(".")
         J=M-1; Z=10**(J-1); M=0
         Y=10*Y*Z
      REPEAT
      if MORIG>0 start          { Chop any redundant trailing 0s}
         opline_length=opline_length-1 while c
           opline_l(opline_length-1)='0' and opline_l(opline_length-2)#'.'
      finish
END;                                    ! OF ROUTINE PRINT
ROUTINE OUTFL (LONGREAL X, INTEGER N)
!***********************************************************************
!*       PRINTS IN FLOATING POINT FORMAT WITH N PLACES AFTER THE       *
!*       DECIMAL POINT. ALWAYS TAKES N+7 PRINTING POSITIONS.           *
!*       CARE REQUIRED TO AVOID OVERFLOW WITH LARGE X                  *
!***********************************************************************
LONGREAL SIGN,ROUND,FACTOR,LB,UB
CONSTLONGREAL DZ=0
INTEGER COUNT,INC
     inc=integer(addr(x))
      if inc>>20&x'7ff'=x'7ff' start
         outstring("NAN {"); outhex(inc); outhex(integer(addr(x)+4))
         outsym('}'); return
      finish
      ROUND=0.5/10**N;                  ! TO ROUND SCALED NO
      LB=1-ROUND; UB=10-ROUND
      SIGN=1
      X=X+DZ;                           ! NORMALISE
      IF X=0 THEN COUNT=0 ELSESTART
         IF X<0 THEN X=-X AND SIGN=-SIGN
         INC=1; COUNT=0
         FACTOR=1/10
         IF X<=1 THEN FACTOR=10 AND INC=-1
                                        ! FORCE INTO RANGE 1->10
         WHILE X<LB OR X>=UB CYCLE
            X=X*FACTOR; COUNT=COUNT+INC
         REPEAT
      FINISH
      PRINT(SIGN*X,1,N)
      if count#0 start
         OUTSTRING("E")
         OUTINT(COUNT)
      finish
END;                                    ! OF ROUTINE OUTFL
   routine FORCE TRIPS
!***********************************************************************
!*    FORCE OUT THE TRIPLES TO CODE. NEEDED IN CEND ETC                *
!***********************************************************************
      triples(0)=0
      nexttrip=1
      triples(0)_flink=1       { return any triples }
      end

      routine COMPILE A STMNT
         integer I
         force trips
         I = NEXTP
         STARSIZE = A(NEXTP)<<16+A(NEXTP+1)<<8+A(NEXTP+2)
         NEXTP = NEXTP+STARSIZE
         LINE = A(I+3)<<8+A(I+4)
         curlinead=fromar4(I+5)
         nextlinead=fromar4(NEXTP+5)
         STMTS = STMTS+1
         opline_line=line
         CSS(I+9)
          if a(NEXTP+3)<<8!A(NEXTP+4)=line then start
           curly check(1)
           outsym(9)
         else
            force line
         finish
      end
integerfn nextstmntalt
      result=a(NEXTP+9)
end
      routine CSS(integer Pinit)
         routine spec ENTER JUMP(integer MASK,STAD,FLAG)
         integer fn spec ENTER LAB(integer M,FLAG)
         routine spec REMOVE LAB(integer LAB)
         routine spec SAVE STACK PTR
         routine spec CEND(integer KKK)
         integer fn spec CCOND(integer CTO,A,B,JFLAGS)
         integer fn spec REVERSE(integer MASK)
         routine spec SET LINE
         routine spec CUI(integer CODE)
         routine spec ASSIGN(integer A,B)
         routine spec CSTART(integer CCRES,MODE)
         routine spec CCYCBODY(integer UA,ELAB,CLAB)
         routine spec CLOOP(integer ALT,MARKC,MARKUI)
         routine spec CIFTHEN(integer MARKIU,MARKC,MARKUI,MARKE,MARKR,Afterelse)
         integer fn spec CREATE AH(integer MODE,
            record (RD) name EOPND,NOPND)
         routine spec TORP(integer name HEAD,BOT,NOPS,integer mode)
         integer fn spec INTEXP(integer name VALUE, integer PRECTYPE)
         integer fn spec CONSTEXP(integer PRECTYPE)
         routine spec CSEXP(integer MODE)
         routine spec labexp
         routine spec outopnd(record(rd)name opnd,integer mode)
         routine spec outtriple(integer tripno,mode)
         routine spec CSTREXP(integer B)
         routine spec CRES(integer LAB)
         routine spec EXPOP(integer name A,B, integer C,D)
         routine spec TEST APP(integer name NUM)
         routine spec SKIP EXP
         routine spec SKIP APP
         routine spec NO APP
         integer fn spec DOPE VECTOR(integer A,B,C,MODE,ID)
         routine spec DECLARE ARRAYS(integer A,B)
         routine spec DECLARE SCALARS(integer B)
         routine spec CRSPEC(integer M)
         routine spec CFPLIST(integer name A,B)
         routine spec CFPDEL
         routine spec CLT
         integer fn spec ROUNDING LENGTH(integer PTYPE,RULES)
         routine spec CQN(integer P)
         integer fn spec TSEXP(integer name VALUE)
          integer fn spec tcond
         routine spec CRCALL(integer RTNAME)
         routine spec NAMEOP(integer Z,SIZE,NAMEP)
         routine spec CNAME(integer Z)
         routine spec CANAME(integer Z,ARRP, record (RD) name HDOPND)
         routine spec CSNAME(integer Z)
         routine spec COPY TAG(integer KK,DECLARE)
         routine spec REDUCE TAG(integer DECLARE)
         routine spec STORE TAG(integer KK,LEVEL,RBASE,J,SNDISP,ACC,SLINK,
            KFORM)
         routine spec UNPACK
         routine spec PACK(integer name PTYPE)
         routine spec RDISPLAY(integer KK)
         routine spec RHEAD(integer RTNAME,AXNAME,Xtra)
         integer fn spec CFORMATREF
         routine spec CRFORMAT(integer myrflevel)
            routinespec process format(integer level,alt,structor union,intid,
                  integername strid,ophed,opbot)
         integer fn spec DISPLACEMENT(integer LINK)
         integer fn spec COPY RECORD TAG(integer name SUBS)
         integer fn spec CHK REC ALIGN(integer p1)
         switch SW(1:24)
         const byte integer array FCOMP(0:14)=0,
                                   8,10,2,7,12,4,7,
                                   8,12,4,7,10,2,7
integer array rfhead,rfbot(0:12,0:12),rfalt(0:12)
integer rflevel

         integer P,SNDISP,ACC,K,KFORM,STNAME,MIDCELL
         integer TCELL,JJ,JJJ,KK,QQ,MARKER,REPORTUI,XDISP,MASK,BASE,AREA,
            ACCESS,DISP,EXTRN,CURR INST,VALUE,STRINGL,PTYPE,I,J,OLDI,USEBITS,
            STRFNRES,MARKIU,MARKUI,MARKC,MARKE,MARKR,INAFORMAT
         integer LITL,ROUT,NAM,ARR,PREC,TYPE,lhformatname,doinglabel
         record (RD) EXPOPND,NAMEOPND,MLOPND;   ! RESULT RECORD FOR EXPOP&CNAME
!
! on some machines global parameters are difficult to access hence
! copy pinit into local P which is frequently updated globally
!
         P = Pinit
        doinglabel=0
         CURR INST = 0; INAFORMAT = 0
         currentSSalt=a(p)
         ->SW(currentSSalt)
SW(13):                                  ! INCLUDE SOMETHING
      begin
      string(255) s,head,tail
      s=string(addr(a(P+2)))       { File name}
      if s-> head.(".inc").tail then s=head.".h"
      outstring("#include "); outsym('"')
      outstring(s)
      outsym('"')
      end
      ->cssexit2
SW(24):                                  ! REDUNDANT SEP
      if a(p+1)=10 then outsym(' ')         { extar neline }
      ->css exit2
SW(2):                                   ! <CMARK> <COMMENT TEXT>
      p=p+1
      kk=a(p); p=p+1;                    ! kk=1 # comment, =2 ! comment, =3 %comment
       jj=a(p); jjj=0
      if KK=1 then outsym('#') else outstring("/*")    { preserve any #defines in the imp}
      while jj#NL cycle
         if JJ>128 and jjj<128 then outsym('%')
         outsym(jj&127)
         jjj=jj
         p=p+1; jj=a(p)
         if jjj='¬' and JJ=13{CR} and KK=1 then outsym(NL) and p=p+1 and continue
         if jjj=',' and ((kk=2 and jj='!') or (kk=1 and jj='#')) start { unscramble comments ending with a comma = continuation}
            if kk=1 start
               outsym(NL); outsym('#')
            else
               outcommentend; outsym(NL)
               outstring("/*")
            finish
            jjj=jj; p=p+1; jj=a(p)
         finish
      repeat
      if kk>1 then outcommentend
      ->CSSEXIT2
CSSEXIT: outsep unless opline_length>0 and  opline_l(opline_length-1)='}'
Cssexit2: 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 c
            CIFTHEN(MARKIU,MARKC,MARKUI,0,0,NO) 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)
         outname(from ar2(P+3))
         outsym(':'); curly check(0);  outsym(NL);
        if 1<<next stmntalt&(1<<6!1<<4!1<<18!1<<9)#0 then outsep
         ->CSSEXIT2
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
         ->CSSEXIT2
SW(22):                                  ! '%CONTROL' (CONST)
         ->CSSEXIT2
!
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)
SW(18):
                                         ! '%ELSE' MEANING FINISH ELSE START
         ->CSSEXIT2
SWITCH:  begin;                          ! SWITCH LABEL
            record (LISTF) name LCELL
            record(swdataform)name swdata
            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+6
            COPY TAG(FNAME,NO)
            if OLDI#LEVEL or TYPE#6 then FAULT(4,0,FNAME) and ->BEND
            LCELL==aslist(k)
            swdata==record(LCELL_S1)
            swdata_slabs(swdata_lseen)=p
            swdata_lseen=swdata_lseen+1
            outswadname(fname); outstring("_"); labexp; outsym(':')
            curly check(0); outsym(NL);
           if 1<<next stmntalt&(1<<6!1<<4!1<<18!1<<9)#0 then outsep
BEND:    end
         FORCE TRIPS if PARM_OPT=0
         ->CSSEXIT2
SW(23):
                                         ! SWITCH(*):
         begin
            record (LISTF) name LCELL
            record(swdataform)name swdata
            integer FNAME,JJ,RES
            FNAME = FROM AR2(P+1)
            COPY TAG(FNAME,NO)
            if OLDI=LEVEL and TYPE=6 start
               LCELL == ASLIST(K)
               swdata==record(LCELL_S1)
               swdata_default=p
               outswadname(fname); outstring("_default:")
            finish else FAULT(4,0,FNAME)
         end
         FORCE TRIPS if PARM_OPT=0
         ->CSSEXIT2
!
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
         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)
            if qq=1 then ->cssexit2   { ignore formats }
            FORCE TRIPS if PARM_OPT=0
         finish else start
            CLT
            CQN(P+1); P = P+2
            DECLARE SCALARS(KFORM)
         finish
         ->CSSEXIT
!
SW(9):                                   ! %end
         begin
            switch S(1:5)
           integer etype
            etype=A(P+1)
            ->S(etype)
S(1):                                    ! ENDOFPROGRAM
{GT:}       outstring("exit(0);"{"imp_stop();"}); outsym(NL)
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)
            outsym('}') if etype=1
            ->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)
            outstring("}"); ! outstring(" /* proc */")
BEND:    end
         ->CSSEXIT2
!
SW(11):
         begin
            integer MARKER1,RTNAME,KKK,PTR,PTYPEP,CNT,PP,PCHAIN,AXNAME,
               PNAME,NPARAMS,SCHAIN,PARMSPACE,D,PARAMPTYPE,PARAMACC,pcount
            record (LISTF) name LCELL,LCELL2,TCELL
            P = P+1; MARKER1 = FROM AR2(P)+P;  ! (SEX)(RT)(SPEC')(NAME)(FPP)
           markc=a(marker1)
AGN:        Q = P; RTNAME = FROM AR2(MARKER1+3);  ! 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
            FORCE TRIPS;                 ! IN CASE OPTIMISING
            COPY TAG(RTNAME,NO)
            AXNAME = ADDR(WORKA_LETT(WORD(RTNAME)))
            if EXTRN=3 then EXTRN = 2
            if TARGET=EMAS and EXTRN=1 then WARN(11,0)
            if A(MARKER1+5)=1 then start;   ! extract alias name
               MOVE BYTES(A(MARKER1+6)+1,ADDR(A(0)),MARKER1+6,ADDR(A(0)),
                  WORKA_ARTOP)
               AXNAME = ADDR(A(WORKA_ARTOP))
               WORKA_ARTOP = (WORKA_ARTOP+4+A(MARKER1+6))&(-4)
            finish
            if EXTRN=4 then AXNAME = 0
            if OLDI#LEVEL then start;     ! NAME NOT KNOWN AT THIS LEVEL
               P = Q+3; CRSPEC(2); P = Q; ->AGN
            finish else start;           ! NAME ALREADY KNOWN AT THIS LEVEL
               if PARM_CPRMODE=0 then PARM_CPRMODE = 2;    ! FLAG AS FILE OF%c
                                                           ROUTINES
               FAULT(56,0,RTNAME) unless c
                  EXTRN=4 or (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 (J=15 or J=7*EXTRN) and PTYPE&X'FFFF'=KKK start
               P = Q+3; CRSPEC(2); P = Q; ->AGN
            finish
{GT:} ! BUG !!!  externalroutinespec fred(int i)
!       translates to void fred(void)

            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 COPY TAG IN THIS SEQUENCE
!
            TCELL == ASLIST(TAGS(RTNAME))
            TCELL_PTYPE <- PTYPE
            if PTYPE&x'c000'=x'8000' then USEBITS = 2;    ! externals presumed%c
                                                          'used'

            TCELL_UIOJ <- TCELL_UIOJ&X'3FF0'!USEBITS<<14
                                         ! NEWPTYPE & SET J=0
            if (target=Perq or Target=Accent) and J=14 then c
              TCELL_S2 = WORKA_RTCOUNT and WORKA_RTCOUNT = WORKA_RTCOUNT+1
                                         ! NO RT NO ALLOCATED TO EXTERNAL SPECS
            PTYPEP = PTYPE
               if ptypep&x'c000'=0 then outstring("static ")
               outtype(ptypep&255,tcell_kform)
               if ptypep&x'800'#0 and ptypep&7#5 then outsym('*')
               if axname=0 then outname(rtname) else outstring(string(axname))
               outsym('(')
            PCHAIN = TCELL_SLINK;        ! CHAIN OF PARAMETER DESCRIPTUONS
            RHEAD(RTNAME,AXNAME,fromar2(marker1+1));! FIRST PART OF ENTRY SEQUENCE
!
! NOW DECLARE THE FORMAL PARAMETERS. FOLLOW BY CLAIMING DISPLAY
! AND SETTING DIAGNOSTIC PTR IN ROUTINE RDISPLAY
!
            P = MARKER1+6
            if A(P-1)=1 then P = P+A(P)+1;    ! SKIP OVER ALIASNAME
            CNT = 0
            PTYPE = PTYPEP; UNPACK
            N = RTPARAM1OFFSET
            if TARGET=PERQ or TARGET=ACCENT start
               if TYPE#0 then N = (BYTES(PREC)+1)&(-2)
               if TYPE=5 or TYPE=3 then N = 4;     ! MAPS
               if NAM#0 then start
                  if TYPE=5 then N = 4 else N = PTRSIZE(PTYPE&127)
                                         ! BYTE MAPS RETURN BYTE PTR
               finish
               CURRINF_RESSIZE = N
            finish
            NPARAMS = 0; PARMSPACE = 0
            if PCHAIN#0 then NPARAMS = ASLIST(PCHAIN)_S3
            if NPARAMS#0 then c
               PARMSPACE = NPARAMS>>16 and NPARAMS = NPARAMS&X'FF'
                                         ! ALLOW ACTUAL PARAMETER SPACE
            while A(P)=1 cycle;          ! WHILE SOME (MORE) FP PART
               PP = P+1+FROMAR2(P+1)
               P = P+3
               CFPDEL
               PARAMPTYPE = PTYPE; PARAMACC = ACC;  ! may get cahnged for rt%c
                                                    types
               PTR = P
               until A(PTR-1)=2 cycle;    ! CYCLE DOWN NAMELIST
                  if PARAMS BWARDS=YES start;    ! MAP PCHAIN TO REVERSE ORDER%c
                                                 LIST
                     PCHAIN = TCELL_SLINK
                     PCHAIN = ASLIST(PCHAIN)_LINK for KKK = 2,1,NPARAMS-CNT
                  finish
                  LCELL == ASLIST(PCHAIN);  ! EXTRACT PTYPE XTRA INFO
                  if PCHAIN#0 then start
                     unless LCELL_PTYPE=PARAMPTYPE and c
                        LCELL_ACC&x'FFFF'=PARAMACC then FAULT(9,CNT+1,RTNAME)
                  finish
                  PNAME = FROM AR2(PTR);  ! NAME FOR PARAM INTERNALLY
                  LCELL_UIOJ <- LCELL_UIOJ!PNAME<<4;  ! SAVED IN LIST( max 12 bits!)
                  D = LCELL_SNDISP+N;    ! PARAMETER OFFSET
                  if PARAMPTYPE&x'1000'#0 start;    ! PROCEDURE PARAMETERS
                     P = PTR
                     P = P+3 until A(P-1)=2
                     CFPLIST(SCHAIN,KKK);  ! PARAMETERLIST FOR PASSED PROC
                     PTYPE = PARAMPTYPE;  ! CHANGED BY CFPLIST
                     outtype(paramptype&255,kform); outname(pname); outstring("(")
                     lcell2==aslist(schain)
                     if KKK=0 then outstring("void ") else start
                        for pcount=1,1,KKK cycle
                           if lcell2_s1&x'10000000'#0 start
                              outtype(lcell2_s1>>16&255,lcell2_sndisp); outstring("()")
                           else
                              outxtype(lcell2_s1>>16,lcell2_sndisp)
                           finish
                           if lcell2_link#0 then outsym(',')
                           lcell2==aslist(lcell2_link)
                        repeat
                     finish
                     outstring(")")
                     STORETAG(PNAME,LEVEL,RBASE,13,D,LCELL_ACC,SCHAIN,0)
                  finish else start
                     if TARGET=EMAS and PTYPE=X'33' then D = D+8
                                         ! FOR HISTORIC PARAMTER COMPATABILITY
                     if STRVALINWA=YES and PTYPE=X'35' then PTYPE = X'435'
!                      %if recvalinwa=yes %and ptype=X'33' %and acc#4 %then ptype=x'433'
                     outxtype(paramptype,kform); outname(pname);
                     STORE TAG(PNAME,LEVEL,RBASE,LCELL_UIOJ&15,0,ACC,D,KFORM)
                     PTYPE = PARAMPTYPE
                  finish
                  PTR = PTR+3
                  CNT = CNT+1
                  PCHAIN = LCELL_LINK if PARAMS BWARDS=NO
            outsym(',') unless pchain=0
               repeat
               P = PP
            repeat;                      ! UNTIL NO MORE FP-PART
            outstring(") {")
            N = N+PARMSPACE
            N = (N+MINPARAMSIZE-1)&(-MINPARAMSIZE);  ! TO WORD BOUNDARY AFTER%c
                                                     ALL SYSTEM
                                         ! STANDARD PARAMETERS HAVE BEEN%c
                                         DECLARED
            FAULT(8,0,RTNAME) if CNT>NPARAMS
            FAULT(10,0,RTNAME) if CNT<NPARAMS
            PTYPE = PTYPEP
            if STRRESINWA=YES start;     ! NEEDS FN RESULT DESC
               unless 3#PTYPE&X'F0F'#5 then N = N+PTRSIZE(X'35')
                                         ! STR FNS RESULT PARAM IS STACKED
               CURRINF_RESSIZE = N
            finish
            N = N+ALPHA;                 ! allow for link bytes on unix(etc)
            if TARGET=PNX then start
               IMPABORT if N&7#0
            finish
                                         ! AS XTRA PARM JUST BEFORE DISPLAY
            RDISPLAY(RTNAME)
BEND:    end
      Force trips if parm_opt=0; ! Problems if procname redeclared
                                         ! as new proc before entry code planted
         ->cssexit2
!
SW(14):                                  ! %begin
         begin
            FORCE TRIPS;                 ! IN CASE OPTIMISING
            PTYPE = 0
            if LEVEL=1 and RLEVEL=0 start
               if PARM_CPRMODE=0 then start
                  RLEVEL = 1; RBASE = 1
                  PARM_CPRMODE = 1
                  RHEAD(-1,ADDR(MAINEP),1)
                  N = RTPARAM1OFFSET+alpha
                  outstring("main() {")
               finish else FAULT(58,0,0)
            finish else start
               SET LINE;                 ! SO 'ENTERED FROM LINE' IS OK
               outstring("{")
               RHEAD(-1,0,1)
            finish
            RDISPLAY(-1)
         end
         ->CSSEXIT2
!
SW(15):
                               ! '%ON'(EVENT')(N)(NLIST)'%start'

! Shouldn't we compile a CSTART(..., 3) here? ... Yes! - code supplied by PDS:

         p=p+2; skip exp;
         while a(p)=1 cycle
           p=p+1
           skip exp
         repeat
         p=p+1
         outstring("if (0) {")
         outsym(NL)
         cstart(0,3)
         outstring(" }")

! and in cstart, do...  %if code=3 %then outstring("#endif /* On event */") %and outsym(NL)
! so ... where is the %FINISH handled if not there???

         ->CSSEXIT

SW(16):
         begin;                          ! %switch (SWITCH LIST)
            integer Q,RANGE,KKK,LB,UB,PP,D0,OPHEAD,V,R,datad
            record (RD) OPND1,OPND2
            record(swdataform)name swdata
!            FAULT(57,0,0) %unless LEVEL>=2
            Q = P
            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,MINAPT);  ! EXTRACT LOWER BOUND
               P = P+3
               KKK = KKK!INTEXP(UB,MINAPT);  ! EXTRACT UPPER BOUND
               RANGE = (UB-LB+1)
               if RANGE<=0 or KKK#0 start
                  LB = 0; UB = 10; RANGE = 1024
               finish
               datad=malloc(4*range+8)
               swdata==record(datad)
               swdata_lseen=0; swdata_default=0
               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
                  OPND1_PTYPE <- PTYPE
                  OPND1_XB = 0
                  OPND1_FLAG = DNAME
                  OPND1_D = K
                  OPND1_XTRA = 0
                  OPND2_PTYPE = X'61'
                  OPND2_XB = 0
                  OPND2_FLAG = DNAME
                  OPND2_D = LB
                  OPND2_XTRA = UB
                  V = BRECTRIP(DCLSW,PTYPE,0,OPND1,OPND2)
                  PUSH(OPHEAD,datad,LB,UB)
                  STORE TAG(K,LEVEL,RBASE,1,0,4,OPHEAD,0)
{GT:}             outstring("int "); outswadname(k); outstring("_value;")
{GT:}             outstring("int "); outswadname(k); outstring("_line;")
{GT:}             outstring("char *"); outswadname(k); outstring("_file;")
               repeat;                   ! FOR ANY MORE NAMES IN NAMELIST
               Q = PP; P = Q
            repeat;                      ! UNTIL A(Q)=2
         end; ->CSSEXIT2
!
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.            *
!***********************************************************************
            routine spec CLEAR(integer L)
            routine spec XTRACT CONST(integer CONTYPE,CONPREC)
            integerfn spec INIT SPACE(integer A,B)
            integer SLENGTH,PP,SIGN,TAGDISP,DVO,K,STALLOC,SPOINT,tp,savep,
               CONSTSFOUND,CPREC,EXTRN,NNAMES,MARK,QPUTP,LB,CTYPE,CONSTP,
               FORMAT,DPTYPE,DIMEN,SACC,TYPEP,KK,orlevel,savesndisp,savekform,II
            record (RD) COPND,FCOPND
            own long real ZERO=0
            string (255) SCONST,NAMTXT
            record (LISTF) name LCELL
            QPUTP = 5;                  ! NORMAL CASE GLA SYMBOLTABLES
            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 = 4
            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 (A(P)=2 and c
               A(P+1)#2)) then FAULT(46,0,0)
            if type=5 and a(p)#1 and extrn=0 then extrn=1
            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%c
                                         POINTER
            if (TARGET=PERQ or TARGET=ACCENT or TARGET=PNX) and c
               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(ADDR(WORKA_LETT(WORD(K))))
               if A(P)=1 then start;     ! ALAIS GIVEN
                  if LITL=0 then WARN(10,0)
                  LENGTH(NAMTXT) = A(P+1)
                  CHARNO(NAMTXT,KK) = A(P+KK+1) for KK = 1,1,A(P+1)
                  P = P+A(P+1)+1
                  outstring("#define "); outname(k); outsym(' ')
                  outstring(namtxt); outsym(NL)
               finish
               P = P+1;                  ! P ON CONST'
!
! OBTAIN THE INITIAL CONSTANT,ITS TYPE(CTYPE) AND SIGN(SIGN)
!
               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 RLEVEL=0 and EXTRN=0 start
                  outstring("#define ")
                  outrevisablename(k)
               else
                  out extern(EXTRN)
                  if ptype=x'35' then outstring("char ") else outtype(ptype&255,kform)
                  if nam#0 then outsym('*')
                  outname(k)
               finish
               if ptype=x'35' then start
                  outstring(" ["); outint(stalloc); outsym(']')
               finish
               tp=1
               if A(P-1)=1 then start;     ! CONSTANT GIVEN
                  savep=p; p=p-3; tp=tsexp(kk); p=savep
                  if RLEVEL=0 and EXTRN=0 start
                     outstring(" "); outstring("(") if tp<=0
                  else
                     outsym('=')
                  finish
                  XTRACT CONST(CTYPE,CPREC)
               finish else start
                  WARN(7,K) if EXTRN=0;   ! %const NOT INITIALISED
                  FCOPND = 0; COPND = 0
               finish
               if RLEVEL=0 and EXTRN=0 start
                 outsym(')') if tp<=0
               else
                 outsep
               finish
               outsym(NL) unless a(MARK)=2
               PTYPE = DPTYPE; UNPACK;   ! MAY HAVE BEEN CONSTANT EVALUATIONS
                                         ! WHICH HAVE CHANGED PTYPE
               J = 0; orlevel = 0
               if NAM#0 then start;      ! OWNNAMES AND ARRAYNAMES
                  if ARR=0 then start
                     if (target=ibm or target=amdahl or target=ibmxa) and c
                        extrn=0 start
                        tagdisp = worka_const ptr
                        if type=5 then ctable(tagdisp)=acc and c
                             worka_const ptr=worka_const ptr+1
                        ctable(worka_const ptr) = fcopnd_d
                        worka_const ptr = worka_const ptr+1
                        if worka_const ptr>worka_const limit then c
                           fault(102,worka_wkfilek,0)
                        tagdisp = 4*tagdisp; orlevel = 14
                     finish else TAGDISP = PINITOWN(PTYPE,ACC,FCOPND,NAMTXT)
                  finish else start;     ! ARRAYNAMES
!                     DVO = DOPE VECTOR(NO,TYPE,ACC,-1,K,QQ,LB)
                     if PARM_COMPILER#0 and LB#0 then FAULT(99,0,0)
                     if EXTRN#0 then SNDISP = 0 and J = 0 else c
                        J = 1 and SNDISP = (SNDISP&X'3FFFF')>>2
                     TAGDISP = POWNARRAYHEAD(PTYPE,J,LB,X'FFFFFF',COPND_D,0,
                        DVO,NAMTXT)
                  finish
                  STORE TAG(K,LEVEL,orlevel,J,SNDISP,ACC,TAGDISP,KFORM)
                  P = MARK
                  continue
               finish
               if EXTRN=3 then start;     ! EXTRINISIC
!                  PTYPE = PTYPE!X'400';  ! FORCE NAM=1 (IE VIA POINTER)
                  FCOPND_D = 0
                  TAGDISP = PINITOWN(PTYPE,ACC,FCOPND,NAMTXT)
                  STORE TAG(K,LEVEL,0,J,SNDISP,ACC,TAGDISP,KFORM)
                  P = MARK
                  continue
               finish
               if TYPE=3 then start;     ! RECORDS
                  TAGDISP = PINITOWN(PTYPE,ACC,FCOPND,NAMTXT)
               finish
               if 1<<TYPE&B'100110'#0 start;    ! INTEGER & REAL & STRING
                  if EXTRN#0 then start
                     TAGDISP = PINITOWN(PTYPE,ACC,FCOPND,NAMTXT)
                  finish else TAGDISP = 0
               finish
               STORE TAG(K,LEVEL,0,J,SNDISP,ACC,TAGDISP,KFORM)
               if EXTRN=0=NAM and 1<<TYPE&B'100110'#0 start
                                         ! CONST = LITERAL
                  LCELL == ASLIST(TAGS(K))
                  lcell_s1=lcell_S1!(copnd_ptype&8)<<16
                  LCELL_S2 = COPND_D
                  LCELL_S3 = COPND_XTRA
                  if TYPE=5 then start
                     LCELL_S2 = WORKA_ARTOP
                     WORKA_ARTOP = (WORKA_ARTOP+COPND_XTRA+4)&(-4)
                  finish
               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(ADDR(WORKA_LETT(WORD(K))))
            if A(P)=1 then start;        ! ALAIS GIVEN
               if LITL=0 then WARN(10,0)
               LENGTH(NAMTXT) = A(P+1)
               CHARNO(NAMTXT,KK) = A(P+KK+1) for KK = 1,1,A(P+1)
               P = P+A(P+1)+1
            finish
            P = P+1;                     ! P ON CONSTLIST
            SACC = ACC; TYPEP = PTYPE; savekform=kform
            DVO = DOPE VECTOR(NO,TYPE,STALLOC,0,K)
            if SNDISP=-1 then SNDISP = 0;    ! BUM DOPE VECTOR
            SNDISP = (SNDISP&X'3FFFF')>>2;  ! AS WORD DISPLACEMENT
            savesndisp=sndisp           { Not proof against C-T concatenation !}
            DIMEN = J;                   ! SAVE NO OF DIMENESIONS
            ACC = SACC; PTYPE = TYPEP; UNPACK
            PP=p
begin
            shortinteger savedp, savedp2, savedptype
            integer i;
            integer count; count = 0
!GT: This is where arrays are declared.  We want to adjust the base of
!    each array if the lower bound is non-0 so that accesses to the array
!    can use the natural bounds (which in Imp are not forced to start at 0)

! Ideally we would allow static declarations to remain static declarations,
! but this does not work for multi-dimensional arrays so these too will
! come off the heap for now

! Also dynamic arrays simply are not converted correctly at the moment, so
! this code takes care of that too.

! We must plant code at the end of each procedure to free the heap arrays
! Note if we use a mark/release scheme this can be very cheap.

! Remember to initialise if members given, and to initialise to zero otherwise
! (can be done in the allocate heap space procedure)

            if format=0 start
               savedptype = ptype&255
               outextern(EXTRN)
               outtype(savedptype,savekform)
               for ii=dimen,-1,1 cycle
                 outsym('*') for i = 1,1,ii
                 outname(k);
                 outsym('_') and outint(ii) if ii#dimen
                 outsym(',') if ii#1
               repeat
               outsym(';'); outsym(NL)

               outextern(EXTRN)
               outstring("int ");
               for ii=dimen,-1,1 cycle
                 outname(k);
                 outstring("_dim_")
                 outint(ii)
                 outsym(',') if ii#1
               repeat
               outsym(';'); outsym(NL)

               for ii=dimen,-1,1 cycle
                  outname(k);
                  outsym('_') and outint(ii) if ii#dimen
                  p=ctable(savesndisp+3*ii+2)
                  savedp = p
                  outstring(" = (")
                  outtype(savedptype,savekform)
                  outsym('*') for i = 1,1,ii
                  outstring(")malloc(((")
                  csexp(x'51'); outsym(')')
                  if ctable(savesndisp+3*ii)=x'80000000'start
                     outsym('-'); p=ctable(savesndisp+3*ii+1)
                     outsym('('); csexp(x'51'); outstring(")+1")
                  finish else if ctable(savesndisp+3*ii)<1 start
                     outsym('+'); outint(1-ctable(savesndisp+3*ii))
                  finish else if ctable(savesndisp+3*ii)>1 start
                     outsym('-'); outint(ctable(savesndisp+3*ii)-1)
                  finish
                  outstring(") * sizeof(");
                  outtype(savedptype,savekform)
                  outsym('*') for i = 1,1,ii-1
                  outstring(") );"); outsym(NL);

                  if ctable(savesndisp+3*ii)=x'80000000'start
                     outname(k);
                     outsym('_') and outint(ii) if ii#dimen
                     outstring(" -= ");
                     p=ctable(savesndisp+3*ii+1)
                     csexp(x'51')
                  finish else if ctable(savesndisp+3*ii)#0 start
                     outname(k);
                     outsym('_') and outint(ii) if ii#dimen
                     outstring(" -= ");
                     outint(ctable(savesndisp+3*ii))
                  finish;  ! otherwise based at 0 already

                  outsym(';'); outsym(NL);

                  outstring("for ("); outname(k)
                  outstring("_dim_"); outint(ii);
                  outstring(" = ")

                  if ctable(savesndisp+3*ii)=x'80000000'start
                     p=ctable(savesndisp+3*ii+1)
                     csexp(x'51')
                  finish else if ctable(savesndisp+3*ii)#0 start
                     outint(ctable(savesndisp+3*ii))
                  finish else outint(0);

                  outstring("; "); outname(k)
                  outstring("_dim_"); outint(ii);
                  outstring(" <= ")

                  csexp(x'51')
                  outstring("; "); outname(k)
                  outstring("_dim_"); outint(ii);
                  outstring("++) {"); outsym(NL);
               repeat
               for ii=1,1,dimen cycle
                 if ii#1 then start
                   outname(k);outsym('_') and outint(ii) if ii#dimen
                   outstring("["); outname(k)
                   outstring("_dim_"); outint(ii);
                   outstring("] = "); outname(k)
                   outsym('_'); outint(ii-1)
                   outstring(";"); outsym(NL)
                 finish else start
                   outstring("/* Assign initialised elements if any */"); outsym(NL)
                 finish
                 outsym('}'); outsym(NL)
               repeat

            outsym('{'); outsym(NL); ! for static decl after code!
            outextern(EXTRN)
            outtype(savedptype,savekform)
            outname(k); outstring("_data[] ")


            finish


            PTYPE = TYPEP; UNPACK
            if LB=0 and FORMAT=0 then ARR = 2 and PACK(PTYPE)
            if TYPE=3 then SLENGTH = QQ else SLENGTH = QQ//STALLOC
                                         ! NO OF ELEMENTS
            cas(qputp)=(cas(qputp)+arrayrounding)&(¬arrayrounding)
            SPOINT = cas(qputp)

            if FORMAT=0 then start
               if A(PP)=1 then start
                 P = PP+1
                 count = INIT SPACE(QQ,SLENGTH)
               finish
            finish
            outsep  if format=0

            if EXTRN=3 then SPOINT = 0
!
! OUTPUT AN ARRAYHEAD INTO THE GLA RELATIVE TO THE START OF THE SYMBOL-
! TABLES IN WHICH THE ARRAY RESIDES.
!
            PTYPE = TYPEP; UNPACK
            if Format#0 then qputp=0     { avoid data fixup in pownarrayhead}
            TAGDISP = POWNARRAYHEAD(PTYPE,dimen,LB,QQ,SPOINT,QPUTP,DVO,NAMTXT)
            SNDISP=savesndisp
            STORE TAG(K,LEVEL,0,dimen,SNDISP,ACC,TAGDISP,saveKFORM)

            /* if no init declarations, don't do this... */
            outsym(NL);
            outstring("int "); outname(k); outstring("_inels = 0;"); outsym(NL);

            ACC = SACC; PTYPE = TYPEP; UNPACK
            PP=p

            %for ii=dimen,-1,1 %cycle
                  p=ctable(savesndisp+3*ii+2)
                  outstring("for ("); outname(k)
                  outstring("_dim_"); outint(ii);
                  outstring(" = ")

                  savedp = p;

!                  outstring(" /* 1:")
!                  csexp(x'51')
!                  outstring(" */ ")


                  %if ctable(savesndisp+3*ii)=x'80000000'%start
                     p=ctable(savesndisp+3*ii+1)
                     csexp(x'51')
                  %finish %else %if ctable(savesndisp+3*ii)#0 %start
                     outint(ctable(savesndisp+3*ii))
                  %finish %else outint(0);

                  outstring("; "); outname(k)
                  outstring("_dim_"); outint(ii);
                  outstring(" <= ")
                  p = savedp;
                  csexp(x'51')
                  outstring("; "); outname(k)
                  outstring("_dim_"); outint(ii);

                  outstring("++) {"); outsym(NL);

                  outstring("if (")
                  outname(k)
                  outstring("_inels == "); outint(count); outstring(") break;");outsym(NL)


                  %if ctable(savesndisp+3*ii)=x'80000000'%start
                     p=ctable(savesndisp+3*ii+1)
!                     outstring(" /* 2:")
!                     csexp(x'51')
!                     outstring(" */ ")
                  %finish
            %repeat

            outname(k)
            %for ii=dimen,-1,1 %cycle
              outstring("["); outname(k); outstring("_dim_")
              outint(ii)
              outstring("]")
            %repeat
            outstring(" = ")
            outname(k)
            outstring("_data[")
            outname(k)
            outstring("_inels++];"); outsym(NL)
            %for ii=dimen,-1,1 %cycle
                  outstring("}"); outsym(NL);
            %repeat
            outsym('}'); outsym(NL); ! End of static init 

%end; ! of tweak to make arrays based at non-0

            ->BEND
%integerfn 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                                       *
!***********************************************************************
%const %integer BUFSIZE=512
%integer RF,I,II,ELSIZE,AD,SPP,SLENGTH,WRIT,PIN,PP,contype,conprec,ppp,value
%integer nels out
      nels out = 0
      pIN=p; contype=type
      conprec=prec
 outstring(" = {")
      SPP = 0; WRIT = 0
      %until A(P-1)=2 %cycle
         p=p-3; PP=p; skip exp
         %if A(P)=1 %start;     ! REPITITION FACTOR
            P = P+2
            %if A(P-1)=2 %then %start     { * found issue warning }
               RF = 1                     { Except for 0(*) when detectable }
               %unless a(PP+3)=4 %and a(PP+4)=2 %and a(PP+5)=x'41' %andc
                  a(PP+6)=a(PP+7)=0 %and a(PP+8)=2 %then warn(10,0)
            %finish %else %start
               P = P+2
               %if INTEXP(RF,MINAPT)#0 %then warn(10,0) %and RF = 1
            %finish
            P = P+1
         %finish %else RF = 1 %and P = P+2
         nels out = nels out + RF
         warn(10,0) %if RF<=0
          spp=p
         %cycle I = RF,-1,1
            p=pp
            %if contype=5 %then cstrexp(1) %else csexp(conprec<<4!contype)
            consts found=consts found+1
            outsym(',') %unless i=1 %and a(spp-1)=2  { very last const}
         %if (contype=5 %and consts found&3=0) %or consts found&7=0 %c
              %then outsym(NL)
         %repeat
         p=spp
      %repeat
      outstring("}")
      %result = nels out
%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 SLENGTH,STYPE,SACC,MODE,CH,WR,I,PP
               STYPE = PTYPE; SACC = ACC;  ! MAY BE CHANGED IF CONST IS EXPR
               %if CONTYPE=5 %then %start
                  P = P-3; CSTREXP(1)
                  WR = WORKA_ARTOP
                  %if EXPOPND_FLAG=LCONST %and EXPOPND_PTYPE=X'35' %start
                     SLENGTH = EXPOPND_XTRA
                     LENGTH(SCONST) = SLENGTH
                     A(WR) = SLENGTH
                     %for I = 1,1,SLENGTH %cycle
                        CH = A(EXPOPND_D+I)
                        CHARNO(SCONST,I) = CH
                        A(WR+I) = CH
                     %repeat
                     COPND_PTYPE = X'35'; COPND_FLAG = LCONST
                     COPND_D = EXPOPND_D
                     COPND_XTRA = SLENGTH
                  %finish %else %start
                     FAULT(44,CONSTS FOUND,K); SCONST = ""
                     SLENGTH = 0
                  %finish
               %finish %else %start
                  MODE = CONPREC<<4!CONTYPE
                  %if CONPREC<5 %then MODE = CONTYPE!X'50'
                  PP=P; p=p-3; csexp(mode)
                  p=pp; I = CONSTEXP(MODE)   { Evaluate again to get storeable value }
!                  %if CONSTP=0 %then FAULT(41,0,0)
                                         ! CANT EVALUATE EXPT
                  COPND = EXPOPND;       ! GET RESULT OPND
                  COPND_PTYPE = MODE
               %finish
               PTYPE = STYPE; UNPACK; ACC = SACC

               FCOPND = COPND
            %end
BEND:    %end; ->CSSEXIT2
SW(10):
      %begin;                         ! %recordformat (RDECLN)
      %integer NAME,OPHEAD,OPBOT,NLIST,HeadCell,FHEAD,SPEC,l1,l2,strid,fpt
      %record (LISTF) %name LCELL,FRCELL
       %string(255) typename
      SNDISP = 0
      SPEC = A(P+1);               ! 1 FOR SPEC 2 FOR FORMAT
      NAME = FROM AR2(P+2); P = P+4
      COPY TAG(NAME,NO)
      %if SPEC=1 %or %not (PTYPE=4 %and J=15 %and OLDI=LEVEL) %start
         KFORM = 0
         PUSH(KFORM,0,0,0)
         PTYPE = 4
         STORE TAG(NAME,LEVEL,RBASE,15,0,MAXRECSIZE,KFORM,KFORM)
                                   ! IN CASE OF REFS IN FORMAT
      %finish
      %if SPEC=2 %start
         ophead=0; opbot=0; nlist=0
         %for l1=0,1,12 %cycle
           %for l2=0,1,12 %cycle
              rfhead(l1,l2)=0
              rfbot(l1,l2)=0
           %repeat
           rfalt(l1)=0
          %repeat
         INAFORMAT = 1
         rflevel=0
         crformat(rflevel)
         INAFORMAT = 0
         %if PARM_Z#0 %start
            %for l1=0,1,12 %cycle
              %for l2=0,1,12 %cycle
                  %if rfhead(l1,l2)#0 %start
                      printstring("level&rfalt="); write(l1,5); write(l2,5); newline
                      printlist(rfhead(l1,l2))
                  %finish
               %repeat
            %repeat
         %finish
         strid=0;                 { for generating internal names }
        HeadCell=rfhead(0,1)
         %if HeadCell=0 %start      { No alternatives at top level }
            outstring("struct "); outname(name)
            outsym('{'); outsym(NL)
            process format(0,0,'s',0,strid,ophead,opbot)
            fpt=4
         else
            outstring("union "); outname(name)
            outsym('{'); outsym(NL)
            process format(0,0,'u',0,strid,ophead,opbot)
            fpt=x'14'
         finish
         outsym('}'); outsym(';'); outsym(NL)
         if PARM_Z#0 start
            printstring("after processing")
            printlist(ophead)
         finish
         if possible typename(name,typename)#0 start
            outsym(NL)
            outstring("typedef ")
            if HeadCell=0 start      { No alternatives at top level }
               outstring("struct ")
            else
               outstring("union ")
            finish
            outname(name)
            outstring(" ".typename.";")
            outsym(NL)
         finish
         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
           LCELL == ASLIST(TAGS(NAME))
         KFORM = LCELL_KFORM
         if PARM_Z#0 start
                printstring("before throwing dummy cell")
                printlist(kform)
         finish
         POP(KFORM,I,I,FHEAD);     ! THROW DUMMY CELL
                                   ! GET HEAD OF FORWARD REFS
         fhead=ophead
         while FHEAD>0 cycle;      ! THROUGH format changeFORWARD REFS
            FRCELL == ASLIST(fhead)
            if frcell_ptype=x'433' and frcell_kform=lcell_kform start
               FRCELL_UIOJ = FRCELL_UIOJ&X'FFFFFFF0';  ! SET J BACK TO 0
               FRCELL_ACC <- ACC;     ! ACC TO CORRECT VALUE
               FRCELL_KFORM = OPHEAD;  ! CORRECT KFORM
            finish
            fhead=frcell_link
         repeat
         LCELL_UIOJ = LCELL_UIOJ&X'FFFFFFF0';  ! J BACK TO ZERO
         LCELL_ACC <- ACC
         LCELL_SLINK = name;     ! KFORM&SLINK TO SIDECHAIN & name
         LCELL_PTYPE=fpt        { To distinguish unions from structs }
         LCELL_KFORM = OPHEAD
         if PARM_Z#0 start
            printstring("after processing self refs")
            printlist(ophead)
         finish
      finish
end; ->CSSEXIT2
!
SW(19):
                                         ! '*' (UCI) (S)
!         FAULT(57,0,0) %unless LEVEL>=2
        outstring("***Untranslateable stmnt***")
         i=curlinead
         while i<nextlinead cycle
            outsym(byteinteger(i))
            i=i+1
         repeat
         ->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(ADDR(WORKA_LETT(WORD(KK))))
         ->CSSEXIT
         integer fn 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,NO)
               if 3<=TYPE<=4 then result = KFORM
               if INAFORMAT#0 and OLDI#LEVEL start
                  PTYPE = 4; ACC = MAXRECSIZE
                  PUSH(KFORM,0,0,0)
                  STORE TAG(FNAM,LEVEL,RBASE,15,0,MAXRECSIZE,KFORM,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
              outstring("*** imp construction too difficult***")
            result = OPHEAD
         end

         routine CRFORMAT(integer myrflevel)
!***********************************************************************
!*       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,DVO
            routine spec SN(integer Q)
            routine spec ROUND
            FORM = 0; ACC = 0
            INC = 0;          ! 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
                  P = P+1
                  if A(P-1)=1 start
                                         ! (TYPE) (QNAME')(NAMELIST)
                     FORM = KFORM
                     CQN(P); P = P+1
                     PACK(PTYPE); D2 = 0
                     RL = ROUNDING LENGTH(PTYPE,0)
                     if NAM=1 then start
                        STALLOC = PTRSIZE(PREC<<4!TYPE)
                         RL=PTRrounding(ptype&127)
                        if ARR#0 then STALLOC = AHEADSIZE and RL=ROUNDINGLENGTH(AHEADPT,0)
                     finish
                     fault(70,0,0) if type=5 and stalloc=0
                     ROUND; J = 0
                     until A(P-1)=2 cycle
                        D1 = 0; 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
                        D2=dope vector(NO,typep&7,acc,0,fromar2(q))>>2
                                         ! DOPE VECTOR INTO SHAREABLE S.T.
                        ACC = SACC; PTYPE = TYPEP; UNPACK
                        RL = ROUNDING LENGTH(PTYPE&255,0);  ! FOR ELEMENT AS%c
                                                            SCALAR
                        if RL<ARRAYINREC ROUNDING then c
                           RL = ARRAYINREC ROUNDING
                        cycle
                           ROUND
                           D1 = 0
                           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)
                  rflevel=rflevel+1
                  binsert(rfhead(myrflevel,rfalt(myrflevel)),rfbot(myrflevel,rfalt(myrflevel)),
                    0,rflevel,0)
                  CRFORMAT(rflevel)
                  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
                  rfalt(myrflevel)=rfalt(myrflevel)+1
               CRFORMAT(myrflevel)
               if ACC>INC then INC = ACC
            finish else P = P+1
            ACC = INC;                   ! SIZE ROUNDED APPROPRIATELY
            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.              *
!*       CARE IS NEEDED TO MATCH TAG LAYOUT ON BYTE SWOPPED HOSTS      *
!***********************************************************************
               record (TAGF) CELL
               FNAME = FROM AR2(Q)
               if aslist(tags(fname))_ptype=x'4051' then warn(11,0)
               CELL_PTYPE <- PTYPE; CELL_UIOJ <- FNAME<<4!J
               CELL_ACC <- ACC
               CELL_SNDISP <- D2&X'FFFF';  ! IN CASE OF BUM FORMATS
               CELL_SLINK <- D1&X'FFFF';  ! IN CASE OF BUM FORMATS
               CELL_KFORM = FORM
               BINSERT(rfhead(myrflevel,rfalt(myrflevel)),rfbot(myrflevel,rfalt(myrflevel)),
                  CELL_S1,CELL_S2,CELL_S3)
!               %if PTYPE=X'433' %and ACC=MAXRECSIZE %then %c
                  PUSH(ASLIST(FORM)_S3,OPBOT,0,0)
! NOTE FORWARD REFERENCE
            end
            routine ROUND
            end
         end;                            ! OF ROUTINE CRFORMAT
routine out fmt cell(record(listf)name lcell)
!***********************************************************************
!* print out a single cell of a format list                            *
!***********************************************************************
integer pt,name,dvdisp,nd,ii
record(listf)name fcell
      pt=lcell_s1>>16
      name=lcell_S1>>4&X'FFF'
      if pt&x'cff'=x'35' start
         outstring("char "); outname(name)
      else
         OUT XTYPE(PT&x'cff',lcell_kform)
         outname(name)
      finish
      if PT&x'300'#0 start
         nd=lcell_s1&15
         dvdisp=lcell_sndisp
            for ii=nd,-1,1 cycle
               p=ctable(dvdisp+3*ii+2)
               outstring(" [")
               csexp(x'51')
               if ctable(dvdisp+3*ii)=x'80000000'start
                  outsym('-'); p=ctable(dvdisp+3*ii+1)
                  outsym('('); csexp(x'51'); outstring(")+1")
               finish else if ctable(dvdisp+3*ii)<1 start
                  outsym('+'); outint(1-ctable(dvdisp+3*ii))
               finish else if ctable(dvdisp+3*ii)>1 start
                  outsym('-'); outint(ctable(dvdisp+3*ii)-1)
               finish
               outsym(']')
            repeat
      finish
      if pt&x'cff'=x'35' start
         outsym('['); outint(lcell_acc); outsym(']')
      finish
      outsep
      outsym(NL)
end
routine process format(integer level,alt,structor union,intid,
      integername strid,ophead,opbot)
!***********************************************************************
!* process one level of the recordformay data structure and call       &
!* itself recursively to handle lower levels. Note C unions cal        &
!* can have only one element in each alternative so imp multi-         &
!* element alternatives have to be coalesced into structures           &
!* this is the main problem                                            &
!***********************************************************************
record (listf)lcell
integer i,j,k,newid,lstrid

      if structorunion='s' start   { struct only 1 alt }
         while rfhead(level,alt)#0 cycle
            pop(rfhead(level,alt),lcell_s1,lcell_s2,lcell_s3)
            if lcell_s1#0 start
               out fmt cell(lcell)
               lcell_slink=intid
               binsert(ophead,opbot,lcell_s1,lcell_s2,lcell_s3)
            else                   { union within struct }
               newid=intid<<4!(lcell_s2{-1}{ union update })
               outstring("union {"); outsym(NL)
               process format(lcell_s2,0,'u',newid,strid,ophead,opbot)
               outstring("} u"); outint(lcell_s2-1)
               outsym(';'); outsym(NL)
            finish
         repeat
      else                          { union with at least 2 alternatives }
         for i=alt,1,rfalt(level) cycle
            if rfhead(level,i)=rfbot(level,i) start   { only 1 alt }
               pop(rfhead(level,i),lcell_s1,lcell_s2,lcell_s3)
               if lcell_s1#0 start
                  out fmt cell(lcell)
                  lcell_slink=intid
                  binsert(ophead,opbot,lcell_s1,lcell_s2,lcell_s3)
               else                   { union within union }
                  newid=intid<<4!(lcell_s2{-1}{ union update })
                  outstring("union {"); outsym(NL)
                  process format(lcell_s2,0,'u',newid,strid,ophead,opbot)
                  outstring("} u"); outint(lcell_s2-1)
                  outsym(';'); outsym(NL)
               finish
            else                 { force in a struct }
               lstrid=strid; strid=strid+1
               newid=intid<<4!8!lstrid
               outstring("struct {"); outsym(NL)
               process format(level,i,'s',newid,strid,ophead,opbot)
               outstring("} s"); outint(lstrid)
               outsym(';'); outsym(NL)
            finish
        repeat
      finish
end

         integer fn 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
            record (TAGF) TOPND
            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_UIOJ<<16>>20=ENAME start;    ! RIGHT SUBNAME LOCATED
                     TCELL = LINK
                     SNDISP = LCELL_SNDISP
                     K = LCELL_SLINK
                     J = LCELL_UIOJ&15; PTYPE = LCELL_PTYPE
                     ACC = LCELL_ACC&X'FFFF'
                     SNDISP = LCELL_SNDISP
                     KFORM = LCELL_KFORM
                     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 start
               TOPND_PTYPE = x'51'
               TOPND_UIOJ <- ENAME<<4
               PUSH(ASLIST(CELL)_LINK,TOPND_S1,0,0)
            finish
            PTYPE = X'51'; TCELL = 0; unpack
            result = -1
         end
         integer fn COPY RECORD TAG(integer name 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
integerfn chk rec align(integer p1)
!***********************************************************************
!*      Tiddles down chain looking for an integer or larger            *
!*      returns 0 unless at least word aligned                         *
!***********************************************************************
integer cell,i
integerfnspec scan(integer cell)
      p=p1; reduce tag(no);    ! leaves kform set for records
      cell=kform
!        printstring("chk align ".printname(a(p1)<<8!a(p1+1)))
!        write(kform,5); newline
!           printlist(cell)
      result=scan(cell)
integerfn scan(integer cell)
integer j
      while cell #0 cycle
         i=aslist(cell)_ptype>>4&7
         if i>=5 then result=i
         if aslist(cell)_ptype=x'33' then start
            i=scan(aslist(cell)_kform)
          if i>=5 then result=i
         finish
         cell=aslist(cell)_link
      repeat
      result=0
end
end { chk rec align }
         routine CRNAME(integer Z,MODE,BS,DP, integer name 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,EMNAME
            routine spec CENAME(integer MODE,FNAME,BS,DP,XD)
            record (RD) HDOPND
            HDOPND = 0
            DEPTH = 0
            EMNAME = NAMEP&X'FFFF';      ! ORIGINAL RECORD NAME FOR ERROR%c
                                         MESSES
            FNAME = KFORM;               ! POINTER TO FORMAT
            if ARR=0 or (6<=z<=7 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
               HDOPND_PTYPE = AHEADPT
               HDOPND_FLAG = LOCALIR
               HDOPND_D = BS<<16!DP
               CANAME(Z,ARR,HDOPND)
               NAMEP = -1
               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                                 *
!***********************************************************************
routine spec FETCH RAD
integer Q,QQ,D,C,TR,ENAME,RPTYPE,EPTYPE
record (RD) RADOPND,OPND1
record (LISTF) name LCELL
               DEPTH = DEPTH+1
              RPTYPE=PTYPE
               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 or Z=7 start;      ! ADDR(RECORD)
                        FAULT(64,0,EMNAME); 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
              EPTYPE=PTYPE;                ! Save ptype of ename
               UNPACK;                   ! INFO ABOUT THE SUBNAME
!               %if Q=-1=ACC %or PTYPE=X'51' %start;  ! WRONG SUBNAME(HAS BEEN%c
!                                                     FAULTED)
!                  P = P+2; SKIP APP; P = P-3
!                  ACCESS = 0; BASE = RBASE; DISP = 0
!                  %return
!               %finish
               ENAME = A(P)<<8!A(P+1)
               NAMEP = ENAME<<16!NAMEP;  ! NAMEP=-1 UNALTERED !
               if rptype&x'f00'=x'400' then outstring("->") else outstring(".")
               outinternames(q)
               outname(ename)
               ->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 (TYPE=3 and A(P)=2 and c
                  (3<=Z<=4 or 6<=z<=7)) 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 = NAMEP!X'FFFF0000'
               if NAM=1 then start
                  MODE = MODE+4;         ! SO ADDRESS OF POINTER FETCHED
                  FETCH RAD;             ! NEW METHOD IS AS FOR REC FNS
                  EXPOPND = RADOPND;     ! EXPOPND IS ADDRESS TO WHICH POINTER%c
                                         POINTED
                  MODE = 3
                  DP = 0; XD = 0; BS = 0
                  NAMEP = -1
               finish
               CENAME(MODE,KFORM,BS,DP,XD)
               return
AE:                                      ! ARRAYS AND ARRAYNAMES AS ELEMEN
               LCELL == ASLIST(TCELL)
               ACC = LCELL_ACC&X'FFFF'; SNDISP = LCELL_SNDISP&X'FFFF'
               KFORM = LCELL_KFORM; K = LCELL_SLINK&x'ffff'
               C = ACC; D = SNDISP; Q = K; QQ = KFORM
               if (Z=6 or Z>=11) and A(P+2)=2 start;      ! 'GET ARRAYHEAD'%c
                                                          CALL
                  P = P+3
                  if NAM=1 then start
                     ACCESS = MODE+8; BASE = BS
                     DISP = DP; XDISP = XD+Q
                     PTYPE = AHEADPT
                     NAMEOP(6,8,NAMEP);  ! PTR TO HEAD
                     return
                  finish
!
! PASSING AN ARRAY IN A RECORD BY NAME MUST CONSTRUCT PROPER ARRAYHEAD
! FROM THE RECORD RELATIVE ONE AT Q(GLA)
!
                  FETCH RAD
                  NAMEP = -1
                  OPND1 = 0
                  OPND1_PTYPE = AHEADPT
                  OPND1_FLAG = LOCALIR
                  OPND1_D = Q
                  NAMEOPND_D = CREATE AH(1,RADOPND,OPND1)
                  NAMEOPND_PTYPE = AHEADPT; NAMEOPND_FLAG = REFTRIP
                  NAMEOPND_XTRA = 0
               finish else start;        ! ARRAY ELEMENTS IN RECORDS
                  if NAM=1 then start;     ! ARRAYNAMES-FULLHEAD IN RECORD
                     XD = XD+Q
                     ACCESS = MODE+8
                     BASE = BS; DISP = DP; XDISP = XD
                     NAMEOP(6,AHEADSIZE,NAMEP)
                     OPND1 = NAMEOPND
                     OPND1_PTYPE = AHEADPT
                     PTYPE = LCELL_PTYPE; UNPACK
                     CANAME(Z,3,OPND1);  ! ARRAY MODE SETS DISP,AREA&BASE
                     XD = 0
                  finish else start;     ! ARRAY RELATIVE HEAD IN GLA
                     FETCH RAD;          ! 32 BIT ADDR TO ETOS
                     OPND1 = 0; OPND1_PTYPE = AHEADPT
                     OPND1_FLAG = LOCALIR
                     OPND1_D = Q
                     CANAME(Z,3,OPND1);  ! RECORD REL ARRAY ACCESS
                                         ! CAN RETURN ACCESS=1 OR 3 ONLY
                      TR =0
!                     TR = BRECTRIP(AAINC,X'51',0,RADOPND,EXPOPND)
                     EXPOPND_FLAG = REFTRIP
                     EXPOPND_D = TR
!                     TRIPLES(TR)_X1 = PTYPE&255;  ! FRIG FOR PERQ&ACCENT 3%c
                                                  WORD BYTE PTRS!
                     XD = 0
                  finish
                  NAMEP = -1
                  XDISP = XD
                  if TYPE=3 thenstart
                     CENAME(ACCESS,QQ,BASE,DISP,XD)
                     c=acc;         ! to return element size
                  else
                        if Z>=11 then FAULT(17,0,ENAME)
                  finish
                                         ! AN ELEMENT IS NOT AN ARRAY FOR P-P
               finish
               ACC = C;                  ! NEEDED FOR STRING ARRAYS
               return
routine FETCH RAD
!***********************************************************************
!*       SET ACC TO 32 BIT ADDRESS OF RECORD.                          *
!***********************************************************************
                  ACCESS = MODE+4
                  BASE = BS
                  DISP = DP; XDISP = XD
               ptype=rptype; unpack
                  NAMEOP(4,4,NAMEP)
                 ptype=eptype; unpack
                  RADOPND = NAMEOPND
               end
            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,Firsttrip,trip
            record (RD) OPND1,OPND2,OPND3
            integer fn spec STROP(record (RD) name OPND)
            KEEPWA = MODE&16; MODE = MODE&15
            OPND1 = 0
            OPND1_PTYPE = X'35'
            OPND1_FLAG = LOCALIR
            OPND1_XTRA = 268;            ! THE WORK AREA SIZE NEEDED FOR
            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
            if STRRESINWA=NO and PTYPE&X'1000'#0 then MODE = 1
                                         ! IF FN RESULT NOT IN A WORK AREA
                                         ! COPY IN FROM TOP OF STACK
                                         ! SOMETIMES NOT NECESSARY BUT FN=FN%c
                                         COMPARISONS
                                         ! WILL GO WRONG WITHOUT THIS
            ->ERROR unless ERR=0
NEXT:       if A(P)=2 then ENDFLAG = 1 else start
               if A(P+1)#CONCOP then ERR = 72 and ->ERROR
               P = P+2
!
! LEFT TO RIGHT EVALUATION IS DEFINED BUT IF FIRST OPERAND IS ACONST
! WE CAN EVALUATE THE SECOND. THIS ENABLES US TO FOLD "TOSTRING(NL)" ETC
!
               if DOTS=0 and OPND2_FLAG=LCONST then start
                  ERR = STROP(OPND3)
                  ->ERROR unless ERR=0
               finish else OPND3_FLAG = 255
            finish
            if ENDFLAG=0 and OPND2_FLAG=LCONST=OPND3_FLAG  and mode=1 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  ENDFLAG#0 start;    ! NO RUN-TIME OPERATIONS
                  outopnd(opnd2,0)
                  OPND1 = OPND2; ->TIDY
               finish
               Firsttrip = BRECTRIP(PRECC,X'35',0,OPND1,OPND2)
               OPND1_FLAG = REFTRIP
               OPND1_D = Firsttrip;              ! CHANGE TO TRIPLES REFERENCE
               DOTS = DOTS + 1
            finish
            if ENDFLAG=0 then start
               if OPND3_FLAG=255 start;    ! 3 NEED EVALUATION
                  ERR = STROP(OPND3)
                  ->ERROR unless ERR=0
               finish
               OPND1_D = BRECTRIP(CONCAT,X'35',0,OPND1,OPND3)
               dots = dots +1; ->NEXT
            finish
!          printtrips(triples)
            outstring("imp_concat(") for i=2,1,DOTS
            trip=Firsttrip
            while trip #0 cycle
               outopnd(Triples(trip)_opnd2,0)
               if trip=Firsttrip then outstring(",") else start
                  outstring(")")
                  outsym(',') unless Triples(trip)_puse=0
               finish
               trip=Triples(trip)_puse
            repeat
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)
            EXPOPND = OPND1
            BASE = RBASE; DISP = 0
            VALUE = 0; ACCESS = 0
            P = PP; SKIP EXP
            return
            integer fn STROP(record (RD) name OPND)
!***********************************************************************
!*       DEALS WITH OPERAND FOR CONCATENATION. RETURN RESULT=0 FOR     *
!*       VALID OPERAND OTHERWISE AN ERROR NUMBER.                      *
!***********************************************************************
               integer CTYPE,alt,I
               alt  = A(P);              ! ALTERNATIVE OF OPERAND
               OPND = 0
               result = 75 if alt >2
               if alt #1 then start
                  CTYPE = A(P+1);        ! GET CONST TYPE & LOSE AMCK FLAGS
                  if CTYPE=X'35' then start
                     PTYPE = CTYPE
                     STRINGL = A(P+2)
                     OPND_PTYPE = CTYPE
                     OPND_FLAG = LCONST
                     OPND_D = P+2
                     OPND_XTRA = STRINGL
                     P = P+STRINGL+3
                  finish else result = 73
               finish else start
                  P = P+1;               ! MUST CHECK FIRST
                  COPYTAG(FROMAR2(P),NO)
                  if PTYPE=x'1006' then TYPE = ACC&7;    ! special for "string"
                  if TYPE=3 then REDUCE TAG(NO)
                  if 5#TYPE#7 then FNAM = FROMAR2(P) and result = 71
                  if ptype=x'4035' and A(P+2)=2=A(P+3) and mode#0 start
                      opnd_flag=lconst; opnd_ptype=x'35'
                      opnd_d=midcell; opnd_xtra=kform
                      stringl=opnd_xtra
                      p=p+4
                      result=0
                  finish
                  if PTYPE=X'35' and A(P+2)=2=A(P+3) start
                     OPND_FLAG = DNAME
                     OPND_XTRA = 0
                     OPND_PTYPE <- PTYPE
                     OPND_D = FROMAR2(P)
                     P = P+4
                  finish else start
                     OPND_FLAG = ARNAME
                     OPND_D = P
                     p=p+2; skip app
                     while a(p)=1 cycle
                        p=p+3; skip app;
                     repeat
                     p=p+1
                  finish
                  STRINGL = 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,JJ
record (RD) OPND1,OPND2
      LAST = 0; FNAM = 0;          ! =1 WHEN END OF EXPRNSN FOUND
      SEXPRN = 0;                  ! RESOLUTION(BRKTD) EXPRESSNS
      P1 = P
      ERR = 43
      if NAMEOPND_PTYPE&X'C700'=X'4000' then c
         FNAM = NAMEOPND_D and ->ERROR
                                   !  CANT RESOLVE A CONST STRING
      ERR = 74;                    ! NORMAL CRES FAULT
      GET WSP(W,4);                ! TO HOLD P1,P2 AND VALUE OF P3
      OPND1_PTYPE = X'61'
      OPND1_FLAG = LOCALIR
      OPND1_D = RBASE<<16!W
      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)
      if A(P)=3 then start;        ! B OMITTED
         OPND2_PTYPE = X'51'
         OPND2_FLAG = SCONST
         OPND2_D = 0;              ! ZERO CONST FOR NO DEST
         outstring("NULL,")
      finish else start
         ->ERROR unless A(P)=1;    ! P(OPERAND)=NAME
         P = P+1; P2 = P
         CNAME(2)
         outsym(',')
         OPND2 = NAMEOPND
         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
      ->ERROR unless A(P)=3;       ! P(OPERAND)='('(EXPR)')'
      SEXPRN = SEXPRN+1; P = P+1
      CSTREXP(0);                 ! FULL 32 BIT ADDRESS
      outsym(',')
      OPND2_PTYPE = X'51'; OPND2_FLAG = SCONST
      OPND2_D = LAB
      if A(P)=2 then outstring("NULL") and ->END
      if A(P+1)#CONCOP then ERR = 72 and ->ERROR
      P2 = P+1; P = P2+1
      if A(P)=3 then start
        P = P2
         outstring("_imptempstring)")
         if lab=0 then outsym(';') else outsym('+')
         outstring("imp_resolve(_imptempstring,")
         ->RES
      finish
      ->ERROR unless A(P)=1
      P = P+3 and SKIP APP until A(P)=2
      if A(P+1)=1 then start
        P = P2
         outstring("_imptempstring)")
         if lab=0 then outsym(';') else outsym('+')
         outstring("imp_resolve(_imptempstring,")
         ->RES
      finish
      P1 = P+1
      P = P2+2
      CNAME(2)
      P = P1
END:
      P = P+1
end
         routine SAVE STACK PTR
!***********************************************************************
!*    SAVE THE CURRENT STACK TOP AND POSSIBLY A DESCRIPTOR TO IT       *
!*    NEEDED ON AUX STACK IMPLEMENTATIONS AND ALSO IN BEGIN-END BLOCKS *
!*    SO ARRAYS CAN BE UNDECLARED ON BLOCK EXIT. ONLY ACTS ON THE FIRST*
!*    CALL IN ANY BLOCK OR ROUITNE                                     *
!***********************************************************************
            integer JJJ
            if CURRINF_AUXSBASE=0 start
               JJJ = UTEMPTRIP(SSPTR,MINAPT,0,N);  ! SAVE THE STACK POINTER
               CURRINF_AUXSBASE = N
               if TARGET=EMAS and PARM_STACK=0 then N = N+16 else N = N+4
            finish
         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
            record (TAGF) name RCELL,TCELL,PCELL
            routine spec DTABLE(integer LEVEL)
            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 and c
               LAST INST=0 then JJ = UCONSTTRIP(RTBAD,X'51',0,0)
                                         ! RUN FAULT 11
            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_AUXSBASE
               if JJ#0 then start;       ! ARRAYS TO BE UNDECLARED
                  JJ = UCONSTTRIP(RSPTR,X'51',0,JJ)
               finish
            finish
            FORCE TRIPS;                 ! BEFOR LABEL LIST CLEARED IN OPT MODE
            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,ASLIST(J)_S3&X'FFFF',KP)
                  CLEAR LIST(J)
               finish else start
                  if I&LABUSEDBIT=0 and KP<MAX ULAB then WARN(3,KP)
               finish
            repeat
!
            NMAX = (NMAX+7)&(-8)
            CURRINF_SNMAX = NMAX
!
! FOR ROUITNE CHECK PARAMETER LIST FOR ARRAY PARAMETERS AND PASS
! BACK ANY INFORMATION ON DIMENSIONALAITY GLEANED DURING THE BODY
!
            JJ = CURRINF_M-1;            ! RT NALE
            if JJ>=0 start
               RCELL == ASLIST(TAGS(JJ))
               if RCELL_PTYPE&X'1000'#0 start;    ! NAME COULD BE REDECLARED%c
                                                  AS LOCAL
                                         ! IF THIS HAPPENS SKIP GLEANING
                  K = RCELL_SLINK
                  while K>0 cycle;       ! DOWN PARAM LIST
                     TCELL == ASLIST(K)
                     if TCELL_PTYPE&X'F00'=X'500' and TCELL_UIOJ&15=0 start
                                         ! TCELL IS ARRAY OF UNKNOWN DIMENSION
                        PCELL == ASLIST(TAGS((TCELL_UIOJ>>4)&4095))
                                         ! ONTO LOCAL TAGS
                        TCELL_UIOJ = TCELL_UIOJ!PCELL_UIOJ&15
                                         ! COPY BACK DIMENSIO
                     finish
                     K = TCELL_LINK
                  repeat
               finish
            finish
!
! NOW PLANT THE BLOCK EXIT SEQUENCE
!
            if KKK&X'1000'#0 then JJ = UCONSTTRIP(RTXIT,X'51',0,KKK)
            JJ = UCONSTTRIP(XSTOP,X'51',0,KKK) if KKK=1;   ! %stop AT%c
                                                           endofprogram
            CLEAR LIST(TWSPHEAD);        ! CAN NOT CARRY FORWARD
            cycle JJ = 0,1,4
               CLEAR LIST(CURRINF_AVL WSP(JJ));  ! RELEASE TEMPORARY LOCATIONS
            repeat
            if TARGET=PERQ or TARGET=ACCENT then FORCE TRIPS
                                         ! PERQ NEED THIS BEFORE DTABLE AS
                                         ! DTABLE OFFSET GOES IN RTDICT

                                         ! PNX MUST HAVE DATBLE FIRST OR
                                         ! FILLING OF DTABLE REFS FAILS
            DTABLE(LEVEL);               ! OUTPUT DIAGNOSTIC TABLES
            FORCE TRIPS
                                         ! ALL TRIPS MUST BE DEALT WITH
                                         ! BEFORE CURRENT LEVELS ARE CHANGED
            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
!
            if KKK=2 then return
!
! 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'#0 then start
               RLEVEL = CURRINF_RBASE
               RBASE = RLEVEL
            finish
!
! RESTORE INFORMATION ABOUT THE (NEW) CURRENT LEVEL
!
            NMAX = CURRINF_SNMAX if KKK&X'1000'#0
            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'#0 and PARM_COMPILER=0 and (RLEVEL>0 or c
               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,1)
                  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.                                    *
!***********************************************************************
integerfnspec swopof(integer ptype,value)
string (11) RT NAME
string (11) LOCAL NAME
if 1<<host&unsignedshorts=0 start
   record format HEADF(short RTLINE,LINEOFF,OFLAGS,ENV,
      DISPLAY,RTFLAGS,(integer IDHEAD or string (11) RTNAME))
   record format VARF(short FLAGS,DISP, string (11) VNAME)
finish else start
   record format HEADF(half integer RTLINE,LINEOFF,OFLAGS,
      ENV,DISPLAY,RTFLAGS,
      (integer IDHEAD or string (11) RTNAME))
   record format VARF(half integer FLAGS,DISP,
      string (11) VNAME)
finish
record (HEADF) name DHEAD
record (VARF) name VAR
record (LISTF) name LCELL,scell
record(swdataform)name swdata
const integer LARRROUT=X'F300'
record (TAGF) T
integer DPTR,LNUM,ML,KK,JJ,Q,DEND,BIT,S4,LANGD,RULES,II
const integer DLIMIT=700
integer array DD(0:DLIMIT);    ! 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
      if PARM_TRACE=1 then PDATA(DAREA,4,0,ADDR(DD(0)));      ! TO WORD BOUNDARY
      FILL DTABREFS(CURRINF_RAL)
      PUSH(LEVELINF(LEVEL-1)_RAL,DAREA,CAS(DAREA)+4,LANGD) if PARM_TRACE#0
      DHEAD == RECORD(ADDR(DD(0)))
      DHEAD_RTLINE <-swopof(X'41', CURRINF_L)
      DHEAD_LINEOFF <-Swop of(x'41', CURRINF_DIAGINF)
      DHEAD_OFLAGS <-Swop of(x'41', LANGD>>16)
      DHEAD_ENV = 0
      if TARGET=IBM or TARGET=IBMXA or TARGET=AMDAHL then c
         DHEAD_DISPLAY = CURRINF_RBASE else c
         DHEAD_DISPLAY <-Swop of(x'41', CURRINF_DISPLAY)
      DHEAD_RTFLAGS <-Swop of(x'41', 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 = WORKA_LETT(ML);            ! LENGTH OF THE NAME
      DPTR = 4; DEND = 0
      if LNUM=0 then DHEAD_IDHEAD = 0 else start
         Q = ADDR(WORKA_LETT(ML))
         RT NAME <- STRING(Q);          ! FOR RTS MOVE IN 1ST 32 CHARS
         LNUM = LENGTH(RT NAME)
         DHEAD_RTNAME = RTNAME;         ! AND UPDATE POINTER PAST
!         %if HOST#TARGET %and PARM_TRACE#0 %then %c
!            CHANGE SEX(ADDR(DD(0)),12,LNUM+1)
         DPTR = DPTR+LNUM>>2;           ! ACTUAL NO OF CHARS
      finish
      DD(DPTR) <-Swop of(X'51',CURRINF_ONWORD);! ON CONDITION WORD
      DPTR = DPTR+1
      JJ = CURRINF_NAMES
      while 0<=JJ<X'3FFF' cycle
         LCELL == ASLIST(TAGS(JJ))
         T = LCELL
!     printstring("undeclaring"); printstring(printname(jj)); newline
                                         ! OBTAIN NEXT NAME FORM DECLNS
!
! GET ONLY THE MINIMUM OF DETALS NECESSARY
!
         S4 = LCELL_LINK
         PTYPE = T_PTYPE; TYPE = PTYPE&15
!
! FAULT ALL UNUSED NAMES EXCEPT CONSTINTEGERS&REALS
!
         if (TYPE>2 or PTYPE&X'FF00'#X'4000' or c
            PARM_STACK#0) and T_UIOJ&X'C000'=0 then WARN(2,JJ)
         I = T_UIOJ>>4&15
         J = T_UIOJ&15
         K = T_SLINK
!
! ALLOW OWNS (LITL=0) AND EXTERNALS (=2) NOT CONSTS(=1) OR EXTRINSIC(=3)
!
         if PARM_DIAG#0 and PTYPE&X'7300'<=X'200' and c
            DPTR<DLIMIT-3 and (1<=TYPE<=3 or TYPE=5) start
            Q = ADDR(WORKA_LETT(WORD(JJ)));  ! ADDRESS OF NAME
            if I=0 then II = 1 else II = 0;   ! GLA OR LNB BIT
            VAR == RECORD(ADDR(DD(DPTR)))
            VAR_FLAGS <- swopof(X'41',PTYPE<<4!II<<2)
            if ((PARAMS BWARDS=YES and k<currinf_display) or (STACK DOWN=YES and k>Currinf_display))c
                  and PTYPE&X'C00'=0 and II=0 and c
               (TYPE=3 or TYPE=5) start;  ! VALUE RECS&STRS
               if K<Currinf_display then rules=2 else rules=1
                KK=rounding length(ptype,rules)
               K = (K+T_ACC+kk)&(¬KK)
            finish
            VAR_DISP <- swopof(X'41', K)
           if target=eamd and I#0 Then var_disp=k+64;   ! frig so standard diags work
            LOCAL NAME <- STRING(Q);   ! TEXT OF NAME FROM DICTIONARY
            LNUM = LENGTH(LOCAL NAME)
            VAR_VNAME = LOCAL NAME;     ! MOVE IN NAME
            if HOST#TARGET and PARM_TRACE#0 then c
               CHANGE SEX(ADDR(DD(0)),4*DPTR+4,LNUM+1)
            DPTR = DPTR+(LNUM+8)>>2
         finish
         if J=15 and PTYPE&X'3000'#0 and T_UIOJ&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  then start
!            printstring("clearing list for "); printstring(printname(jj)); newline; printlist(k)
            CLEAR LIST(K)
         Finish
         if TYPE=4  then start
!            printstring("clearing list for "); printstring(printname(jj)); newline; printlist(t_kform)
            CLEAR LIST(t_kform)
         Finish
         if type=6 start
            scell==aslist(lcell_slink)
            swdata==record(scell_s1)
            outstring("goto "); outswadname(jj); outstring("_skip;"); outsym(NL)
{GT:}  ! NOTE goto t_despatch ... should pass in __LINE__ and __FILE__
       ! rather than allow them to be picked up at point of dispatch
       ! by which time they are meaningless
            outswadname(jj); outstring("_despatch:"); outsym(NL)
            outstring("switch ("); outswadname(jj);
            outstring("_value) {"); outsym(NL)
            for lnum=0,1,swdata_lseen-1 cycle
               outstring("case ")
               p=swdata_slabs(lnum); csexp(x'51') { No symbolic consts}
               outstring(": goto "); outswadname(jj)
               outsym('_')
               p=swdata_slabs(lnum); labexp
               outsym(';'); outsym(NL)
            repeat
            outstring("default:")
            if swdata_default#0 then start
                outstring("goto "); outswadname(jj)
                outstring("_default;")
            else
{GT:}   ! NOTE: using __LINE__ and __FILE__ from the dispatch table
        ! is not very helpful.  We really want to know where the switch
        ! was jumped to from, at the source of the original ->sw(i)
        ! so I now note the originals into name_file and name_line
        ! at the point of the jump.  I think it's worth the overhead
        ! of the two extra assignments.

        ! NOTE ALSO: I assume the body of BADSWITCH is 
        ! dumped at a %endofprogram - would be better not to,
        ! and to supply it in "imptoc.h" instead
        ! because of problems described elsewhere to
        ! do with limitations of this traslator
        ! (though I haven't yet found where it's dumped so I may be wrong)

                outstring("BADSWITCH("); outswadname(jj);
{GT:}!          outstring("_value,__LINE__,__FILE__);")
                outstring("_value,")
                outswadname(jj); outstring("_line,")
                outswadname(jj);outstring("_file);")
            finish
            outsym(NL); outsym('}'); outsym(NL)
            outswadname(jj); outstring("_skip:;"); outsym(NL)
            free(addr(swdata))
            kk=t_slink
            clear list(kk)
         finish
         LCELL_LINK = ASL; ASL = TAGS(JJ)
         TAGS(JJ) = S4&X'3FFFF'
         JJ = S4>>18
      repeat
      DD(DPTR) = -1;                    ! 'END OF SEGMENT' MARK (Not swopped!)
      DPTR = DPTR<<2+4
      if PARM_TRACE=1 then PDATA(DAREA,4,DPTR,ADDR(DD(0)))
                                         ! ADD TO SHARABLE SYM TABS
      return
integerfn Swopof(integer ptype,value)
!***********************************************************************
!*      Does the byte swopping for cross compilers using rt in P4      *
!***********************************************************************
record(rd)opnd
      if host#target then start
         Opnd=0
         Opnd_d=value
        Opnd_ptype=ptype
         Reformatc(Opnd)
         value=Opnd_d
      finish
      result=Value
end
end;                         ! OF ROUTINE DTABLE
         end
routine DECLARE SCALARS(integer 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.             *
!***********************************************************************
integer INC,SCAL NAME,RL
      PACK(PTYPE)
      INC = ACC; SNDISP = 0
      RL = ROUNDING LENGTH(PTYPE,1)
      if NAM#0 and ARR=0 then INC = PTRSIZE(PTYPE&127) and RL=ptrrounding(ptype&127+128)
      if NAM>0 and ARR>0 then INC = AHEADSIZE and RL=rounding length(aheadpt,1)
      if PTYPE=X'35' and (ACC<=0 or ACC>256) then c
         FAULT(70,ACC-1,0) and ACC = 255
      if type=5 start
        outstring("char ")
      finish else outtype(ptype&255,xtra)
      until A(P-1)=2 cycle;        ! DOWN THE NAMELIST
         N = (N+RL+SFRAME MISALIGN)&(¬RL)-SFRAME MISALIGN
         SCAL NAME = FROM AR2(P)
         if nam#0 then outstring("*")
         outname(scalname)
         P = P+3
         STORE TAG(SCAL NAME,LEVEL,RBASE,0,SNDISP,ACC,N,XTRA)
         N = N+INC
         if type=5 and nam=0 start
           outstring(" ["); outint(acc);
           outstring("] ")
         finish
         if a(p-1)=1 then outsym(',')
      repeat
      N = (N+MIN PARAM SIZE-1)&(-MIN PARAM SIZE);  ! THIS IS NECESSARY !
end
integer fn DOPE VECTOR(integer TAMPER,TYPEP,ELSIZE,MODE,IDEN)
!***********************************************************************
!* Construcst a pseudo dope vector for the handling of arrays          *
!* which is as much like the compiler one as possible. Since           *
!* C arrays all start from 0 but Imp ones can start from anywhere      *
!* provision is needed to take off the lower bound from each index     *
!* on every access.                                                    *
!* The dope vector consists of:-                                       *
!*     word 0 ignored                                                  *
!*     word 1 dimensions<<16 ! element size                            *
!*     word 2 ignored                                                  *
!*     and then a triple for each dimension                            *
!*     word 0 the lower bound if constant                              *
!*     word 1 pointer to the lb expression                             *
!*     word 2 pointer to the ub expression                             *
!*                                                                     *
!* If TAMPER =YES then small +ve lower bounds are reset                *
!* to zero in the interests of access efficiency                       *
!*  IDEN is only for error messages                                    *
!*  Mode not relevant                                                  *
!***********************************************************************
integer I,JJ,K,ND,D,M0,HEAD,NOPS,TYPEPP,PIN,etype,value
record (RD) OPND
record (LISTF) name LCELL
integer array LBH,LBB,LBp,UBp(0:12)
integer array DV(0:39);      ! ENOUGH FOR 12 DIMENSIONS
      ND = 0; TYPEPP = 0; PIN = P
      M0 = 1
      until A(P)=2 cycle
         ND = ND+1; P = P+1
         LBp(ND)=p; etype=tsexp(value)
         p= LBp(ND)+3
         FAULT(37,0,IDEN) and ND = 1 if ND>12
         LBH(ND) = 0; LBB(ND) = 0
         NOPS=0
         TORP(LBH(ND),LBB(ND),NOPS,1)
         UBp(ND)=p
         skip exp
         if imod(etype)=1 start
            expop(LBH(ND),LBB(ND),NOPS,x'251')
            lbb(ND)=expopnd_d
         else
            lbb(ND)=x'80000000'       { Mark as not known }
         finish
      repeat
      P = P+1
!
! now tamper with the lower bounds if permitted
!
      if TAMPER=YES start
         cycle D = 1,1,ND
            if LBB(d)>0 and LBB(d)*ND<=6 then LBB(d)=0
         repeat
      finish
!
! SET UP THE DOPEVECTOR 
!
      DV(1) = ND<<16!ELSIZE
      for d=1,1,nd cycle
         k=3*d
         DV(k)=LBB(d)
         DV(K+1)=LBp(d)
         DV(k+2)=UBp(d)
      repeat

      K = 3*ND+2
      j = ND;                 ! set dimensionality
      SNDISP = 4*WORKA_CONST PTR
      I = SNDISP
      cycle D = 0,1,K
         CTABLE(WORKA_CONST PTR) = DV(D)
         WORKA_CONST PTR = WORKA_CONST PTR+1
      repeat
      if WORKA_CONST PTR>WORKA_CONST LIMIT then c
         FAULT(102,WORKA_WKFILEK,0)
      result = I
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,CDV,
   LWB,PTYPEPP,JJJ,JJ,TRIP1,RL,TOPp,iden
record (RD) OPND1
      SAVE STACK PTR;              ! FOR LATER UNDECLARING
      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(YES,TYPE,ELSIZE,1,FROMAR2(PP))
      TOPP=P
      ND = J
      CDV = 1
      if LWB=0 and FORMAT=0 then PTYPEPP = PTYPEP+256
      SNDISP = SNDISP>>2
      DVDISP=DVDISP>>2
DECL:                                    ! MAKE DECLN - BOTH WAYS
      J = ND
      RL=ROUNDINGLENGTH(AHEADPT,1)
      N = (N+RL)&(¬RL);              ! MAY BE BENEFITS IN WORD ALIGNMENT
      cycle JJJ = 0,1,NN-1;        ! DOWN NAMELIST
         iden = FROM AR2(PP+3*JJJ)
         PTYPE = PTYPEPP; UNPACK
         STORE TAG(iden,LEVEL,RBASE,ND,dvdisp,ELSIZE,N,FINF)
         N = N+AHEADSIZE
         if format=0 start
             if ptypepp&15=5 then outstring("char ") else outtype(ptypepp&255,finf)
            outname(iden)
            for ii=nd,-1,1 cycle
               p=ctable(dvdisp+3*ii+2)
               outstring(" [")
               csexp(x'51')
               if ctable(dvdisp+3*ii)=x'80000000'start
                  outsym('-'); p=ctable(dvdisp+3*ii+1)
                  outsym('('); csexp(x'51'); outstring(")+1")
               finish else if ctable(dvdisp+3*ii)<1 start
                  outsym('+'); outint(1-ctable(dvdisp+3*ii))
               finish else if ctable(dvdisp+3*ii)>1 start
                  outsym('-'); outint(ctable(dvdisp+3*ii)-1)
               finish
               outsym(']')
               if ptypepp&15=5 start
                 outstring(" ["); outint(elsize);
                 outstring("] ")
               finish
            repeat
            if jjj#NN-1 then outsym(';') and outsym(NL)
         finish
      repeat
      P = TOPP+1;                     ! PAST REST OF ARRAYLIST
      if A(P-1)=2 then return
      outsym(';') and outsym(NL)
      ->start
end
         integer fn ROUNDING LENGTH(integer PTYPE,RULES)
!***********************************************************************
!*    RULES=0 IN RECORDS(BEST DEFINED)                                 *
!*    RULES=1 IN STACK FRAME(MOST LATITUDE)                            *
!*    RULES=2 AS PARAMETERS(FUNNY HARDWARE CONSIDERATIONS)             *
!***********************************************************************
            if PTYPE&X'1000'#0 then result = PTR ROUNDING(128*RULES)
                                         ! TREAT RT PARAMS AS %name
            if PTYPE&X'C00'#0 then c
               result = PTR ROUNDING(PTYPE&X'7F'+128*RULES)
            result = RNDING(PTYPE&X'7F'+128*RULES)
         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.           *
!***********************************************************************
            integer ALT,PTYPEP,I,FLAGS,SJ
            ALT = A(P)
            FLAGS = TYPEFLAG(ALT)
            if FLAGS&X'8000'#0 then c
               P = P+1 and FLAGS = TYPEFLAG(A(P)+FLAGS&15)
            if FLAGS&X'4000'#0 then P = P+1;    ! ALLOWS BYTE OR BYTEINTEGER%c
                                                ETC
            if FLAGS&X'2000'#0 then WARN(8,0);    ! SUBSTITUTION MADE
            if FLAGS&X'1000'#0 then FAULT(99,0,0)
            PREC = FLAGS>>4&15
            TYPE = FLAGS&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,MINAPT)#0 then FAULT(41,0,0) and i=255
                     FAULT(70,I,0) unless 1<=I<=255
                     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 start
               SJ = J
               KFORM = CFORMATREF
               PTYPE = PTYPEP
               UNPACK
               J = SJ
            finish
         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

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,SACC,SKFORM,PCHKWORD,pcount
record(listf) name lcell
string(255) ss
      LITL = EXTRN&3
      ACC = 0; KFORM = 0;          ! FOR NORMAL RTS-CLT WILL REVISE
      if A(P)=1 then start;        ! P<RT>=%routine
         TYPEP = LITL<<14!X'1000'
         P = P+4;                  ! IGNORING ALT OF P(SPEC') and hole
      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+4;                  ! AGAIN IGNORING ALT OF P(SPEC') and hole
      finish
      KK = FROM AR2(P)
      AXNAME = ADDR(WORKA_LETT(WORD(KK)))
      JJ = 0
      P = P+3
      SACC = ACC; SKFORM = KFORM;  ! FOR RECORD MAPS WITH PARAMS
      if A(P-1)=1 then start
         if LITL=0 then WARN(10,0)
         MOVE BYTES(A(P)+1,ADDR(A(0)),P,ADDR(A(0)),WORKA_ARTOP)
         outstring("#define "); outstring(string(axname))
         AXNAME = ADDR(A(WORKA_ARTOP))
         outsym(' ')
         if string(axname)="s_cstring" then outstring("s__cstring") else outstring(string(axname))
          outsym(NL)
         WORKA_ARTOP = (WORKA_ARTOP+4+A(P))&(-4)
         P = P+A(P)+1
      finish
      CFPLIST(OPHEAD,NPARMS)
      PCHKWORD = 0
      ss=string(axname)             { symbol table vsn of name }
      if 0<=m<=1 start
         unless typep&x'c000'#0 andc
             (ss="malloc" or ss="free" or ss="realloc" or ss="perror" orc
              ss="getcwd"  or ss="strlen") c
             then start
!            %if typep&x'c000'=0 %then outstring("static ")
            if typep&x'c000'=x'8000' then outstring("extern ")
            outtype(typep&255,skform)
            if typep&x'800'#0 and typep&7#5 then outsym('*')
            outname(kk); outsym('('); outsym(' ')
            lcell==aslist(ophead)
            if nparms=0 then outstring("void ") else start
               for pcount=1,1,nparms cycle
                  if lcell_s1&x'10000000'#0 start
{GT: Unfixed bug.  Type parameter i 0 in an externalspec }
{    and shows up as  extern void itos(void, void)       }
{    instead of       extern void itos(int, int)         } 
                     outtype(lcell_s1>>16&255,lcell_sndisp); outstring("()")
                  else
                     outxtype(lcell_s1>>16,lcell_sndisp)
                  finish
                  if lcell_link#0 then outsym(',')
                  lcell==aslist(lcell_link)
               repeat
            finish
            outstring(");")
         finish
      finish
      if NPARMS>0 then PCHKWORD = NPARMS<<16!ASLIST(OPHEAD)_S3>>16
      if M=1 then start
         if TARGET=EMAS or TARGET=PNX or TARGET=IBM or c
            TARGET=IBMXA or target=amdahl or c
            1<<target&emachine#0 then c
            CXREF(STRING(AXNAME),3*PARM_DYNAMIC!EXTRN,PCHKWORD,JJ)
                                   ! %system & %external =STATIC
                                   ! UNLESS PARM DYNAMIC SET
                                   ! %dynamic = DYNAMIC
         if TARGET=PERQ or TARGET=ACCENT then c
            JJ = AXNAME-ADDR(A(WORKA_DICTBASE))
      finish else start
         if TARGET=PERQ or TARGET=ACCENT then c
            JJ = WORKA_RTCOUNT and 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&1; PTYPE = TYPEP
      STORE TAG(KK,LEVEL,RBASE,j,JJ,SACC,OPHEAD,SKFORM)
end
         routine CFPLIST(integer name 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!LNAME<<12!DIMENSION(DIMEN DEDUCED LATER)*
!*                                      LNAME IS PARAMS LOCAL NAME     *
!*    S2 = PARAMETER OFFSET(SNDISP) <<16 ! ACC                         *
!*    S3 = 0                                 (RESERVED FOR FPP OF RTS) *
!*                                                                     *
!*    ON ENTRY P IS AT ALT OF FPP (WHICH MAY BE NULL)                  *
!***********************************************************************
            integer OPBOT,PP,INC,RL,RSIZE,CELL,PSIMPLE
            record (LISTF) name LCELL
            OPHEAD = 0; OPBOT = 0
            NPARMS = 0;                  ! ZERO PARAMETERS AS YET
            PSIMPLE = 1;                 ! NO COMPLEX PARAMS 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
               PSIMPLE = 0 unless c
                  PTYPE=X'51' or (ROUT=ARR=0 and NAM=1 and 0<TYPE<=3)
               if rout#0 Start
                  INC = RT PARAM SIZE
                  RL = ROUNDING LENGTH(RTPARAMPT,2)
               finish else if ARR=1 then start
                  INC = AHEADSIZE;
                  RL = ROUNDING LENGTH(AHEADPT,2)
               finish else if NAM=1 then start
                  INC = PTRSIZE(PTYPE&X'7F')
                  RL = PTRROUNDING(PTYPE&X'7F'+256)
               finish else if STRVALINWA=YES and PTYPE=X'35' then start
                  INC = PTRSIZE(X'35')
                  RL = PTRROUNDING(256+X'35')
               finish else if RECVALINWA=YES and PTYPE=X'33' then start
                  INC = PTRSIZE(X'33')
                  RL = PTRROUNDING(256+X'33')
              finish else if TARGET=EMAS and PTYPE=X'33' then start
                  INC = ACC+8;           ! ALLOW FOR DESCRPTR FOR IMP80%c
                                         COMPATABILITY
                  RL = 3;                ! STRICTLY ROUNDING LENGTH(X'33',2)
               finish else INC = ACC and RL = ROUNDING LENGTH(PTYPE,2)
               until A(P-1)=2 cycle;     ! DOWN <NAMELIST> FOR EACH DEL
                  if PARAMS BWARDS=YES then start
                     PUSH(OPHEAD,0,0,RL)
                     CELL = OPHEAD
                  finish else start
                     BINSERT(OPHEAD,OPBOT,0,0,RL)
                     CELL = OPBOT
                  finish
                  LCELL == ASLIST(CELL)
                  LCELL_PTYPE <- PTYPE;  ! DIRECT "PUSH" FAILS ON HALF SWOPPED%c
                                         MACHINES
                  LCELL_SNDISP = kform
                  LCELL_ACC <- ACC
                  NPARMS = NPARMS+1
                  P = P+3
               repeat
               P = PP
            repeat
            OPBOT = OPHEAD; INC = 0;     ! FURTHER PASS TO ALLOCATE SPACE
!            %while OPBOT>0 %cycle
!               LCELL == ASLIST(OPBOT)
!               RL = LCELL_S3; LCELL_S3 = 0;  ! EXTRACT ROUNDIMG LENGTH
!               RSIZE = LCELL_SNDISP;     ! INC EXTRACTED
!               INC = (INC+RL+SFRAME MISALIGN)&(¬RL)-SFRAME MISALIGN
!               %if PARAMSBWARDS=NO %and RSIZE<MINPARAMSIZE %and %c
!                  LCELL_PTYPE&7<=2 %then INC = INC+MINPARAMSIZE-RSIZE
!                                         ! MAINTAIN BYTES &SHORTS IN BTM
!                                         ! OF WORDS FOR 2900&IBM ARCHITECTURE
!               LCELL_SNDISP <- INC;      ! THE PARAMETER OFFSET
!               INC = INC+RSIZE
!               OPBOT = LCELL_LINK
!            %repeat
            INC = (INC+RL+SFRAME MISALIGN)&(¬RL)-SFRAME MISALIGN
            P = P+1
            PRINT LIST(OPHEAD) if PARM_Z#0
            PP = INC<<16!NPARMS
            if (TARGET=IBM or TARGET=IBMXA or TARGET=AMDAHL) then c
               PP = PP!PSIMPLE<<15
            if NPARMS>0 then ASLIST(OPHEAD)_S3 = PP
            PRINTLIST(OPHEAD) if PARM_Z#0
         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 = RT PARAM SIZE
            ->PK
FP(3):                                   ! %name
            ACC = PTRSIZE(0); NAM = 1
            ROUT = 0; TYPE = 0
            ARR = 0; PREC = 0
PK:         PACK(PTYPE)
         end
         routine RHEAD(integer RTNAME,AXNAME,Xtra)
!***********************************************************************
!*       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,Flags
            record (LISTF) name LCELL
            Flags=0
            if Xtra#0 then flags=Bstruct
            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
                  if JRNDBODIES=YES then ENTER JUMP(15,PLABEL,0)
               finish
               RLEVEL = RLEVEL+1; RBASE = RLEVEL
{GT:}!         FAULT(105,0,0) if RLEVEL>=2  {REMOVING THIS ALLOWS NESTED PROCS}
            finish
            LEVEL = LEVEL+1
            CURRINF == LEVELINF(LEVEL)
            CURRINF = 0
            CURRINF_RBASE = RBASE
            CURRINF_CLEVEL = LEVEL;      ! SELF POINTER IS NEEDED IN GENERATE
            CURRINF_NAMES = -1
            CURRINF_DIAGINF = LEVELINF(LEVEL-1)_DIAGINF
!            %if target=gould %then currinf_maxpp = levelinf(level-1)_maxpp
            CURRINF_DISPLAY = LEVELINF(LEVEL-1)_DISPLAY
            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 start      { For begin blocks  }
               if axname=0  start        { not initial begin }
                  currinf_iblkid=internalblockid
                  internalblockid=internalblockid+1   { keep a blk no for switches & labels }
               finish
               W3 = 0
            else
               W3 = RTNAME+1
               internalblockid=0
            finish
            CURRINF_L = LINE; CURRINF_M = W3
            CURRINF_FLAG = PTYPE&X'FFFF';  ! CURRENT BLOCK TYPE MARKER
                                         ! SIGN MUST NOT PROPOGATE
!
! TILL LOADER COPIES GLAP TO GLA MUST CALL A FRIG ROUTINE TO DO
! THIS ESSENTIAL AS SOON AS POSSIBLE IN ANYTHING EXTERNAL
!
            W3 = ULCONSTTRIP(RTHD,X'61',Flags,RTNAME,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-alpha;  ! REMEMBER PARAMETER SIZE FOR RTDICT
               if 1<<target&riskmc#0 then N=(N+display rounding)&(¬display rounding)
               CURRINF_DISPLAY = N
               if DISPLAY NEEDED=YES start
                  N = N+DISPLAY C1*RLEVEL+DISPLAY C0;  ! RESERVE DISPLAY SPACE
               finish
               TRIPNO = UCONSTTRIP(RDSPY,X'51',0,CURRINF_DISPLAY)
            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
                  if target=vns then c
                     currinf_diaginf = currinf_psize+8 else start
                     TRIPNO = UCONSTTRIP(RDAREA,X'51',0,N)
                     N = N+4
                     N = N+4 if 1<<Target & Riskmc#0; ! extra word here on risks
                     CURRINF_DIAGINF = N
                     N = N+4
!
! For risk and some others it is better to use words for line & diag pointers
! if half word access is slow.
!
                     if target=ORN or 1<<target&riskmc#0 then N=N+4
                  finish
               finish
               TRIPNO = UCONSTTRIP(RDPTR,X'51',0,LEVEL)
            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 PT,MARKER,J,LNAME,TYPEP,PRECP,ALT,KK
record (RD) OPND1
integer HEAD1,BOT1,NOPS,savepos
record (RD) RPOP
record (LISTF) name LCELL
record(swdataform)name swdata
owninteger depth
switch SW(1:9)
      depth=depth+1
      if depth=1 then savepos=opline_length and outsym(' ')
      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 start
         if depth=1 then opline_l(savepos)='{'
{GT:}    if opline_l(opline_length-1) # '{' then outstring("; ")
         CUI(CODE)
        if depth=1 then outstring(";}")
      finish
      depth=depth-1
      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
         outstring("goto "); outname(lname)
      finish else start;           ! SWITCH LABELS
         COPY TAG(LNAME,NO)
         unless OLDI=LEVEL and TYPE=6 start
            FAULT(4,0,LNAME); P = P-1; SKIP APP
            return
         finish
         outsym('{'); outswadname(lname); outstring("_value=")
         CSEXP(MINAPT)
{GT:}  ! NOTE goto t_despatch ... should pass in __LINE__ and __FILE__
       ! rather than allow them to be picked up at point of dispatch
       ! by which time they are meaningless
{GT:}    outstring("; "); outswadname(lname); outstring("_line = __LINE__")
{GT:}    outstring("; "); outswadname(lname); outstring("_file = __FILE__")
         outstring("; goto "); outswadname(lname)
         outstring("_despatch;}")
         REPORTUI = 1
      finish
      depth=depth-1
      return
SW(3):                                   ! RETURN
      FAULT(30,0,0) unless CURRINF_FLAG&X'3FFF'=X'1000'
      P = P+1
      outstring("return ")
RET:  KK = UCONSTTRIP(RTXIT,X'51',0,0)
      REPORT UI = 1
      CURR INST = 1 if CODE=0
      depth=depth-1
      return
SW(4):                                   ! %result(ASSOP)(EXPR)
      outstring("return ")
      PTYPE = CURRINF_FLAG&X'3FFF'; UNPACK
      PT=ptype&255
      OPND1 = 0
      OPND1_PTYPE <- PTYPE; OPND1_FLAG = DNAME
      OPND1_D = CURRINF_M-1
      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)
            KK = BRECTRIP(MAPRES,PTYPE&255,0,OPND1,NAMEOPND)
            FAULT(81,0,0) unless A(P)=2; P = P+1
            FAULT(83,CURRINF_M-1,FROMAR2(J)) unless c
               TYPEP=TYPE and PRECP=PREC
            ->RET
         finish
         if A(P+1)=2 and NAM=0 then start;      ! ASSOP='='
            P = P+2
            if TYPE=5 then start
               CSTREXP(0);        ! FULL VIRTAD
            finish else if TYPE=3 start
               ->BAD RES unless A(P+3)=4 and A(P+4)=1
               P = P+5
               CNAME(3)
               FAULT(66,0,OPND1_D) unless TYPE=3
               EXPOPND = NAMEOPND
            finish else start
               if PREC<4 then PREC = 4
               CSEXP(PREC<<4!TYPE)
            finish
            if PT=X'31' or PT=X'41' Start
               kk=urectrip(SHRTN,PT,0,expopnd)
               expopnd_flag=reftrip; expopnd_d=kk
               expopnd_ptype=PT
            finish
            KK = BRECTRIP(FNRES,PTYPE&255,0,OPND1,EXPOPND)
            ->RET
         finish
      finish
      P = P+2
BAD RES:
      FAULT(31,0,0)
      SKIP EXP;                    ! IGNORE SPURIOUS RESULT
      depth=depth-1
      return
SW(5):                                   ! %monitor (AUI)
! Woud be nice to intercept this at the level above and translate
! %if <cond> %then %monitor
! to
! assert(!(cond))
{GT:} outstring("assert(_IMP_MONITOR_)")
      P = P+1; ->AUI
SW(6):                                   ! %stop
{GT:} outstring("exit(0)"{"imp_stop()"})
!      KK = UCONSTTRIP(XSTOP,X'51',0,0)
      P = P+1
      CURR INST = 1 if CODE=0
      REPORTUI = 1
      depth=depth-1
      return
SW(7):                                   !'%SIGNAL'(EVENT')(N)(OPEXPR)
      P = P+5
      KK = INTEXP(J,MINAPT);       ! EVENT NO TO J
      if A(P)=1 start;             ! SUBEVENT SPECIFIED
               P = P+3;  skip exp
      finish
      outstring("*** IMP signals untranslateable *****")
      depth=depth-1
      return
SW(8):                                   ! %exit
      outstring(" break ")
      REPORTUI = 1
      CURR INST = 1 if CODE=0
      depth=depth-1
      return
SW(9):                                   ! %continue
      REPORTUI = 1
      CURR INST = 1 if CODE=0
      outstring(" continue ")
      depth=depth-1
      return
         end
         routine CIFTHEN(integer MARKIU,MARKC,MARKUI,MARKE,MARKR,Afterelse)
!***********************************************************************
!*    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,
   ELSEALT,K,J,CS,LINETRIP,ctype
const integer NULL ELSE=4
switch ESW(1:NULL ELSE)
owninteger depth=0
            depth=depth+1
            LINETRIP = -1
            SET LINE and LINETRIP = TRIPLES(0)_BLINK
            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
! '%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 USERLAB = FROM AR2(MARKUI+1)
                                         ! UI = SIMPLE LABEL
            if 8<=ALTUI<=9 and currinf_EXITLAB#0 start;     ! VALID EXIT
               if ALTUI=8 then USERLAB = currinf_EXITLAB else c
                  USERLAB = currinf_CONTLAB
            finish
!
            ctype=rlevel
            if tcond#0 then ctype=0
            P = MARKC                   { may be changed by tcond }
            if ctype=0 start
                if Afterelse=NO then outsym(NL) and outstring("#if")
            else
               outstring("if ")
            finish
            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 else start
                                      ! DELETE LINE NO UPDATE FOR%c
                                      CONDITIONAL STARTR
                                      ! (IT MIGHT CONTAIN M-C CODE!)
                  if LINE TRIP>0 then TRIPLES(LINETRIP)_OPERN = NULLT
               finish
               P = MARKR+1
               If ctype#0 then  curly check(1) and outsym('{'); outsym(NL)
               CSTART(CCRES,1)
               If ctype#0 then outstring("}");  ! outstring(" /* if clause */")
               if A(P)<=2 then PLABEL = PLABEL-1 and ELSELAB = PLABEL
               MARKE = P
               REPORT = LAST INST
            finish else start
               if CCRES#2 start
                  if ctype=0 then outsym(NL)
                  P = MARKUI; CUI(1)
                  if MARKE#0 and a(MARKE)#NULL ELSE and opline_l(opline_length-1)#'}' then outsep
                  REPORT = REPORTUI
               finish else start;     ! FIRST UI NEVER EXECUTED
                  REPORT = 1
               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
                                         ! CONDITIONAL&MERGE OR REPLACE
            ->ESW(ELSEALT)
ESW(1):                                  ! '%ELSESTART'
            if ctype=0 start
               outsym(NL); outstring("#else"); curly check(1); outsym(NL)
            else
               outstring(" else {"); curly check(1);  outsym(NL)
             finish
            if CCRES=0 then CURRINF_NMDECS = CURRINF_NMDECS!1
            CSTART(CCRES,2)
            If ctype#0 then outstring("}");   ! outstring(" /* else clause*/")
            if ctype=0 start
               outsym(NL); outstring("#endif")
            finish
            ->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
            J = NEXT TRIP
            if ctype=0 start
               outsym(NL); outstring("#else"); outsym(NL)
               CIFTHEN(P,P+3,MARKUI,MARKE,MARKR,no)
               outsym(NL); outstring("#endif")
            else
               outstring(" else ");       ! outsym('{')
               CIFTHEN(P,P+3,MARKUI,MARKE,MARKR,NO)
               outsym(NL);                !  outsym('}')
            finish
            REPORT = 0;                  ! CANT TELL IN GENERAL
            ->ENTER ELSELAB
ESW(3):                                  ! '%ELSE'<UI>
             if ctype=0 start
               outsym(nl); outstring("#else"); outsym(NL)
           else
               outstring(" else ")
           finish
            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
               if ctype=0 then start
                  outsep
                  outsym(NL)
                  outstring("#endif")
               else
                  if depth>1 then outsep
               finish
            finish
ENTER ELSELAB:
            if ELSELAB>0 then ELRES = ENTER LAB(ELSELAB,B'11'!REPORT<<2)
      depth=depth-1; return
                                         ! CONDITIONAL MERGE
ESW(NULL ELSE):                          ! NULL ELSE CLAUSE
           if ctype=0 start
               outsep if start=0
               outsym(NL); outstring("#endif")
           finish
         depth=depth-1; 
         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
{GT:}if CODE=3 then outstring("/* beginning of onevent block */") and outsym(NL)
      SKIPCODE = NO
      if 1<=CODE<=2 and CCRES!CODE=3 then SKIPCODE = YES
                                   ! NEVER EXECUTED
      FINISHAR = FROMAR4(P);       ! TO START OF AR FOR FINISH
      OLDLINE = LINE;              ! FOR ERROR MESSAGES
      cycle;                       ! THROUGH INTERVENING STATMNTS
         OLDNEXTP = NEXTP
         COMPILE A STMNT
      repeat until OLDNEXTP>=FINISHAR;    ! HAVING COMPILED FINISH
{GT:}if CODE=3 then outstring("/* end of onevent block */") and outsym(NL)

      P = FINISHAR+10;              ! 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 IMPABORT
      FORDPTH = FORDPTH+1
      OLDLINE = LINE; SAVEE = currinf_EXITLAB; SAVEC = currinf_CONTLAB
      currinf_EXITLAB = ELAB; currinf_CONTLAB = CLAB
      curly check(1)
      outsym('{'); outsym(NL)
      while NEXTP<=FINISHAR cycle
         COMPILE A STMNT
      repeat
      outstring("}"); ! outstring(" /* loop */")
      currinf_EXITLAB = SAVEE; currinf_CONTLAB = SAVEC
      P = FINISHAR+10
      FORDPTH = FORDPTH-1
      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                          *
!*    FORBITS DEFINES FOR LOOP AS FOLLOWS:-                            *
!*    2**2 TO 2**0 SET FOR CONSTANT INITIAL,INC &FINAL                 *
!*    CORRESPONDING UPPER BYTE SET DEFINES CONSTANT FURTHER            *
!*       2**7 NEGATIVE CONSTANT                                        *
!*       2**4 CONSTANT IS 2                                            *
!*       2**3 CONSTANT IS 1                                            *
!*       2**2 CONSTANT IS 0                                            *
!*       2**1 CONSTANT IS -1                                           *
!*       2**0 CONSTANT IS -2                                           *
!*    THESE BITS ARE PASSED ON TO GENERATOR FOR SPECIAL CASE           *
!***********************************************************************
integer L1,L2,L3,L4,CCRES,ELRES,FLINE,TRIP,FOT,PP,DEBJ,JJ,FSTRIP
integer FORNAME,INITP,STEPP,FINALP,REPMASK,FORPT,FORWORDS,FORBITS
record (RD) INITOPND,STEPOPND,FINALOPND,DIFFOPND,ZOPND,OPND
record (TRIPF) name CURRT
routine spec FOREXP(record (RD) name EOPND, integer TT,SH)
switch SW(0:6)
      P = MARKC
      FORBITS = 0
      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
      PP = FROM AR4(P)+10;          ! TO UNTIL CLAUSE IF ANY
      if A(PP)=1 start;            ! %repeat %until <COND>
         outstring("do ")
         C CYC BODY(1,L2,L3)
!         L3 = L3*ENTER LAB(L3,B'011');  ! DELETE IF NOT NEEDED
         SET LINE
         outstring(" while ")
         P = PP+1; CCRES = CCOND(0,2,L1,0)
      finish else start
         outstring("for (;;) ")
         C CYC BODY(1,L2,L1);      ! CONTINUES DIRECT TO TOP
         !outstring(" while (1) /* FOR EVER */")
!         ENTER JUMP(15,L1,0)
      finish
!      L2 = L2*ENTER LAB(L2,B'011');  ! DELETE IF NOT NEEDED
WAYOUT:                                  ! REMOVE LABELS NOT REQUIRED
      return
sw(1):                            ! UI while cond
      outstring("while ")
      ccres=ccond(0,1,l2,b'11')
      p=markui
      cui(1)
!      enter jump(15,l1,0)         ! uncoditional back to while
!      L2 = L2*ENTER LAB(L2,B'111');  ! CONDITIONAL(?) & REPLACE ENV
      ->WAYOUT
SW(2):                                   ! UI %until COND
      P = MARKUI
      outstring("do ")
      CUI(1)
      P = MARKC
      outsep; outstring(" while ")
      CCRES = CCOND(0,2,L1,0)
      ->WAYOUT
SW(6):                                   ! %for ... %cycle
SW(3):                                   ! UI %for ....
      FORCNT = FORCNT+1;           ! TO DETCT FORS IN ENCLOSED STMTS
      FORNAME = FROMAR2(P)
      INITP = P+2
      COPY TAG(FORNAME,YES);       ! DECLARE IF UNKNOWN TO COMPILER
      FAULT(91,0,FORNAME) and ptype=X'51'  unless c
         (TYPE=7 or TYPE=1) and 4<=PREC<=5 and ROUT=0=ARR and LITL#1
      FOT = DNAME;                 ! FOR OPERAND TYPE
      if NAM#0 then FOT = INDNAME
      FORPT = PTYPE&255;           ! SAVE TYPE&PREC OF CONTROL
!
      P = INITP
      SKIP EXP;                    ! P TO STEP EXPRSN
      STEPP = P; SKIP EXP;         ! P TO FINAL
      FINALP=p
!
      P = STEPP
      FOR EXP(STEPOPND,1,1);       ! Investigate step and evaluate if constant
      outstring(" for (")
      if FOT=INDNAME then outsym('*')
      outname(FORNAME)
      outsym('=')
      P = INITP; csexp(FORPT)
      outsep
      outsym(' ')
      if FOT=INDNAME then outsym('*')
      outname(FORNAME)
      if STEPOPND_FLAG<=1 start
         FAULT(92,0,0) if STEPOPND_D=0;   ! ZERO STEP
         if STEPOPND_D<0 then outstring(">=") else outstring("<=")
      finish else start
         outstring("<=")
         warn(10,0)
      finish
      p=finalp; csexp(FORPT)
      outsep
      outsym(' ')
      if FOT=INDNAME then outsym('*')
      outname(FORNAME)
      if STEPOPND_FLAG<=1 and iMOD(STEPOPND_D)=1 start
         if STEPOPND_D<0 then outstring("--") else outstring("++")
      else
         outstring("+=")
         p=STEPP; csexp(FORPT)
      finish
      outstring(") ")
!
      P = MARKUI;                  ! TO UI OR '%CYCLE'(HOLE)
      if ALT=3 then start;         ! DEAL WITH CONTROLLED STMNTS
         CUI(0)
      finish else start
         CCYCBODY(0,L2,L3)
         finish
      ->WAYOUT
SW(4):                                   ! %while COND %cycle
      SET LINE
      outstring("while ")
      CCRES = CCOND(0,1,L2,2);     ! merge but not short
      C CYC BODY(0,L2,L1)
!      ENTER JUMP(15,L1,0)
!      L2 = L2*ENTER LAB(L2,B'111');  ! CONDITIONAL & REPLACE ENV
      ->WAYOUT
SW(5):                                   ! %until ... %cycle
                                         ! ALSO %cycle... %repeat %until
                                         ! MARKUI TO %cycle
      P = MARKUI
      FLINE = LINE
      outstring("do ")
      C CYC BODY(0,L2,L3)
      P = MARKC
!      L3 = L3*ENTER LAB(L3,B'011');  ! CONTINUE LABEL IF NEEDED
      LINE = FLINE; SET LINE
      outsep; outstring(" while ")
      CCRES = CCOND(0,2,L1,0)
!      L2 = L2*ENTER LAB(L2,B'011')
      ->WAYOUT
routine FOR EXP(record (RD) name EOPND, integer TOTEMP,SHIFT)
!***********************************************************************
!*    P INDEXES EXPRESSION.  IF CONST PUT INTO EVALUE OTHERWISE        *
!*    dont generate anything                                           *
!***********************************************************************
integer INP,VAL,SUBBITS
integer exphead,expbot,nops
      exphead=0; expbot=0; nops=0
      INP = P; P = P+3
      torp(exphead,expbot,nops,1)
      if nops>>16&7=0 start        { nothing difficult }
         expop(exphead,expbot,nops,x'200'+FORPT)
         EOPND = EXPOPND;       ! EXPRESSION A LITERAL CONST
      else
         eopnd_flag=255
      finish
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,ACCP,
               II,HEAD1,NOPS,TPCELL,LVL,BOT1,LHNAME,RHNAME,a1,a2
            record (LISTF) name LHCELL
            record (RD) OPND1,OPND2
            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(NO);      ! 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 LHSADDRFIRST=NO or (NAM=0=ARR and A(P1+2)=2=A(P1+3)) start
                                         ! SCALAR
               OPND1 = 0
               OPND1_PTYPE <- PTYPE; OPND1_FLAG = ARNAME
               BINSERT(HEAD1,BOT1,OPND1_S1,P1,LHNAME)
            finish else start
               P = P1; CNAME(3);         ! 32 BIT ADDR TO STACK
               BINSERT(HEAD1,BOT1,NAMEOPND_S1,NAMEOPND_D,NAMEOPND_XTRA)
            finish
            P = P2+3
            TORP(HEAD2,BOT2,NOPS,0);       ! RHS TO REVERSE POLISH
            OPND2 = 0; OPND2_FLAG = VASS+ASSOP-2
            BINSERT(HEAD2,BOT2,OPND2_S1,LHNAME<<16!PTYPEP,0)
                                         ! = OR <-OPERATOR
            ASLIST(BOT1)_LINK = HEAD2
            HEAD2 = 0; BOT1 = BOT2
            PRINT LIST(HEAD1) if PARM_Z#0
            EXPOP(HEAD1,BOT1,NOPS,256+PRECP<<4+TYPEP);  ! PLANT CODE
         tripopt(triples,triples(0)_flink)
            outopnd(expopnd,0)
            return
ST:                                      ! STRINGS
            p = p1
            if assop=3 then start
               outstring("imp_strjam(")
               if nam#0 then warn(10,0)
            finish else outstring("strcpy(")
            CNAME(2)
            outsym(',')
         p = p2
            CSTREXP(0)
            if assop=3 then outsym(',') and outint(accp-1)
            outsym(')')
            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
               outstring("memset(")
               P = P1; CNAME(3)
               outstring(",0,")
               OPND1 = NAMEOPND
               OPND2 = 0
               OPND2_PTYPE = X'51'; OPND2_FLAG = SCONST
               outstring("sizeof( ")
               p=p1; reducetag(NO)
               outformatname(kform)
               outsym(')'); outsym(')')
               P = P2; SKIP EXP
               return
            finish
            if assop=3 {<-} start
               ->BACK unless TYPE=3 and A(P2+3)=4 and A(P2+4)=1
               outstring("memcpy(")
               P = P1; CNAME(3)
               outsym(',')
               OPND1 = NAMEOPND
               ACCP = ACC
               P = P2+5; CNAME(3)
               outsym(',')
               OPND2 = NAMEOPND
               unless A(P)=2 then FAULT(66,0,LHNAME) and ->F00
!               %if ASSOP=2 %and ACCP#ACC %then %c
!                  FAULT(67,LHNAME,FROMAR2(P2+5)) %and ->F00
               if ACCP>ACC then ACCP = ACC
               outstring("sizeof( ")
               p=p1; reducetag(NO)
               outformatname(kform)
               outsym(')'); outsym(')')
               P = P2; SKIP EXP
               return
            finish
            p=P1; cname(7)
            outstring("=")
            p=p2+5; cname(7)
            P = P2; SKIP EXP
            return
SW(4):                                   ! RESOLUTION
            outstring("imp_resolve(")
            P = P1; CNAME(2)
            outsym(',')
            P = P2;
            if TYPE=5 then CRES(0) else start
               SKIP EXP
               FAULT(71,0,LHNAME) unless TYPE=7
            finish
            outsym(')')
            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==
           lhformatname=kform
            if ARR=1 then start
               JJ = 11; KK = 12
               II = AHASS; B = AHEADPT
            finish else start
               JJ = 6; KK = 3
               II = PTRAS; B = X'51'
               if PTRSIZE(PTYPE&255)>4 then B = X'61'
            finish
            P = P1; CNAME(JJ)
            outsym('=')
            P = P2+5
            RHNAME = A(P)<<8!A(P+1)
            if typep=3 start
              reduce tag(NO)
              if kform#lhformatname start
                 outsym('('); outformatname(lhformatname)
                 outstring("*)")
              finish
            finish
            CNAME(KK);                   ! DESCRPTR FETCHED
            if kk=12 start
!printstring("dv reset "); write( LHCELL_SNDISP,5); write(sndisp,5); write(ctable(sndisp+3),5); newline
            if lhcell_uioj&15=0 then  lhcell_uioj= lhcell_uioj!(j&15)
            if LHCELL_SNDISP=0 then LHCELL_SNDISP=sndisp
         finish
            ->F81 unless A(P)=2;         ! NO REST OF EXP ON RHS
!            ->F83 %unless TYPE=TYPEP %and PREC=PRECP %and (ARR>0 %or II=PTRAS)
!            ->F86 %unless OLDI<=LVL %or I=0 %or NAM#0
                                         ! GLOBAL == NONOWN LOCAL
            P = P+1
            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 outopnd(record(rd)name opnd,integer mode)
!***********************************************************************
!*   Outputs an operand which may be a complete tree                   *
!*      mode&1 = 0 output as is                                        *
!*      mode&1 = 1 output enclosed in ( and )                          *
!*       mode&2#0 output as a store not a load                         *
!*       Mode&256#0 all consts as numeric for switches                 *
!***********************************************************************
integer i,pp
longreal r
switch sw(0:9)
      if mode&1=1 then outsym('(')
      ->sw(opnd_flag)
sw(0):                                {short const }
sw(1):                               {long const }
      if opnd_ptype&7=1 start
         if opnd_ptype&x'f0'=x'60' then outlhex(opnd_d,opnd_xtra) else start
            if opnd_ptype&8#0 and doinglabel=0 then start
               if opnd_ptype>>4&7=3 start
{GT:}             outsym('''');
                  if opnd_d = '¬' or opnd_d = '''' c
                   then outsym('¬');
                  outsym(opnd_d);
                  outsym('''')
               finish else outhex(opnd_d)
            finish else outint(opnd_d)
         finish
      finish
      if opnd_ptype=x'52' then outfl(opnd_r,7)
      if opnd_ptype=x'62' start
         integer(addr(r))=opnd_d
         integer(addr(r)+4)=opnd_xtra
         outfl(r,15)
      finish
      if opnd_ptype=x'72' start
         outstring("NAN or unrepresentable value")
      finish
      if opnd_ptype=x'35' start
         outsym('"')
         outstring(string(addr(a(opnd_d))))
         outsym('"')
      finish
wayout:
      if mode&1=1 then outsym(')')
      return
sw(2):                              { name as dictionary no }
      outname(opnd_d)
      ->wayout
sw(3):                              { name(app) as ar pointer }
      pp=p; p=opnd_d
      if mode&2#0 then cname(1) else cname(2)
      p=pp; ->wayout
sw(8):                              { triple }
      outtriple(opnd_d,mode&x'ff00')
      ->wayout
end
routine outtriple(integer tripno,mode)
!***********************************************************************
!*  output an expression defined by a triple which can head a tree     *
!*  mode as for outopnd                                                *
!***********************************************************************
record(tripf)name trip
conststring(3)array rsassop(ADD:ANDL)="+=","-=","^=",
                                       "|=","*=","/="(2),"&=";
string(15) op,opl
integer case,i,j
switch sw(0:192)
      trip==triples(tripno)
      if mode=1 and doinglabel=0 then outsym('(')
      case=trip_opern
      ->sw(case)
sw(ADD):
      op="+"; opl="plus"
binop:
      outopnd(trip_opnd1,mode&x'ff00'!trip_opnd1_flag>>3&1)
       if doinglabel#0 then outstring(opl) else outstring(op)
      outopnd(trip_opnd2,mode&x'ff00'!trip_opnd2_flag>>3&1)
wayout:
      if mode=1 and doinglabel=0 then outsym(')')
      return
sw(SUB): op="-"; opl="minus"; ->binop
sw(NONEQ): op="^"; opl="non"; ->binop
sw(ORL): op="|"; opl="or"; ->binop
sw(MULT): op="*"; opl="mul"; ->binop
sw(INTDIV): op=" / "; opl="idiv"; ->binop
sw(REALDIV): op=" / "; opl="div"; ->binop
sw(ANDL): op="&"; opl="and"; ->binop
sw(RSHIFT): op=">>"; opl="rsh";  
      if doinglabel=0 then start
         if trip_opnd1_ptype&x'ff'=x'61' then start
             outstring("(UINT64)")
         else
             outstring("(unsigned)")
         finish
      finish; ->binop
sw(LSHIFT): op="<<"; opl="lsh"; ->binop
sw(iexp):
      outstring("(int)")
sw(REXP):
      outstring("pow(")
      outopnd(trip_opnd1,mode&x'ff00')
      outstring(",")
      outopnd(trip_opnd2,mode&x'ff00')
      outstring(")")
      ->wayout
sw(RSTORE):
!     printstring("Rstore:")
      if ADD<=trip_x1<=SUB and 0<=trip_opnd2_flag<=1 andc
          trip_opnd2_d=1 and trip_opnd1_ptype&x'ff00'=0{not pointer}start
         outopnd(trip_opnd1,mode&x'ff00')
         if trip_x1=ADD then outstring("++") else outstring("--")
         ->wayout
      finish
      op=rsassop(trip_x1); ->assop
sw(VASS):sw(VJASS):
      op="="
assop:
      outopnd(trip_opnd1,mode&x'ff00'!2)
      outstring(op)
      outopnd(trip_opnd2,mode&x'ff00'!0)
      ->wayout
sw(NOTL): op="~"; opl="not"
unaryop:
       if doinglabel#0 then outstring(opl) else outstring(op)
       outopnd(trip_opnd1,mode&x'ff00'!trip_opnd1_flag>>3&1)
      ->wayout
sw(LNEG):
      op="-"; opl="uminus"; ->unaryop
sw(IFLOAT):
      if trip_opnd1_flag=SCONST start
           trip_opnd1_ptype=x'62'
           begin
           longreal x;
           x=trip_opnd1_d
           trip_opnd1_d=integer(addr(x))
           trip_opnd1_xtra=integer(addr(x)+4)
           end
           op=""
           ->unaryop
      finish
      op="(double)"; ->unaryop
sw(SHRTN):sw(LNGTHN):sw(JAMSHRTN):sw(NULLT):sw(PRELOAD):
      outopnd(trip_opnd1,mode&x'ff00'!0)
end {outtriple }
         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,form
            EXPHEAD = 0; EXPBOT = 0
            NOPS = 0; Form=0
            P = P+3
            if a(p)=4 and a(P+1)=3 then Form=1   { Bracketed expr }
            TORP(EXPHEAD,EXPBOT,NOPS,0)
            EXPOP(EXPHEAD,EXPBOT,NOPS,MODE&x'ffff')
!            tripopt(triples,triples(0)_flink)
            outopnd(expopnd,Form! mode>>16)
         end
routine labexp
!***********************************************************************
!*    Evaluates the expression in a switch label to a valid cname      *
!*    This means operators have to be replaced by lettere              *
!***********************************************************************
      doinglabel=1
      csexp(x'51')
      doinglabel=0
end
         integer fn 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,1)
!      ->WAYOUT %unless NOPS&X'00040000'=0
            EXPOP(EXPHEAD,EXPBOT,NOPS,X'200'+PRECTYPE)
            ->WAYOUT unless EXPOPND_FLAG<=1
            RES = ADDR(EXPOPND_D)
WAYOUT:
            result = RES
         end
         integer fn INTEXP(integer name 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,1)
            EXPOP(EXPHEAD,EXPBOT,NOPS,X'200'+PRECTYPE)
            CODE = 1 unless EXPOPND_FLAG<=1 and EXPOPND_PTYPE&x'77'=PRECTYPE
            VALUE = EXPOPND_D
            ACC = SACC; PTYPE = SPTYPE
            UNPACK
            result = CODE
         end
         routine TORP(integer name HEAD,BOT,NOPS,integer mode)
!***********************************************************************
!*       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     *
!*    mode # 0 if const expressions to be evaluated                    *
!***********************************************************************
            switch OPERAND(1:3)
            const byte integer array PRECEDENCE(0:20)=0,3,3,4,5,5,4,3,3,4,4,5,5,3,5,5,
                                        0(3),3,5

            const byte integer array OPVAL(0:20)=0,ADD,SUB,ANDL,IEXP,REXP,MULT,NONEQ,
                  ORL,INTDIV,REALDIV,RSHIFT,LSHIFT,ADD,IEXP,REXP,0(3),LNEG,NOTL

            integer RPHEAD,PASSHEAD,SAVEHEAD,REAL,REALOP,OPERATOR,OPPREC,
               OPND,C,D,E,BDISP,OPNAME,OPMASK,RPBOT,OPSTK,OPPSTK,PASSBOT,PIN
            record (TAGF) name LCELL
            record (RD) RPOP
!
            PASSHEAD = 0; RPHEAD = 0; SAVEHEAD = 0
            REAL = 0; REALOP = 0; BDISP = 0
            RPBOT = 0; OPSTK = 0; OPPSTK = 0
            PIN=p
!
            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
            RPOP = 0
            ->OPERAND(OPND);             ! SWITCH ON OPERAND
OPERAND(1):                              ! NAME
            OPNAME = A(P)<<8+A(P+1)
            LCELL == ASLIST(TAGS(OPNAME))
            LCELL_UIOJ <- LCELL_UIOJ!X'8000';  ! SET USED BIT
            PTYPE = LCELL_PTYPE
            TYPE = PTYPE&7; PREC = PTYPE>>4&15
            if PTYPE=X'FFFF' then PTYPE = X'51';    ! NAME NOT SET
            if PTYPE=SNPT then PTYPE = LCELL_ACC and UNPACK
            if (mode#0 or string(addr(worka_lett(word(opname))))="pi") c
               and PTYPE&X'FF00'=X'4000' and A(P+2)=2=A(P+3) and 1<=TYPE<=2 then start
                                         ! CONST VAR
               RPOP_D = LCELL_S2; RPOP_XTRA = LCELL_S3
               RPOP_FLAG = 1; PTYPE = PTYPE&255
               if TYPE=1 and PREC<=5 and X'FFFF8000'<RPOP_D<=X'7FFF' then c
                  RPOP_FLAG = 0 and PTYPE = MINAPT
               REAL = 1 if TYPE=2
               P = P+2; ->SKNAM
            finish
            RPOP_XTRA = OPNAME
            RPOP_FLAG = ARNAME; RPOP_D = P; PTYPE = X'51' if PTYPE=X'57'
            if TYPE=3 then start
               D = P; KFORM = LCELL_KFORM
               C = COPY RECORD TAG(E); P = D;
            finish
            if TYPE=5 then FAULT(76,0,OPNAME) and RPOP_FLAG = 0 and c
               PTYPE = X'51'
            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 RPOP_FLAG=ARNAME then OPMASK = OPMASK!1<<18
            if PTYPE>>4&15>5 then OPMASK = OPMASK!1<<17;    ! CONTINS LONG
            if 3<=PTYPE&7<=7 then PTYPE = X'51';    ! NOT SET TO INTEGER
            RPOP_PTYPE <- PTYPE
            BINSERT(RPHEAD,RPBOT,RPOP_S1,RPOP_D,RPOP_XTRA)
            ->OP
OPERAND(2):                              ! CONSTANT
            PTYPE = A(P); D = PTYPE>>4
            C = PTYPE&7
            if (PTYPE=x'61' and 1<<TARGET&LINTAVAIL=0) or c
               (D=7 and c=2 and 1<<TARGET&LLREALAVAIL=0) then FAULT(99,0,0)
            if D>=6 then OPMASK = OPMASK!1<<17;    ! MORE THAN 32 BIT OPERAND
            if D=4 or d=3 then start
               d=4; RPOP_D = FROM AR2(P+1)
!               PTYPE = ptype&8!X'51'
            finish else RPOP_D = FROM AR4(P+1)
            REAL = 1 if C=2; RPOP_FLAG = 1
            if D=6 then RPOP_XTRA = FROM AR4(P+5)
            if C=5 then start;           ! STRING CONSTANT
               FAULT(77,0,0); RPOP_D = 1; RPOP_FLAG = 0
               P = P+A(P+1)+3; PTYPE = X'51'
            finish else start
               if D=7 then RPOP_XTRA = RPOP_D and RPOP_D = P+1
               if PTYPE=X'51' and X'FFFF8000'<=RPOP_D<=X'7FFF' then c
                  RPOP_FLAG = 0 and PTYPE = MINAPT
               P = P+2+BYTES(D)
            finish; ->INS
OPERAND(3):                              ! SUB EXPRESSION
            PASSHEAD = 0; PASSBOT = 0
            P = P+3
            TORP(PASSHEAD,PASSBOT,NOPS,mode)
            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
            RPOP = 0
            ->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=REALDIV 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
               RPOP_FLAG = OPVAL(OPSTK&31)
               BINSERT(RPHEAD,RPBOT,RPOP_S1,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
               RPOP_FLAG = OPVAL(OPSTK&31)
               BINSERT(RPHEAD,RPBOT,RPOP_S1,0,0)
               OPSTK = OPSTK>>5
            repeat
            PTYPE = REAL+1
            TYPE = PTYPE
!         CONCAT(RPHEAD,HEAD)
            if HEAD=0 then BOT = RPBOT else ASLIST(RPBOT)_LINK = HEAD
            HEAD = RPHEAD;               ! HEAD BACK TO TOP OF LIST
            NOPS = NOPS!OPMASK
         end
         routine EXPOP(integer name 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          *
!***********************************************************************
            routine spec PSEVAL
!
            integer array 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,CURR TRIP,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
!
            const half integer array CORULES(0:20)= c
                                        X'1FF'{+},X'FF'{-},
                                        X'1F1'{!!},X'1F1'{!},
                                        X'1FF'{*},X'F1'{//},
                                        X'F2'{/},X'1F1'{&},X'71'{>>},
                                        X'71'{<<},X'43'{**},
                                        X'1FF'{COMP},X'FF'{DCOMP},
                                        X'21'{VMY},X'1F1'{COMB},
                                        X'14'{ASSIGN=},
                                        X'54'{ASSIGN<-},X'71'{****},
                                        X'01'{ARR BADJ},
                                        X'001'{ARR INDEX},
                                        X'100'{INDEXED FETCH}

            const integer array PTYPECH(0:19)=0(12),X'11',0,-X'10',X'10',-X'10',0(3)


!
            STPTR = 0; CONSTFORM = MODE&512
            INITTRIP = NEXTTRIP
            CONDFORM = MODE&256
            SAVEP = P
            INHEAD = HEAD
            PSEVAL
NEXT:       LIST == ASLIST(INHEAD)
            XTRA = LIST_S2
            JJ = LIST_FLAG; 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
            IMPABORT 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 JJ>=128 then start
               OPND2 == ASLIST(OPERAND(2))

            finish else OPND2 == RECORD(0)
! next line must be wrong 32 is not dsided
!            %if JJ=32 %then COMM = 2;    ! DSIDED RESULT=2ND OPERAND
                                         ! ALL OTHERS RESULT=1ST OPERAND
            if JJ<128 then C = 0 else C = CORULES(JJ-128)
            if JJ=VASS or JJ=VJASS then KK = 1 else KK = 2
                                         ! CNAME FETCH-STORE
!            %if OPND1_FLAG=ARNAME %and (LHSADDRFIRST=YES %or KK=2) %start
!                                         ! EXPAND UP NAMES BUT NOT LHS
!                                         ! ASSIGNMENT NAMES
!               P = OPND1_D; CNAME(KK)
!               OPND1 = NAMEOPND
!            %finish
!            %if JJ>=128 %and OPND2_FLAG=ARNAME %then %start
!               P = OPND2_D
!               CNAME(2)
!               OPND2 = NAMEOPND
!            %finish
!            %if OPND1_FLAG=ARNAME %then %start
!               P = OPND1_D
!               CNAME(KK)
!               OPND1 = NAMEOPND
!            %finish
            if constform#0 and 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
               CURR TRIP = NEW TRIP
               CURRT == TRIPLES(CURR TRIP)
               CURRT_DPTH = 0;           ! LEAVE DEPTHS TO BE WORKED OUT IN%c
                                         OPT PASS
               CURRT_CNT = 0
               CURRT_FLAGS = 1!(C>>1&128)
               CURRT_OPERN = JJ
               CURRT_OPTYPE <- OPND1_PTYPE
               if 12<=JJ<=16 start;      ! UNARY(TYPECHANGE)OPN
                  CURRT_OPTYPE <- XTRA; XTRA = 0
               finish else if c
                  OPND1_PTYPE&7=1 and OPND1_PTYPE&255<MINAPT then c
                  CURRT_OPTYPE = MINAPT
                                         ! PREVENT OPTIMISING BYTE ARRAY SCALE
                                         ! AS THESE CREATE EXTRA WORD
                                         ! WHICH DEFEATS ALGORITHMS
               if (TARGET=PERQ or TARGET=ACCENT or TARGET=PNX) and c
                  JJ=39 and XTRA>>20=1 then c
                  CURRT_FLAGS <- CURRT_FLAGS!DONT OPT
               CURRT_X1 = XTRA
               CURRT_OPND1 = OPND1
               if 1<<OPND1_FLAG&BTREFMASK#0 then KEEP USE COUNT(OPND1)
               if JJ>=128 then start
                  CURRT_OPND2 = OPND2
                  if 1<<OPND2_FLAG&BTREFMASK#0 then KEEP USE COUNT(OPND2)
               finish
               OPND1_FLAG = 8
               OPND1_PTYPE = CURRT_OPTYPE
               OPND1_D = CURR TRIP
            finish
            STK(STPTR) = OPERAND(COMM)
            STPTR = STPTR+1
            ->ANYMORE
FINISH:
!            %if EXPOPND_FLAG=ARNAME %then %start
!               P = EXPOPND_D
!               CNAME(2)
!               EXPOPND = NAMEOPND
!            %finish
            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                                           *
!***********************************************************************
               routine spec AMEND(record (RD) name OPND, integer OP)
               routine spec COERCET(integer RULES)
               routine spec COERCEP(integer RULES)
               integer TMPHEAD,INHEAD,C,JJ,NEXT
               record (RD) name OPND1
               record (RD) OPND2,RPOP
               record (LISTF) name CELL
               PRINT LIST(HEAD) and IMPABORT unless ASLIST(BOT)_LINK=0
               RPOP = 0
               TMPHEAD = 0
               INHEAD = HEAD
!
               while INHEAD#0 cycle
                  CELL == ASLIST(INHEAD)
                  NEXT = CELL_LINK
                  RPOP <- CELL;          ! COPY BEFOR ADJUSTING PTYPE
                  JJ = RPOP_FLAG;        ! FLAG
                  if JJ<10 start;        ! AN OPERAND
!            %if RPOP_PTYPE>>4&15<MINAPREC %then RPOP_PTYPE%c
=RPOP_PTYPE&X'FF0F'!(MINAPREC<<4)
                     PUSH(TMPHEAD,RPOP_S1,RPOP_D,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-128)
                        if JJ=REXP and OPND2_PTYPE&7=2 then C = X'F2'
                                         ! REAL TO THE REAL
                        if C&15#0 then COERCET(C&15)
                        if C>>4&15#0 then COERCEP(C>>4&15)
                     else
                        OPND1 == ASLIST(TMPHEAD)
                        if JJ=MODULUS start
                           if OPND1_PTYPE&7=1 and RPOP_D&7=2 then COERCET(3)
                           if OPND1_PTYPE>>4&15<RPOP_D>>4&15 then c
                              AMEND(OPND1,LNGTHN)
                           if OPND1_PTYPE>>4&15>RPOP_D>>4&15 then c
                              AMEND(OPND1,SHRTN)
                         else
                            if jj<19 then opnd1_ptype=opnd1_ptype+ptypech(jj)
                        finish
                     finish
                     OPND1_XTRA = INHEAD;  ! IN CASE(FURTHER)TYPE CHANGE
                  finish
                  INHEAD = NEXT
               repeat
!
! FINAL COERCION ON RESULT
!
               POP(TMPHEAD,OPND2_S1,OPND2_D,OPND2_XTRA)
               PRINT LIST(HEAD) and IMPABORT 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 AMEND(OPND2,IFLOAT)
                  C = MODE>>4&15;        ! TARGET PREC
                  AMEND(OPND2,SHRTN) while C<OPND2_PTYPE>>4&15
                  AMEND(OPND2,LNGTHN) while C>OPND2_PTYPE>>4&15
               finish
               PRINTLIST(HEAD) if PARM_DCOMP#0 and PARM_Z#0
               BOT = ASLIST(BOT)_LINK while ASLIST(BOT)_LINK#0
               return
               routine AMEND(record (RD) name OPND, integer OP)
!***********************************************************************
!*    ADDS IN AN OPERATION TO CHANGE THE TYPE OR PREC OF OPND          *
!*     On E machines we can not elide uneceesary changes               *
!***********************************************************************
                  record (RD) RPOP
                  if 1<<target&Emachine=0 and OP=LNGTHN and OPND_PTYPE&255<MINAPT then c
                     OPND_PTYPE <- OPND_PTYPE&X'FF00'!MINAPT and return
                  RPOP = 0
                  RPOP_FLAG = OP
                  if OP=IFLOAT and OPND_PTYPE&255<MINAPT then c
                     OPND_PTYPE = MINAPT
                  OPND_PTYPE = OPND_PTYPE+PTYPECH(OP)
                    if 1<<target&Llrealavail=0 and op=ifloat c
                       and Opnd_ptype&255=X'72' then OPnd_ptype=opnd_ptype-x'10'
                                       ! float longinteger when longlongreal not available
                  INSERT AFTER(OPND_XTRA,RPOP_S1,OPND_PTYPE,0)
                  NOPS = NOPS+1
               end
               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
                  record (RD) RPOP
                  RPOP = 0; RPOP_FLAG = 12;  ! FLOAT
                  PT1 = OPND1_PTYPE&7;
                  PT2 = OPND2_PTYPE&7; if PT2=7 then PT2=1
                  if RULES=4 then PT1 = CELL_S2&7;    ! ORIGINAL PT FOR ARRAYS%c
                                                      ETC
                  if PT1=7 then PT1=1
                  if (RULES=1 or RULES=15 or RULES=4) and PT1=1=PT2 then c
                     return
                  if RULES=1 or (RULES=4 and PT1=1) then c
                     FAULT(24,0,0) and return
                  if PT1=1 then AMEND(OPND1,IFLOAT)
                  if PT2=1 and (RULES=2 or RULES=4 or RULES=15) then c
                     AMEND(OPND2,IFLOAT)
               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=7 OPND1>=32BITS, OPND2 TO BE 'STANDARD'                 *
!*       RULES=15 BOTH OPERANDS TO THE LARGEST PRECISION               *
!***********************************************************************
                  integer PREC1,PREC2,TPREC,OPER
                  record (RD) name OPND
                  record (RD) RPOP
                  RPOP = 0
                  if RULES=6 then COERCEP(4) and RULES = 2
                  PREC1 = OPND1_PTYPE>>4&15
                  PREC2 = OPND2_PTYPE>>4&15
                  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 OPER = SHRTN else OPER = JAMSHRTN
                           AMEND(OPND2,OPER)
                           PREC2 = PREC2-1
                        repeat until PREC1=PREC2
                        return
                     finish else RULES = 1;    ! IN CASE LENGTHEN NEEDED
                  finish
                  if PREC1<MINAPREC then c
                     PREC1 = MINAPREC and c
                     OPND1_PTYPE <- OPND1_PTYPE&X'FF0F'!(MINAPREC<<4)
                  if PREC2<MINAPREC then c
                     PREC2 = MINAPREC and c
                     OPND2_PTYPE <- OPND2_PTYPE&X'FF0F'!(MINAPREC<<4)
                  if RULES=7 start;      ! FORCE SHIFT INTO 32 BIT MIN REG
                     RULES = 4
                     if PREC1=4 then AMEND(OPND1,LNGTHN) and PREC1 = 5
                  finish
                  if 2<=RULES<=4 start
                     if RULES<=2 then OPND == OPND1 else OPND == OPND2
                     if OPND_PTYPE&X'FF'>MINAPT then AMEND(OPND,SHRTN)
                     return
                  finish
                  if PREC1<PREC2 then c
                     TPREC = PREC2 and OPND == OPND1 else c
                     TPREC = PREC1 and OPND == OPND2
                  OPER = OPND_PTYPE
                  AMEND(OPND,LNGTHN) while OPND_PTYPE>>4&15<TPREC
               end
            end
         end;                            ! OF ROUTINE EXPOP
         integer fn 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
            routine spec SKIP SC(integer REVERSED)
            routine spec SKIP COND(integer REVERSED)
            integer fn spec CCOMP
            routine spec JUMP(integer MASK,LAB,FLAGS)
            routine spec NOTE JUMP(integer LAB)
            routine spec LAB UNUSED(integer LAB)
            routine spec 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
            record format CF(byte integer TF,CMP1,CMP2,LABU,LVL,JMP,REV,
               JUMPED, integer LABNO,SP1,SP2,sp3)
            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

{GT:} ! Would be nice to apply de-morgan's law below and invert the actual
      ! conditional tests, eg
      !        a=1 %and b>fred
      ! ->     a#1 %or b<=fred
      ! 
      ! Since Imp80 has no %predicates, we don't need to re-insert any "!"s
      ! at a lower level, except for conditional string resolution, i.e.
      !       a->a.("->").b
      ! ->    (%not a->a.("->").b)
      ! 
      ! If we add this as a general mechanism, then when translating to
      ! C we can clean up 'unless' and 'repeat until' statements, which map
      ! to C's if and while statements.
      !
      ! Also it would be useful in my %if <cond> %then %monitor
      ! extension, which maps to assert(!(<cond>))
      !
      ! NOTE: ** it would appear SKIP SC(1) and SKIP COND()
      ! do exactly what I want here!
      !
!           %if iu=2 %then outstring("(!")
            outsym('(')
            if iu=2 then start
              SKIP SC(1);                  ! SKIP THE 1ST CMPARSN
              SKIP COND(1);                ! AND ANY %and/%or CLAUSES
            else
              SKIP SC(0);                  ! SKIP THE 1ST CMPARSN
              SKIP COND(0);                ! AND ANY %and/%or CLAUSES
            finish
            outstring(") ")
!           %if iu=2 %then outsym(')')
            result=0
routine SKIP SC(integer REVERSED)
!***********************************************************************
!*       REVERSED=1 FOR RECURSIVE CALL IN %not(SC)                     *
!*       SKIPS OVER A SIMPLE CONDITION. P ON ALT OF<SC>                *
!***********************************************************************

!
! In Imp to C translator we do NOT generate jumps so the logic
! for REVERSED which changes the jump destinations does not
! do anything.  Instead we must explicity apply de-morgan's
! law to the operands and operators.  I am in the process
! of adding that code now.  SKIP COND is done already

conststring(5) array CMP(0:10)=" ??? ","==",">=",">",
                       "!=","<=","<","!=","?->??",
                       "==","!="

conststring(6) array REVCMP(0:10)=" ??? ","!=","<","<=",
                       "==",">",">=","==","!?->??",
                       "!=","=="

switch SCALT(1:4)
integer ALT,TE1,TE2,PRECP,TYPEp,finalp,rexp
      ALT = A(P); P = P+1
      ->SCALT(ALT)
SCALT(1):                                ! <EXP><COMP><EXP><SECONDSIDE>
      C1_SP1 = P
      te1=tsexp(TE2)
      typep=type; precp=prec
      p = c1_sp1             { tsexp may not reset p }
      SKIP EXP
      C1_CMP1 = A(P)
      C1_REV = 3*REVERSED
      P = P+1; C1_SP2 = P
      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; C1_SP3=P; SKIP EXP
      finish
      finalp=p
!      outsym('(') %unless a(finalp)=3
      if typep=5 start
         p=c1_sp1
         if c1_cmp1=8 start
           outstring("imp_resolve(")
           p=p+5; cname(2)
            outsym(',')
           p=c1_sp2; cres(1)
           if REVERSED=1 then start
             outstring(")!=0"); ! De-Morgan's law
           else
             outstring(")==0")
           finish
           if c1_cmp2#0 then outstring("untranslateable cond")
        else
            if c1_cmp2#0 then outsym('(')
            outstring("strcmp(")
            cstrexp(0)
            outsym(',')
            p=c1_sp2; cstrexp(0)
            outsym(')')
            if REVERSED=1 then start
              outstring(REVcmp(c1_cmp1)); ! de-morgan's law
            else
              outstring(cmp(c1_cmp1))
            finish
            outsym('0')
            if c1_cmp2#0 then start
               if REVERSED=1 then start
                  outstring(") || ("); ! De-Morgan's Law
               else
                  outstring(") && (")
               finish
               p=c1_sp2; cstrexp(0)
               outsym(',')
               p=c1_sp3
               cstrexp(0)
               outsym(')')
            finish
        finish
      else
         if c1_cmp2#0 then outsym('(')
         p=c1_sp1
         REXP = 2-A(P+1+FROM AR2(P+1))
         if rexp#0 then outsym('(')
         if c1_cmp1>8 then p=p+5 and cname(4) else csexp(precp<<4!typep!256)
         if rexp#0 then outsym(')')
         if REVERSED=1 then start
            outstring(REVcmp(c1_cmp1)); ! DeMorgan's law
         else
            outstring(cmp(c1_cmp1))
         finish
         p=c1_sp2
         REXP = 2-A(P+1+FROM AR2(P+1))
         if rexp#0 then outsym('(')
         if c1_cmp1>8 then p=p+5 and cname(4) else csexp(precp<<4!typep!256)
         if rexp#0 then outsym(')')
         if c1_cmp2#0 start
            if REVERSED=1 then start
               outstring(") || (")
            else
               outstring(") && (")
            finish
            if rexp#0 then outsym('(')
            p=c1_sp2; csexp(precp<<4!typep)
            if rexp#0 then outsym(')')
            if REVERSED=1 then start
               outstring(REVcmp(c1_cmp1)); ! DeMorgan's law
            else
               outstring(cmp(c1_cmp2))
            finish
            p=c1_sp3
            REXP = 2-A(P+1+FROM AR2(P+1))
            if rexp#0 then outsym('(')
            csexp(precp<<4!typep)
            if rexp#0 then outsym(')')
            outsym(')')
         finish
      finish
      p=finalp
!      outsym(')') %unless a(finalp)=3
      return
SCALT(2):                                ! '('<SC><RESTOFCOND>')'
      outsym('(')
      L = L+1
      SKIP SC(REVERSED)
      SKIP COND(REVERSED)
      L = L-1
      outsym(')')
      return
SCALT(3):                                ! %not(SC)
{GT:}!outstring("!(")
     ! now that SKIP SC and SKIP COND reverse properly,
     ! we do not need to negate here as well...
      SKIP SC(REVERSED!!1)
     !outsym(')')
      return
SCALT(4):
      if REVERSED=1 then outstring("/* what is a pseudo-boolean? - is the conditio accidentally inverted? */");
      csexp(x'51');             ! single pseudo boolean expr
   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)
{GT: experimenting with reversing}

                     if REVERSED=1 then start
                       ! Apply de-morgan to operators
                       if alt=1 then outstring(" || ") else outstring(" && ")
                     else
                       if alt=1 then outstring(" && ") else outstring(" || ")
                     finish


                     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
         end;                            ! OF CCOND
         integer fn 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

         integer fn ENTER LAB(integer LAB,FLAGS)
         result=0
         end
         routine ENTER JUMP(integer TFMASK,LAB,FLAGS)
         end
         routine REMOVE LAB(integer LAB)
         end
         integer fn CREATE AH(integer MODE, record (RD) name EOPND,NOPND)
!***********************************************************************
!*       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*
!***********************************************************************
            integer JJ
            JJ = BRECTRIP(AHADJ,AHEADPT,0,EOPND,NOPND)
            TRIPLES(JJ)_X1 = PTYPE<<4!MODE
            result = JJ
         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)                          *
!*       64=%longintegerfn LINT(%longlongreal X)                       *
!*       65=%longintegerfn LINTPT(%longlongreal X)                     *
!*       66=%shortintegermap SHORTINTEGER(%integer N)                  *
!*       67=%integerfn TRUNC(%longreal X)                              *
!***********************************************************************
integer fn spec OPTMAP
switch ADHOC(0:67)

const string(80) array SMDETAILS(0:NO OF SNS) = c
  /* 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)",
  /* 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)",
  /* 45 */ "%byteintegermap CHARNO(%stringname STR,%integer CHARREQD)",
  /* 46 */ "%string(1)",
  /* 47 */ "%string(255)",
  /* 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)",
  /* 64 */ "%longintegerfn LINT(%longlongreal X)",
  /* 65 */ "%longintegerfn LINTPT(%longlongreal X)",
  /* 66 */ "%shortintegermap SHORTINTEGER(%integer N)",
  /* 67 */ "%integerfn TRUNC(%longreal X)"


const integer array 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',
        X'11110024',X'11110024',X'2100003E',X'11040024'


const string (13) array SNXREFS(0:20)= c
      "s#readstring", "s#read",   "s#iarcsin", "s#int",
      "s#intpt" , "s#fracpt", "s#print" , "s#printfl",
      "s#iarccos","sqrt" , "log"  , "sin",
      "cos"  , "tan"  , "exp"  , "s#closestream",
      "s#iradius","atan2","imp_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.
!
            if PARAMS BWARDS=YES then start
   const integer array SNPARAMS(0:25)=0{NO PARAMS},
   8<<16!1,LRLPT{%LONGREAL X},
   16<<16!2,8<<16!LRLPT,LRLPT{%LONGREAL X,Y},
   12<<16!2,12<<16!LRLPT,4<<16!X'51'{%LONGREAL X,%INTEGER I},
   16<<16!3,8<<16!LRLPT,4<<16!X'51',X'51'{%LONGREAL X,%INTEGER I,J},
   8<<16!1,X'435'{%STRINGNAME S},
   16<<16!3,8<<16!X'435',4<<16!X'51',X'51'{%STRINGNAME S,%INTEGER I,J},
   8<<16!1,X'400'{%NAME X},
   4<<16!1,X'51'{%INTEGER I},
   8<<16!2,4<<16!X'51',X'51'{%INTEGER I,J}
 finish else start
   const integer array SNPARAMS(0:25)=0{NO PARAMS},
   8<<16!1,LRLPT{%LONGREAL X},
   16<<16!2,LRLPT,8<<16!LRLPT{%LONGREAL X,Y},
   12<<16!2,LRLPT,8<<16!X'51'{%LONGREAL X,%INTEGER I},
   16<<16!3,LRLPT,8<<16!X'51',12<<16!X'51'{%LONGREAL X,%INTEGER I,J},
   8<<16!1,X'435'{%STRINGNAME S},
   16<<16!3,X'435',8<<16!X'51',12<<16!X'51'{%STRINGNAME S,%INTEGER I,J},
   8<<16!1,X'400'{%NAME X},
   4<<16!1,X'51'{%INTEGER I},
   8<<16!2,X'51',4<<16!X'51'{%INTEGER I,J}
 finish
!
const byte integer array WRONGZ(0:15)=27,29,23,29,29,23,82,109(5),
                            23,27,109(2)

routine spec RTOS
integer fn spec CIOCP(integer N, record (RD) name PARAM)
record (LISTF) name LCELL
record (LISTF) PCELL
record (RD) OPND,OPERATOR
record (TRIPF) name CURRT
string (31) SNXREF
integer ERRNO,FLAG,POINTER,PIN,SNNO,SNNAME,NAPS,SNPTYPE,JJ,XTRA,
   IOCPEP,B,D,SNINF,P0,OPHEAD,ERRVAL,EXPHEAD,EXPBOT,formatname,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
      if snptype&255=x'61' and 1<<Target&LINTAVAIL=0 then c
         errno=99 and ->errexit
!
! 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.
!
      ->adhoc(snno)
adhoc(47):                                   ! substring
         outstring("imp_substring(")
      p=p+1; cstrexp(0); outsym(',')
      p=p+1; csexp(x'51'); outsym(',')
      p=p+1; csexp(x'51'); outsym(')');
      p=p+1; ->OKEXIT
adhoc(24):                                   ! arccos
adhoc(25):                                   ! sqrt
adhoc(26):                                   ! log
adhoc(27):                                   ! sin
adhoc(28):                                   ! cos
adhoc(29):                                   !tan
adhoc(30):                                   ! exp
      SNXREF = SNXREFS(XTRA)
      P0 = SNPARAMS(POINTER)
      if TARGET=PERQ or TARGET=ACCENT then start
         JJ = ADDR(SNXREF)
         D = LENGTH(SNXREF)
         MOVE BYTES(D+1,JJ,0,ADDR(A(0)),WORKA_ARTOP)
         JJ = ADDR(A(WORKA_ARTOP))-ADDR(A(WORKA_DICTBASE))
         WORKA_ARTOP = (WORKA_ARTOP+D+4)&(-4)
      finish else CXREF(SNXREF,3*PARM_DYNAMIC,P0<<16!P0>>16,JJ)
                                ! JJ SET WITH REF DISPLACEMENT
      OPHEAD = 0
      K = OPHEAD; D = 1
      while D<=P0&15 cycle
         B = SNPARAMS(POINTER+D)
         PTYPE = B&X'FFFF'
         UNPACK
         if NAM=0 then ACC = BYTES(PREC) else ACC = 8
         if PTYPE=X'35' then ACC = 256;    !STRING BY VALUE
         PCELL = 0;             ! SET UP PARAMETER DESC VIA RECORD
         PCELL_PTYPE <- PTYPE;  ! FOR CONSISTENCY ON BYTE SWOPPED%c
                                HOSTS
         PCELL_SNDISP = B>>16
         PCELL_ACC <- ACC
         if PARAMS BWARDS=YES then c
            PUSH(OPHEAD,PCELL_S1,PCELL_S2,0) else c
            INSERTAT END(OPHEAD,PCELL_S1,PCELL_S2,0)
         D = D+1
      repeat
      if P0>0 then ASLIST(OPHEAD)_S3 = P0;    ! INSERT NO OF PARAMS
                                ! UPPER PART OF P0(TOTAL PARAMSPACE)
                                ! APPARENTLY NOT NEEDED AS NO BODIES
                                ! ARE PROVIDED.
      LCELL == ASLIST(TAGS(SNNAME))
      LCELL_PTYPE = SNPTYPE
      LCELL_UIOJ = 1<<4!14;     ! I=1 & J=14
      LCELL_SNDISP <- JJ;       ! RT ENTRY DISPLACEMENT
      LCELL_ACC = BYTES(SNPTYPE>>4&15)
      LCELL_SLINK = OPHEAD
      LCELL_KFORM = 0;          ! KFORM(=FORMAT INFO)
      P = PIN; CNAME(Z);        ! RECURSIVE CALL
      P = P-1; return;          ! DUPLICATES CHECK OF <ENAME>
ADHOC(6):ADHOC(7):                       ! NEWLINES(=6) & SPACES(=7)
      if parm_arr=0 start
         if snno=6 then outstring("_imp_newlines(") else outstring("_imp_spaces(")
         p=p+1; csexp(x'51')
         outsym(')')
         p=p+1
         ->OKEXIT
      finish
      p=p+1
      if tsexp(jj)>0 and jj>0 start
{GT:}    outstring("fprintf(out_file, "); outsym('"')
         for xtra=1,1,jj cycle
            if snno=6 then outstring("¬n") else outstring(" ")
        repeat
         outsym('"'); outsym(')')
      else
         p=PIN+3
         outstring("{ for (_imptempint=1; _imptempint<=")
         csexp(x'51')
         outstring("; _imptempint++) fprintf(out_file, "); outsym('"')
         if snno=6 then outstring("¬n") else outstring(" ")
         outsym('"')
         outstring(");}")
      finish
      P = P+1
      ->OKEXIT
ADHOC(37):                                  ! printstring
      if parm_arr=0 then start
        outstring("_imp_printstring(")
      finishelsestart
{GT:}   outstring("fprintf(out_file, "); outsym('"'); outstring("%s")
        outsym('"'); outstring(", ")
      finish
      p=p+1
      cstrexp(0)
      outstring(")")
      P=P+1; ->OKEXIT
adhoc(2):                                   ! newline
      if parm_arr=0 start
         outstring("_imp_newlines(1)")
      else
{GT:}    outstring("fprintf(out_file, "); outsym('"'); outstring("%s")
         outsym('"'); outstring(", "); outsym('"'); outsym('¬')
         outsym('n'); outsym('"');outsym(')')
      finish
      P=P+1; ->OKEXIT
adhoc(3):                                        ! space
      if parm_arr=0 start
         outstring("_imp_spaces(1)")
      else
{GT:}    outstring("fprintf(out_file, "); outsym('"'); outstring("%s")
         outsym('"'); outstring(", "); outsym('"'); outsym(' ')
         outsym('"'); outsym(')')
      finish
      P=P+1; ->OKEXIT
adhoc(21):                                  ! real
adhoc(22):                                  ! integer
adhoc(61):                                  ! halfinteger
adhoc(66):                                  ! shortinteger
adhoc(39):                                  ! longreal
adhoc(32):                                  ! byteinteger
adhoc(54):adhoc(55):                         ! long int & longlongreal
      outstring("(*(")
      outtype(snptype&255,0)
      outstring(" *)(")
      p=p+1; csexp(x'51')
      outstring("))")
      P=P+1; ->OKEXIT
adhoc(42):                                  ! string
      outstring("((char *)")
      p=p+1; csexp(x'51')
      outstring(")")
      P=P+1; ->OKEXIT
adhoc(45):                                   ! charno
{GT: Needs special handling for charno(s,0); also for LHS = ..}
      if z#2 then warn(10,0)
      p=p+1; cstrexp(0)
      outsym('[')
      p=p+1; csexp(x'51')
      outstring("-1]")
      p=p+1
      ->OKexit
ADHOC(36):                               ! length
{GT: Also needs special treatment on LHS }
      if z#2 then warn(10,0)
      outstring("strlen(")
      p=p+1; cstrexp(0)
      outstring(")")
      P=P+1; ->OKEXIT
adhoc(46):                                  ! tostring
      outstring("imp_tostring(")
      p=p+1; csexp(x'51')
      outstring(")")
      P=P+1; ->OKEXIT
ADHOC(9): adhoc(40):                      ! printsymbol & printch
      if parm_arr=0 start
         outstring("_imp_printsymbol(")
      else
{GT:}    outstring("fprintf(out_file, ");
         outsym('"')
         outstring("%c")
         outsym('"');
         outstring(", ");
      finish
      p=p+1; csexp(x'51')
      outstring(")")
      P = P+1
      ->OKEXIT
ADHOC(12):                               ! write
      if parm_arr=0 start
         outstring("_imp_write(")
         p=p+1; csexp(x'51'); outsym(',')
         p=p+1; csexp(x'51'); outsym(')')
         p=P+1; ->OKEXIT
      finish
      p=p+1; skip exp; p=p+1; jj=tsexp(xtra)
      p=PIN+2
      if jj#0 start
         outstring("fprintf(out_file, "); outsym('"'); outstring("%")
         outint(imod(xtra)+1); outstring("d"); outsym('"'); outstring(",")
      else
         outstring("fprintf(out_file, "); outsym('"'); outstring(" %d"); outsym('"'); outstring(",")
      finish
      p=p+1; csexp(x'51')
      outstring(")")
      p=PIN+2; skip app
      p=p-1; ->OKEXIT
ADHOC(19):                               ! print
      if parm_arr=0 start
         outstring("_imp_print(")
         p=p+1; csexp(x'62'); outsym(',')
         p=p+1; csexp(x'51'); outsym(',')
         p=p+1; csexp(x'51'); outsym(')')
      else
         outstring("fprintf(out_file, "); outsym('"'); outstring(" %f"); outsym('"'); outstring(",")
         p=p+1; csexp(x'62')
         outstring(")")
      Finish
      p=PIN+2; skip app
      p=p-1; ->OKEXIT
ADHOC(20):                               ! printfl
      if parm_arr=0 start
         outstring("_imp_printf(")
         p=p+1; csexp(x'62'); outsym(',')
         p=p+1; csexp(x'51'); outsym(')')
      else
         outstring("fprintf(out_file, "); outsym('"'); outstring(" %e"); outsym('"'); outstring(",")
         p=p+1; csexp(x'62')
         outstring(")")
      finish
      p=PIN+2; skip app
      p=p-1; ->OKEXIT

ADHOC(0):                               ! SELECT INPUT
      if parm_arr=0 start
         outstring("_imp_selectinput(")
         p=p+1; csexp(x'51'); outsym(')')
         p=p+1; ->OKEXIT
      finish
      ! if C i-o we can not handle this so fall thru
{GT:} 
      outstring("selectinput(")
      p=p+1; csexp(x'51'); outstring(")")
      p=p+1;
      ->OKEXIT

ADHOC(1):                               ! SELECT OUTPUT
      if parm_arr=0 start
         outstring("_imp_selectoutput(")
         p=p+1; csexp(x'51'); outsym(')')
         p=p+1; ->OKEXIT
      finish
      ! if C i-o we can not handle this so fall thru
{GT:} 
      outstring("selectoutput(")
      p=p+1; csexp(x'51'); outstring(")")
      p=p+1;
      ->OKEXIT

ADHOC(64):ADHOC(65):                      ! LINT(=64) AND LINTPT(=65)
            unless TYPEFLAG(10)&255=X'61' and TYPEFLAG(12)&255>=X'62' then c
               ERRNO = 99 and ->ERREXIT
! NEED LONGINTS&LLREALS
      outstring("((long int) floor(")
      p=p+1
      CSEXP(typeflag(12)&255);    ! LONGLONGREAL MODE or longreal if defaulted
      if SNNO=64 then outstring("+0.5")
      outstring("))")
      P = P+1
      P0 = X'61'; ->OKEXIT
ADHOC(16):ADHOC(17):                      ! INT(=16) AND INTPT (=17)
      outstring("((int) floor(")
      p=p+1
      CSEXP(LRLPT)
      if SNNO=16 then outstring("+0.5")
      outstring("))")
      P = P+1
      ->OKEXIT
ADHOC(67):                                 ! trunc
      outstring("((int)(")
      p=p+1
      CSEXP(LRLPT)
      outstring("))")
      P = P+1
      ->OKEXIT

{GT:}
ADHOC(4):                                ! SKIP SYMBOL
      outstring("(void)fgetc(in_file)")
      P = P+2 { DON'T KNOW HOW MUCH TO ALTER P BY }; ->OKEXIT

ADHOC(8):                                ! NEXT SYMBOL
      P = P+6;
      CNAME(1);
      outstring("ungetc(fgetc(in_file), in_file)")
      P = P+2; ->OKEXIT

ADHOC(10):                                ! READ SYMBOL
ADHOC(41):                                ! READ CH
      P = P+6;
      CNAME(1);
      outstring(" = fgetc(in_file)")
      P = P+2; ->OKEXIT

ADHOC(14):                                ! ADDR(=14)
      P = P+6; CNAME(4);           ! FETCH ADDRESS MODE
      P = P+2; ->OKEXIT
ADHOC(23):                                ! MOD(=23)
      outstring("fabs(")
      p=p+1
      csexp(x'62')
      outstring(")")
      P = P+1
      ->OKEXIT
ADHOC(51):                               ! imod
      outstring("abs(")
      p=p+1
      csexp(x'51')
      outstring(")")
      P = P+1
      ->OKEXIT
ADHOC(52):                               ! PI(=52)
ADHOC(38):                                ! NL(=38). THIS FN IS PICKED OFF
            P = P+1
            ->OKEXIT;                    ! ERROR EG NL=A+B
ADHOC(48):                               ! RECORD(=48)
      p=p+1
      if tsexp(jj)=1 and jj=0 start
         outstring("NULL")
      else
         if z#4 start
            outsym('(')
!            outsym('('); outtype(x'33',lhformatname)
!            outsym('*')
!            outsym(')')
         finish
         p=PIN+3
         CSEXP(X'51')
         P = P+1
         outsym(')')
      finish
      DISP = 0; BASE = 0; ACCESS = 3
      OLDI = 0; ACC = X'FFFF'
      SNPTYPE = SNPTYPE+X'1C00';   ! ADD MAP BITS
      PTYPE = SNPTYPE; UNPACK
      return
ADHOC(49):                               ! ARRAY(=49)
      p=p+1
      skip exp
      ERRNO = 22; ERRVAL = 2
      ->ERREXIT unless A(P+4)=4 and A(P+5)=1
      P = P+6; formatname=fromar2(p)
      copytag(formatname,NO)
      p=p+4
      ->ERREXIT unless A(P)=2
      xtra=p+2
      outstring("(("); outtype(ptype&255,lhformatname)
      outstring("*)(")
      p=PIN+3
      CSEXP(X'51');                ! ADDR(A(0)) TO NEST
      outstring("))")
      copytag(formatname,NO)
      P = xtra
      return
ADHOC(13):                               ! EVENTINF(=33) & EVENTLINE
            D = CURRINF_ONINF
            FAULT(16,0,SNNAME) if D=0
            D = D+4 if SNNO#33
            BASE = RBASE; ACCESS = 0
            DISP = D; SNPTYPE = SNPTYPE+X'1C00';  ! ADD MAP BITS
            ->OKEXIT
!ADHOC(14):                               ! LENGTHEN AND SHORTEN
            D = (SNNO&3)*8
            JJ = X'62517261'>>D&255
            if 1<<TARGET&LLREALAVAIL=0 and JJ=X'72' then JJ = X'62'
            if 1<<TARGET&LINTAVAIL=0 and JJ=X'61' then JJ = X'51'
            CSEXP(JJ)
            P = P+1
            NAMEOPND = EXPOPND
            ->OKEXIT
ADHOC(15):                               ! PPROFILE(IGNORED UNLESS PARM SET)
            JJ = UCONSTTRIP(PPROF,X'51',0,PROFAAD) unless PARM_PROF=0
            ->OKEXIT
!ADHOC(16):                               ! FLOAT
            CSEXP(LRLPT)
            NAMEOPND = EXPOPND
            P = P+1
            ->OKEXIT

ADHOC(*):                                ! NEXTSYMBOL(=8) & NEXTITEM(=44)
                                         ! ALSO ANY WITH NO C EQUIVALENTS
{GT:} outstring("/* Call to ");
      outstring(SMDETAILS(snno));
      outstring (" - please modify pass2.i to handle it */")
      skip app; p=p-1; -> OKEXIT

OKEXIT:                                  ! NORMAL EXIT
            PTYPE = SNPTYPE; UNPACK
            ACC = BYTES(PREC)
            return
ERREXIT:                                 ! ERROR EXIT
            FAULT(ERRNO,ERRVAL,SNNAME)
            NAMEOPND = 0; NAMEOPND_PTYPE = X'51'
            BASE = 0; DISP = 0; ACCESS = 0; AREA = 0
            PTYPE = SNPTYPE; UNPACK
            P = PIN+2; SKIP APP
            P = P-1; return
            integer fn CIOCP(integer EP, record (RD) name PARAM)
!***********************************************************************
!*    CALL IOCP PASSING A PARAMETER
!*    RETURNS THE TRIPLE NO OF THE CALL
!***********************************************************************
               record (RD) OPND
               OPND_PTYPE = MINAPT; OPND_FLAG = SCONST
               OPND_D = EP
               result = BRECTRIP(IOCPC,MINAPT,DONT OPT,OPND,PARAM)
            end
            routine RTOS
!***********************************************************************
!*       PLANTS CODE TO CONVERT A SYMBOL IN EXPOPND TO A ONE           *
!*       CHARACTER STRING IN A TEMPORARARY VARIABLE.                   *
!***********************************************************************
               integer KK,JJ
               if EXPOPND_FLAG<=1 start
                  KK = ITOS1
                  CTOP(KK,JJ,0,EXPOPND,NAMEOPND)
                  if KK=0 then NAMEOPND = EXPOPND and return
               finish
               JJ = URECTRIP(ITOS1,X'35',0,EXPOPND)
               NAMEOPND_PTYPE = X'35'; NAMEOPND_FLAG = REFTRIP
               NAMEOPND_D = JJ
            end
         end;                            ! OF ROUTINE CSNAME
         routine CANAME(integer Z,ARRP, record (RD) name HDOPND)
!***********************************************************************
!*       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,KK,PP,TYPEP,LB,
   ARRNAME,Q,PRECP,NAMINF,DVD,DVDP,PRIVOPS
record (RD) VMYOP,RPOP
record (TAGF) name LCELL
integer array HEADS,BOTS(0:12)
            NOPS = 0; HEAD1 = 0; BOT1 = 0
            PP = P; TYPEP = TYPE
            JJ = J; PTYPEP = PTYPE; PRECP = PREC; SOLDI = OLDI
            if TYPE<=2 then ELSIZE = BYTES(PRECP) else ELSIZE = ACC
            if ELSIZE>4095 or (TYPE=5 and NAM#0) then ELSIZE = 0
            DVD = SNDISP;                ! LOCATION OF DV IF CONSTANT
            VMYOP_FLAG = 0; VMYOP_XB = 0
            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
            if DVD>0 then VMYOP_PTYPE = X'51' and VMYOP_D = DVD else c
               VMYOP = HDOPND
            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
               LCELL == ASLIST(TCELL)
               LCELL_UIOJ = LCELL_UIOJ!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.
!
!
! NOW PROCESS THE SUBSCRIPTS CALLING TORP TO CONVERT THE EXPRESSIONS
! TO REVERSE POLISH AND ADDING THE EXTRA OPERATIONS.
!
               P = PP+3
               cycle KK = 1,1,JJ;        ! THROUGH THE SUBSCRIPTS
                  heads(kk)=p; skip exp
                  P = P+1
               repeat
               pp=p; outstring(" [")
               DVDP=DVD+3*jj
               cycle KK = jj,-1,1
                  p=heads(kk); csexp(x'51')
                  LB=Ctable(DVDP)
                  if DVD#0 start    { we know how to adjust bounds }

!GT: remove the correction for the lower bound from array accesses
!    because we now do the correction at the point of declaration

                     if LB=x'80000000' start
!GT:                    outstring("-(")
!GT:                    p=Ctable(DVDP+1); csexp(x'51'); outsym(')')
                     finish else if lb>0 start
!GT:                    outsym('-'); outint(LB)
                     finish else if LB=0 start
!                        outint(LB)
                     finish else if LB<0 start
!GT:                    outsym('+'); outint(-LB)
                     finish
                  else
                     warn(13,0)
                  finish
                  outstring("] [") unless kk=1
                  DVDP=DVDP-3
               repeat
               p=pp; outsym(']')
            finish else start
               RPOP = 0; RPOP_FLAG = SCONST
               BINSERT(HEAD1,BOT1,RPOP_S1,0,0)
               if JJ>Q then FAULT(20,JJ-Q,ARRNAME) else c
                  FAULT(21,Q-JJ,ARRNAME)
               P = P+2; SKIP APP
            finish
            SOLDI = OLDI
            ACCESS = 3
            ACC = ELSIZE; PTYPE = PTYPEP; UNPACK; J = JJ
            if TYPE=5 and NAM>0 then MLOPND = HDOPND
            OLDI = SOLDI;                ! FOR NAME==A(EL) VALIDATION
            return
         end;                            ! OF ROUTINE CANAME
routine namepreamble(integer z,fname)
!***********************************************************************
!*     puts any unary operators on front of the name                   *
!*     assumes ptype has been set and unpacked                         *
!***********************************************************************
integer typep,qq,subs,pp
      typep=type
      pp=p
      if typep=3 then qq=copy record tag(subs) and p=pp
      if z=3 and type#5 and (nam=0 or arr#0) then outsym('&')
      if z=4 and type#5 and (nam=0 or arr#0) then outstring("(int)&")
      if z=4 and (type=5 or (nam#0 and arr=0)) then outstring("(int)")
      if (z=1 or z=2) and ((nam#0 and arr=0=rout) orc
      (nam>=2 and rout=1{mapping fn call })) and type#5 c
       and not(typep=3 and qq=0){ NOT RECORD WITHOUT SUBNAME} then outsym('*')
      if z=7 and typep=3 and qq=0 and nam#0 and arr=0 thenc
         outsym('*')          { record pointer without subname }
      outname(fname)
      if typep=3 then copy tag(fname,no)
end
!*
         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
            record (RD) TOPND
            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
            copy tag(Fname,YES);         ! DECLARE IF UNKNOWN AT THIS POINT
            SAVESL = ACC
            JJ = J; JJ = 0 if JJ=15
            NAMEP = FNAME
            LEVELP = I; DISPP = K
            FAULT(43,0,FNAME) if c
               LITL=1 and ROUT=0=NAM and (Z=1 or Z=3 or (Z=4 and ARR=0))
            ->NOT SET if TYPE=7
            if (Z=0 and (ROUT#1 or 0#TYPE#6)) or (Z=13 and ROUT=0) then c
               FAULT(27,0,FNAME) and ->NOT SET
            ->FUNNY(Z) if Z>=10
            ->RTCALL if ROUT=1
           namepreamble(z,fname)
            ->SW(TYPE)
SW(6):
            FAULT(5,0,FNAME)
            ->NOT SET
SW(4):                                   !RECORD FORMAT NAME
            FAULT(87,0,FNAME)
NOT SET:                                 ! NAME NOT SET
           namepreamble(z,fname)
SW(7):
            BASE = I; DISP = K; ACCESS = 0
            NAMEOPND = 0; NAMEOPND_PTYPE = X'51'
            PTYPE = X'51'; UNPACK
            P = P+2
            if a(p)=1 start
               {%if z=1 %or z=3 %or z=4 %then jj='[' %else} jj='('
               outsym(jj)
               p=p+1; csexp(x'51')
               while a(p)=1 cycle
                   outsym(','); p=p+1; csexp(x'51')
               repeat
               outsym(jj+1+jj>>6)      { ')' or ']' }
           finish
           p=p+1
          ->CHKEN
FUNNY(11):                               ! SET 32 BIT ADRESS OF ARRAYHEAD
FUNNY(12):                               ! MOVE ARRAYHEAD TO ESTACK
            if PTYPE=SNPT then CSNAME(12) and ->CHKEN
            namepreamble(z,fname)
            ->SW(3) if TYPE=3 and (ARR=0 or A(P+2)=1)
            if A(P+2)=2 then P = P+3 else NO APP
            NAMEOPND_FLAG = DNAME
            NAMEOPND_D = FNAME
            NAMEOPND_XTRA = 0
S(12):
S(11):                                   ! ARRAYS IN RECORDS BY NAME
            NAMEOPND_PTYPE = AHEADPT
            ->CHKEN
FUNNY(13):                               ! LOAD ADDR FOR RT-TYPE
            if PTYPE=SNPT then CSNAME(Z) and P = P+1 and ->CHKEN
           namepreamble(z,fname)
            JJ = UNAMETRIP(RTFP,RTPARAMPT,0,FNAME)
            NAMEOPND_PTYPE = RTPARAMPT; NAMEOPND_FLAG = REFTRIP
            NAMEOPND_D = JJ
            NAMEOPND_XTRA = 0
            if A(P+2)=2 then P = P+3 else NO APP
            ->CHKEN
RFUN:                                    ! RECORD FUNCTIONS
            EXPOPND = NAMEOPND
RMAP:                                    ! RECORD MAPS
            COPY TAG(NAMEP,NO);          ! SET KFORM ETC
            P = P-3
            NAMEP = -1
            CRNAME(Z,3,0,0,NAMEP)
            ->RBACK
SW(3):                                   ! RECORD
            CRNAME(Z,2*NAM,I,K,NAMEP)
RBACK:
            ->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:       MLOPND = 0
            if NAM#1 then start
               MLOPND_PTYPE = X'51'
               MLOPND_D = SAVESL-1
            else
               MLOPND_PTYPE = X'61'
               MLOPND_FLAG = LOCALIR
               MLOPND_D = I<<16!K
            finish
            NAMEOP(Z,4,NAMEP)
            ->CHKEN
STRARR:                                  ! STRINGARRAYS &  ARRAYNAMES
            TOPND = 0
            TOPND_PTYPE = AHEADPT; TOPND_FLAG = DNAME
            TOPND_D = FNAME
            CANAME(Z,ARR,TOPND)
            ->SMAP unless Z=3 and NAM#0
                                         ! MLOPND LEFT SET BY CANAME
            NAMEOP(3,4,NAMEP)
            ->CHKEN
STRINREC:                                ! STRINGS IN RECORDS
            SAVESL = ACC
            ->SMAP unless Z=3 and NAM#0 and ARR#0
                                         ! MLOPND SET BY CANAME & SET LEFT SET%c
                                         BY CENAME
            NAMEOP(3,4,NAMEP)
            ->CHKEN
!
! 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
           namepreamble(z,fname)
            CRCALL(FNAME); P = P+1;      ! DEAL WITH PARAMS
            ->CHKEN if PTYPE&15=0
            ->UDM if NAM>1;              ! MAPS
            unless Z=2 or Z=5 or Z=3=TYPE start;      ! FUNCTIONS
               FAULT(29,0,FNAME); BASE = 0
               ACCESS = 0; DISP = 0
            finish
            ->RFUN if TYPE=3
            ->CHKEN
UDM:                                     ! USER DEFINED MAPS
            DISP = 0
            ACCESS = 3
            BASE = 0
            EXPOPND = NAMEOPND
            ->RMAP if TYPE=3
BIM:                                     ! BUILT IN MAPS
            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
               TOPND = 0
               TOPND_PTYPE = AHEADPT; TOPND_FLAG = DNAME
               TOPND_D = FNAME
               CANAME(Z,ARR,TOPND)
               NAM = 0
            finish
            NAMEOP(Z,BYTES(PREC),NAMEP)
            ->CHKEN
!
CHKEN:      while A(P)=1 cycle
               FAULT(69,FROMAR2(P+1),FNAME)
               outsym('_'); outname(fromar2(P+1))
               P = P+3; SKIP APP
            repeat
            P = P+1
         end

         routine NAMEOP(integer Z,SIZE,NAMEP)
         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.                           *
!***********************************************************************
integer II,III,QQQ,JJ,JJJ,NPARMS,PT,LP,PSIZE,TWSP,PARMNO,ERRNO,
   FPTR,TYPEP,PRECP,NAMP,TL,CLINK,PSPECED,OUTP,PPTYPE,DVD,DVDP,LB,KK
record (RD) OPND,OPND1,OPND2
record (LISTF) name LCELL
            PT = PTYPE; JJJ = J; TL = OLDI
            TWSP = 0; FPTR = 0
            LP = I; CLINK = K
            TYPEP = TYPE; PRECP = PREC; NAMP = NAM
            if CLINK=0 then PSPECED = 0 else PSPECED = ASLIST(CLINK)_S3&255
!
            begin
               integer array ARP(0:PSPECED)
               switch FPD(0:3)
! NOW CHECK THAT THE RIGHT NUMBER OF PARAMETERS HAVE BEEN PROVIDED
! ALSO NOTE THE POINTERS TO ACTUAL PARAMETERS ALLOWING FOC 'C' COMPATABILITY
!
               P = P+2
               NPARMS = 0
               while A(P)=1 cycle
                  P = P+1
                  if NPARMS<PSPECED start
                     if PARAMS BWARDS=YES then c
                        ARP(PSPECED-NPARMS) = P else ARP(NPARMS+1) = P
                  finish
                  NPARMS = NPARMS+1
                  SKIP EXP
               repeat
               OUTP = P
               if PSPECED#NPARMS then start
                                         ! WRONG NO OF PARAMETERS GIVEN
                  if PSPECED=0 then ERRNO = 17 else start
                     if NPARMS<PSPECED then ERRNO = 18 else ERRNO = 19
                  finish
                  FAULT(ERRNO,IMOD(PSPECED-NPARMS),RTNAME)
                  SKIP APP; P = P-1
                  NAMEOPND = 0; NAMEOPND_PTYPE = X'51';  ! ENSURE SENSIBLE%c
                                                         RESULT TRIPLE
                  ->OVER
               finish
!
               II = UNAMETRIP(PRECL,PT&255,0,RTNAME)
               PARMNO = 0
               outsym('(')
               ->FIRST PARM
!
BAD PARM:                                ! BAD PARAMETER FAULT IT
            if PARAMS BWARDS=Yes then II=pspeced-parmno+1 else ii=parmno
               FAULT(22,II,RTNAME)
NEXT PARM:     CLINK = LCELL_LINK
              outsym(',') unless clink=0
FIRSTPARM:     ->ENTRY SEQ if CLINK=0;   ! DEPART AT ONCE IF NO PARAMS
               LCELL == ASLIST(CLINK)
               PSIZE = LCELL_ACC&X'FFFF'
               PARMNO = PARMNO+1
               P = ARP(PARMNO)
               PTYPE = LCELL_PTYPE
               UNPACK
               II = TYPE; III = PREC
               JJ = (NAM<<1!ARR)&3
               ->BAD PARM unless c
                  (JJ=0 and ROUT=0) or JJ=2 or (A(P+3)=4 and c
                  A(P+4)=1 and A(P+FROMAR2(P+1)+1)=2)
               OPND_PTYPE <- PTYPE; OPND_FLAG = DNAME
               OPND_D = RTNAME
               OPND_XTRA = PARMNO<<24!CLINK
!
! RT TYPE PARAMS, PASS 4 WORDS AS SET UP  BY QCODE INSTRN LVRD
!
               if ROUT=1 then start
                  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
                  FPTR = FPTR+RTPARAMSIZE
                  ->NEXT PARM
               finish
               ->FPD(JJ)
FPD(0):                                  ! VALUE PARAMETERS
               if TYPE=3 start;          ! RECORDS BY VALUE
                  II = TSEXP(III);       ! CHECK FOR ZERO AS RECORD VALUE
                  if II=1 and III=0 start
                     -> bad parm
                  finish else start
                     P = ARP(PARMNO);    ! RESET NEEDED AFTER TSEXP
                     ->BAD PARM unless c
                        A(P+3)=4 and A(P+4)=1 and A(P+FROMAR2(P+1)+1)=2
                     P = P+5
                     CNAME(6)
                     P = P+1
                     JJ = 1
                     EXPOPND = NAMEOPND
                     ->BAD PARM unless ACC=PSIZE
                  finish
                  FPTR = FPTR+PSIZE
                  if TARGET=EMAS then FPTR = FPTR+8;    ! TIRESOME BACK%c
                                                        COMPATIBILITY
                                         ! WITH EMAS IMP ON RECORD VALUES
               finish else if TYPE=5 then start
                  if STRVALINWA=YES start;    ! USING WORK AREA (2900)
                     CSTREXP(0)
                     PUSH(TWSP,VALUE,0,0);  ! REMEBER WA
                     FPTR = FPTR+PTRSIZE(X'35')
                     pptype = x'51'
                     if ptrsize(x'35')>4 then pptype = x'61'
                     opnd1 = 0; opnd2 = 0
                     opnd2_flag = sconst; opnd2_ptype = x'51'
                     opnd2_d = lcell_acc-1
                     opnd1_flag = localir; opnd1_ptype = x'35'
                     opnd1_d = rbase<<16!value
                     opnd1_flag = reftrip; opnd1_ptype = pptype
                     ->next parm
                  finish else start
                     CSTREXP(0)
                     FPTR = FPTR+ACC
                  finish
               finish else start
                  CSEXP(III<<4!II)
                  FPTR = FPTR+BYTES(III)
               finish
               FPTR = (FPTR+MINPARAMSIZE-1)&(-MINPARAMSIZE)
               ->NEXT PARM
!
FPD(2):                                  ! NAME PARAMETERS
               PPTYPE = X'51';           ! PTYPE OF RESULTANT POINTER
               if PTRSIZE(PTYPE&255)>4 then PPTYPE = X'61'
               if II#0 start;            ! NOT A GENERAL NAME
                  QQQ = 0
                  if A(P+3)=4 and A(P+4)=1 and A(P+FROMAR2(P+1)+1)=2 start
                     P = P+5
                     REDUCE TAG(YES)
                     if II=TYPE and III=PREC and (LITL#1 or NAM#0) and c
                        (ROUT=0 or NAM=2) then QQQ = 1 else P = P-5
                  finish
                  if QQQ#0 then CNAME(3) {TRUE REF} else start
                                         ! EXPRESSION BY REFERENCE
                     ->BAD PARM unless JJJ=14 or LP=0
                     ->BAD PARM if II=3
                     if II=5 start;      ! STRING EXPRESSION
                        CSTREXP(0)
                        PUSH(TWSP,VALUE,0,0)
                        QQQ = VALUE
                        OPND2_D = 255
                     finish else start
                        GET WSP(QQQ,BYTES(III)>>2)
                        CSEXP(LCELL_PTYPE&255)
                        OPND2_D = BYTES(III)
                     finish
                     OPND2_FLAG = SCONST
                     OPND2_PTYPE = X'51'
                     OPND1_FLAG = LOCALIR
                     OPND1_PTYPE = LCELL_PTYPE&255
                     OPND1_D = RBASE<<16!QQQ
                     OPND1_XTRA = 268;               ! size of area needed for stack dowm m-cs
                     if II#5 then c
                     NAMEOPND_FLAG = REFTRIP
                     NAMEOPND_PTYPE = PPTYPE
                     NAMEOPND_D = QQQ
                  finish
                  JJ = PTRSIZE(III<<4!II)
                  FPTR = FPTR+JJ
               finish else start
                  ->BAD PARM unless c
                     A(P+3)=4 and A(P+4)=1 and A(P+1+FROMAR2(P+1))=2
                  P = P+5
                  FNAME = FROM AR2(P)
                  REDUCE TAG(NO)
                  OPND2_PTYPE = X'51'; OPND2_FLAG = SCONST
                  OPND2_D = ACC<<16!PTYPE
                  OPND2_XTRA = 0
                  if TYPE=0 start;       ! NAME AS GENERAL NAME
                     NAMEOPND_PTYPE <- PTYPE; NAMEOPND_FLAG = DNAME
                     NAMEOPND_D = FNAME
                     NAMEOPND_XTRA = X'80000000'
                  finish else if NAM#0 and TYPE=5 start
                     CNAME(3)
                  finish else CNAME(4)
                  EXPOPND_PTYPE = X'61'; EXPOPND_FLAG = REFTRIP
                  EXPOPND_XTRA = 0
                  FPTR = FPTR+PTRSIZE(0)
               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
!
               P = P+5
               reduce tag(NO)
               DVD = SNDISP
               if DVD#0 then outsym('&'); CNAME(12)
               P = P+1
               ->BAD PARM unless 1<=ARR<=2 and II=TYPE and III=PREC
               QQQ = ASLIST(TCELL)_UIOJ&15;  ! DIMENSION OF ACTUAL(IF KNOWN)
               JJ = LCELL_UIOJ&15;       ! DIMENSION OF FORMAL
               if JJ=0 then JJ = QQQ and LCELL_UIOJ = LCELL_UIOJ!JJ
               if QQQ=0 then QQQ = JJ and c
                  ASLIST(TCELL)_UIOJ = ASLIST(TCELL)_UIOJ!JJ
               ->BAD PARM unless JJ=QQQ
               if DVD#0 start    { have info to adjust basepoint }
                  DVDP=DVD+3*jj
                  cycle KK = jj,-1,1
                     LB=Ctable(DVDP)
                     outsym('[')
                     if LB=x'80000000' start
                        outstring("-(")
                        p=Ctable(DVDP+1); csexp(x'51'); outsym(')')
                     finish else if lb>0 start
                        outsym('-'); outint(LB)
                     finish else if LB<=0 start
                        {outsym('+');} outint(-LB)
                     finish
                     outstring("] ")
                     DVDP=DVDP-3
                  repeat
               finish
               FPTR = FPTR+AHEADSIZE
               ->NEXT PARM
ENTRY SEQ:                               ! CODE FOR RT ENTRY
               outsym(')')
               while TWSP>0 cycle
                  POP(TWSP,QQQ,JJ,III);  ! ONLY IF STR VALS & EMAS
                  RETURN WSP(QQQ,268)
               repeat
               if STRRESINWA=YES and NAMP<=1 and (TYPEP=3 or c
                  TYPEP=5) start
                  GET WSP(QQQ,268);      ! AUTOMATIC RETURN
                  OPND2_PTYPE <- PT
                  OPND2_FLAG = LOCALIR
                  OPND2_D = RBASE<<16!QQQ
                  OPND2_XTRA = 268
                  Opnd_ptype<-pt; opnd_flag=dname
                  opnd_d=rtname; opnd_xtra=(pspeced+1)<<24
                  FPTR = FPTR+PTRSIZE(X'35')
               finish
               II = UNAMETRIP(RCALL,PT&255,0,RTNAME)
               TRIPLES(II)_OPND1_XTRA = FPTR;  ! PASS PARAM SIZE TOTAL
               CURRINF_NMDECS = CURRINF_NMDECS!2
               ROUT = 1; TYPE = TYPEP; NAM = NAMP
               PREC = PRECP; PTYPE = PT
!
! RECOVER THE RESULT OF FNS & MAPS. OFTEN NOCODE WILL BE NEEDED
!
               if PT&255#0 start
                  if NAM>=2 then II = RCRMR else II = RCRFR
                  II = UNAMETRIP(II,PT&255,0,RTNAME)
                  if STRRESINWA=YES then TRIPLES(II)_OPND1_XTRA = QQQ
                                         ! WORK AREA OFFSET
                  NAMEOPND_PTYPE = PT&255; NAMEOPND_FLAG = REFTRIP
                  NAMEOPND_D = II
                  NAMEOPND_XTRA = 0
               finish
OVER:          P = OUTP
            end;                         ! OF INNER BLOCK
         end
integer fn TSEXP(integer name VALUE)
switch SW(1:3)
integer PP,KK,SIGN,CT
      TYPE = 1; PP = P
      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(NO)
      if ptype&x'ff0f'=x'4001' start   { any const int }
         if a(p+2)=2 and a(p+3)=2 and a(p+4)=2 then start
            value=midcell
            p=p+5
            if sign#2 then result = 2
            value=-value; result=-2
         finish
      finish
      ->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 a(p+5)=2
      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
!*
integerfn tsc
integer value,res,PP
switch sw(1:4)
!printstring("tsc  with p="); write(p,5); newline
      PP=p
      ->sw(a(p))
sw(1):
         p=p+1
         res=tsexp(value)
         if res=0 then result=0
         p=p+1
!printstring("tcond part2 with p="); write(p,5); newline
         res=tsexp(value)
         if res=0 then result=0
         p=p+1
         if a(p-1)=1 then result=0
         RESULT=1
SW(2):
         p=p+1; res=tcond
!printstring("returns from tcond with res & p "); write(res,1); write(p,5); newline
         result=res
SW(3):
         P=P+1
         result=tsc
sw(4):                   ! boolean
      result=tsexp(value)
end
integerfn tcond
!***********************************************************************
!*     Check for a simple compile time condition. PP to First exp      *
!***********************************************************************
integer value,res,PP
!printstring("tcond with p="); write(p,5); newline
      PP=p
      res=tsc
      if res=0 then result=0
      if a(p)=3 then p=p+1 and result=1
      until a(p)=2 cycle
         p=p+1; res=tsc
         if res=0 then result=0
      repeat
      p=p+1
      result=1
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,precp
            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 IMPABORT
               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 start
                     precp=A(P)>>4
                     if precp=3 then precp=4
                     P = P+1+BYTES(precp)
                  finish
               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
!***********************************************************************
!*  Deals with unexpected parameters                                   *
!***********************************************************************
      P = P+2
      if A(P)=1 then start;        ! <APP> PRESENT
         FAULT(17,0,FROM AR2(P-2))
         outsym('[')
         while a(p)=1 cycle
           p=p+1
           csexp(x'51')
           if a(p)=1 then outsym(',')
         repeat
        p=p+1; outsym(']')
      finish else P = P+1;         ! P NOW POINTS TO ENAME
end
         routine TEST APP(integer name 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 SET LINE
!***********************************************************************
!*       UPDATE THE STATEMENT NO                                       *
!***********************************************************************
integer I,offset
            return if RLEVEL=0;          ! AMONG CONDITIONAL GLOBAL DECS
            offset=CURRINF_DIAGINF+2
            if target=ORN or 1<<target&riskmc#0 Then Offset=Offset+2
            I = UCONSTTRIP(SLINE,X'41',0,LINE<<16!Offset)
            if PARM_PROF#0 then start
               I = PROFAAD+4+4*LINE
            finish
         end
routine STORE TAG(integer KK,LEVEL,RBASE,J,SNDISP,ACC,SLINK,KFORM)
            integer Q,I,TCELL
            record (TAGF) name LCELL
            TCELL = TAGS(KK)
!
! above line to stop local and routine having the same name
!
            Q = LEVEL<<8!RBASE<<4!J
            IMPABORT unless (KFORM!ACC)>>16=0
            LCELL == ASLIST(TCELL)
            if LCELL_UIOJ>>8&63=LEVEL or kk=currinf_m-1 then start
!               FAULT(7,0,KK)
               LCELL_UIOJ <- LCELL_UIOJ&X'C000'!Q;  ! COPY USED BITS ACCROSS
            finish else start
               I = ASL; if I=0 then I = MORE SPACE
               LCELL == ASLIST(I)
               ASL = LCELL_LINK
               LCELL_LINK = TCELL!CURRINF_NAMES<<18
               LCELL_UIOJ = Q
               TAGS(KK) = I
               CURRINF_NAMES = KK
            finish
            LCELL_PTYPE <- PTYPE
            LCELL_ACC <- ACC
            LCELL_SNDISP <- SNDISP
            LCELL_KFORM = KFORM
            LCELL_SLINK <- SLINK
         end
         routine COPY TAG(integer TNAME,DECLARE)
!***********************************************************************
!*    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        *
!***********************************************************************
            record (TAGF) name LCELL
            TCELL = TAGS(TNAME)
            if TCELL=0 then start;       ! NAME NOT SET
               TYPE = 7; PTYPE = X'57'; PREC = 5
               if DECLARE=YES start
                  FAULT(16,0,TNAME)
                  STORE TAG(TNAME,LEVEL,RBASE,0,0,4,N,0)
                  N = N+4
                  COPY TAG(TNAME,NO);    ! TO SET USE BITS
                  return
               finish
               ROUT = 0; NAM = 0; ARR = 0; LITL = 0; ACC = 4
               I = -1; J = -1; K = -1; OLDI = -1; kform = -1
            finish else start
               LCELL == ASLIST(TCELL)
               PTYPE = LCELL_PTYPE&X'FFFF'
               USEBITS = LCELL_UIOJ>>14&3
               OLDI = LCELL_UIOJ>>8&63
               I = LCELL_UIOJ>>4&15
               J = LCELL_UIOJ&15
               LCELL_UIOJ <- LCELL_UIOJ!X'8000'
               MIDCELL = LCELL_S2
               SNDISP = LCELL_SNDISP&X'FFFF';  ! Sign extension on some hosts
               ACC = LCELL_ACC&X'FFFF'
               K = LCELL_SLINK&X'FFFF';  ! Sign extension on some hosts
               KFORM = LCELL_KFORM
               LITL = PTYPE>>14&3;       ! SIGNEXTENSION ON 16 BIT MACHINES
               ROUT = PTYPE>>12&3
               NAM = PTYPE>>10&3
               ARR = PTYPE>>8&3
               PREC = PTYPE>>4&15
               TYPE = PTYPE&15
            finish
         end
         routine REDUCE TAG(integer DECLARE)
!***********************************************************************
!*       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),DECLARE)
            if PTYPE=SNPT then start
               PTYPE = ACC; UNPACK
               if k=42 {string} then acc = 256 else if c
                  k=48 {record} then acc = x'7fff' else ACC = BYTES(PREC)
            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(integer name PTYPE)
            PTYPE = (((((LITL&3)<<2!ROUT&3)<<2!NAM&3)<<2!ARR&3)<<4!PREC&15) c
               <<4!TYPE&15
         end
      end;                               ! OF ROUTINE CSS

      integer fn NEWTRIP
!***********************************************************************
!*    SETS UP A NEW TRIPLE AND LINKS IT IN
!***********************************************************************
         record (TRIPF) name CURRT
         integer I
         CURRT == TRIPLES(NEXT TRIP)
         I = NEXT TRIP
         if I>=WORKA_LAST TRIP then i=1{FAULT(102,WORKA_WKFILEK,0)}
         NEXT TRIP = i +1
         CURRT = 0
         CURRT_BLINK = TRIPLES(0)_BLINK
         TRIPLES(0)_BLINK = I
         TRIPLES(CURRT_BLINK)_FLINK = I
         result = I
      end
      integer fn 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_PTYPE = X'51'
         CURRT_OPND1_D = CONST
         result = CELL
      end
      integer fn ULCONSTTRIP(integer OPERN,OPTYPE,FLAGS,CONST1,CONST2)
!***********************************************************************
!*    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_PTYPE = X'61'
         CURRT_OPND1_D = CONST1
         CURRT_OPND1_XTRA = CONST2
         result = CELL
      end
      integer fn 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_PTYPE = TAGINF_PTYPE
         CURRT_OPND1_FLAG = DNAME
         CURRT_OPND1_D = NAME
         CURRT_OPND1_XTRA = 0
         result = CELL
      end
      integer fn 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_PTYPE = OPTYPE; CURRT_OPND1_FLAG = LOCALIR
         CURRT_OPND1_D = TEMP
         result = CELL
      end
      routine KEEPUSECOUNT(record (RD) name OPND)
!***********************************************************************
!*    KEEPS PUSE AND CNT UP TO DATE                                    *
!***********************************************************************
         record (TRIPF) name REFT
         REFT == TRIPLES(OPND_D)
         if REFT_CNT=0 then start
!            printstring("setting puse ")
!            write(opnd_d,4); write(triples(0)_blink,4); write(reft_puse,3)
!             newline
           REFT_PUSE = TRIPLES(0)_BLINK
         finish
         REFT_CNT = REFT_CNT+1
      end
      integer fn URECTRIP(integer OPERN,OPTYPE,FLAGS,
         record (RD) name OPND1)
!***********************************************************************
!*    SETS UP A BINARY TRIPLE WITH  COMPLETE OPERANDS PROVIDED         *
!***********************************************************************
         integer CELL
         record (TRIPF) name CURRT
         CELL = NEWTRIP
         CURRT == TRIPLES(CELL)
         CURRT_OPERN = OPERN
         CURRT_OPTYPE <- OPTYPE
         CURRT_FLAGS <- FLAGS
         CURRT_OPND1 = OPND1
         if 1<<OPND1_FLAG&BTREFMASK#0 then KEEPUSECOUNT(OPND1)
         result = CELL
      end
      integer fn 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
         CELL = NEWTRIP
         CURRT == TRIPLES(CELL)
         CURRT_OPERN = OPERN
         CURRT_OPTYPE <- OPTYPE
         CURRT_FLAGS <- FLAGS
         CURRT_OPND1 = OPND1
         CURRT_OPND2 = OPND2
         if 1<<OPND1_FLAG&BTREFMASK#0 then KEEP USE COUNT(OPND1)
         if 1<<OPND2_FLAG&BTREFMASK#0 then KEEP USE COUNT(OPND2)
         result = CELL
      end
      routine GET WSP(integer name 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
            if size=4 then l=rnding(128+x'72') else if Size=2 c
                then l=rnding(128+x'62') else l=3
            n=(n+L)&(¬l)
            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                  *
!***********************************************************************
         integer CELL
         IMPABORT unless PLACE<=N and PLACE&1=0
         if SIZE>4 then SIZE = 0
         CELL = CURRINF_AVL WSP(SIZE)
         while CELL>0 cycle
            IMPABORT if ASLIST(CELL)_S2=PLACE
            CELL = ASLIST(CELL)_LINK
         repeat
         if PLACE<511 then PUSH(CURRINF_AVL WSP(SIZE),0,PLACE,0) else c
            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
      integer fn FROMAR2(integer PTR)
         result = A(PTR)<<8!A(PTR+1)
      end
      integer fn FROMAR4(integer PTR)
         integer I
         MOVE BYTES(4,ADDR(A(0)),PTR,ADDR(I),0)
         result = I
      end
P2END:                                   ! EXITS AFTER COMPILATION
   end;                                  ! OF SUBBLOCK CONTAINING PASS2
end
end of file