!QIN; %MAINEP ICL9CEZIMP
%TRUSTEDPROGRAM
%BEGIN
%INTEGER I, J, K
! PRODUCED BY OLDPS FROM NRIMPPS3 ON 06/04/78
%CONSTBYTEINTEGERARRAY CLETT(0: 478)=   1,
  40,   1,  41,   1,  44,   2, 201, 198,   6, 213, 206, 204, 197, 211,
 211,   5, 215, 200, 201, 204, 197,   5, 213, 206, 212, 201, 204,   4,
 210, 197, 193, 204,   7, 201, 206, 212, 197, 199, 197, 210,   8, 204,
 207, 206, 199, 210, 197, 193, 204,   4, 204, 207, 206, 199,  11, 194,
 217, 212, 197, 201, 206, 212, 197, 199, 197, 210,   6, 211, 212, 210,
 201, 206, 199,  11, 200, 193, 204, 198, 201, 206, 212, 197, 199, 197,
 210,   7, 210, 207, 213, 212, 201, 206, 197,   2, 198, 206,   3, 205,
 193, 208,   6, 210, 197, 195, 207, 210, 196,   4, 206, 193, 205, 197,
   5, 193, 210, 210, 193, 217,   9, 193, 210, 210, 193, 217, 206, 193,
 205, 197,   9, 207, 198, 208, 210, 207, 199, 210, 193, 205,   6, 207,
 198, 198, 201, 204, 197,   6, 207, 198, 204, 201, 211, 212,   6, 198,
 207, 210, 205, 193, 212,   4, 211, 208, 197, 195,   3, 193, 206, 196,
   2, 207, 210,   1,  58,   6, 206, 207, 210, 205, 193, 204,   3, 207,
 215, 206,   8, 197, 216, 212, 197, 210, 206, 193, 204,   9, 197, 216,
 212, 210, 201, 206, 211, 201, 195,   5, 195, 207, 206, 211, 212,   1,
  61,   5, 197, 214, 197, 206, 212,   2,  62,  61,   1,  62,   1,  35,
   2,  60,  61,   1,  60,   2,  92,  61,   2,  45,  62,   5, 211, 212,
 193, 210, 212,   9, 212, 200, 197, 206, 211, 212, 193, 210, 212,   4,
 212, 200, 197, 206,   5, 195, 217, 195, 204, 197,   9, 212, 200, 197,
 206, 195, 217, 195, 204, 197,   9, 197, 204, 211, 197, 211, 212, 193,
 210, 212,   4, 197, 204, 211, 197,   1,  95,   6, 211, 217, 211, 212,
 197, 205,   7, 196, 217, 206, 193, 205, 201, 195,   2,  42,  61,   1,
  42,   4,  80,  85,  84,  95,   5,  67,  78,  79,  80,  95,   2, 204,
  61,   4,  40, 196, 210,  43,   2, 196, 210,   1, 194,   1,  43,   1,
  45,   3, 212, 207, 211,   3, 204, 206, 194,   3, 216, 206, 194,   2,
 208, 195,   3, 195, 212, 194,   6, 210, 197, 212, 213, 210, 206,   6,
 210, 197, 211, 213, 204, 212,   7, 205, 207, 206, 201, 212, 207, 210,
   4, 211, 212, 207, 208,   6, 211, 201, 199, 206, 193, 204,   4, 197,
 216, 201, 212,   6, 198, 201, 206, 201, 211, 200,   6, 210, 197, 208,
 197, 193, 212,   3, 197, 206, 196,   5, 210, 197, 193, 204, 211,   5,
 194, 197, 199, 201, 206,   2, 207, 206,   6, 211, 215, 201, 212, 195,
 200,   4, 204, 201, 211, 212,   7, 211, 208, 197, 195, 201, 193, 204,
  14, 212, 210, 213, 211, 212, 197, 196, 208, 210, 207, 199, 210, 193,
 205,   6, 205, 193, 201, 206, 197, 208,   7, 195, 207, 206, 212, 210,
 207, 204;




%CONSTINTEGERARRAY SYMBOL(1300: 2182)=  1312,
  1305,  1001,  1326,  1793,  1308,  1003,  1020,  1312,     0,  1312,
     2,  1319,  1319,  1010,  1028,  1300,  1011,  1319,  1326,  1324,
  1026,  1300,   999,  1326,  1000,  1334,  1332,     0,  1312,  1334,
     2,  1334,  1000,  1341,  1339,     4,  1312,   999,  1341,  1000,
  1346,  1344,     6,  1346,     9,  1351,  1349,    16,  1351,    22,
  1358,  1356,     4,  1001,   999,  1358,  1000,  1365,  1361,    28,
  1363,    33,  1365,    41,  1380,  1368,    33,  1370,    28,  1373,
    50,  1358,  1375,    55,  1378,    67,  1895,  1380,    74,  1387,
  1383,    86,  1387,  1031,  1365,  1387,  1392,  1390,    94,  1392,
    97,  1398,  1396,  1387,  1416,  1398,  1421,  1411,  1402,  1365,
  1392,  1406,   101,  1411,   108,  1409,    86,  1416,  1411,   108,
  1416,  1414,   113,  1416,  1000,  1421,  1419,   108,  1421,  1000,
  1428,  1424,   119,  1426,   108,  1428,  1000,  1438,  1436,     0,
  1398,  1001,  1351,  1438,     2,  1438,  1000,  1447,  1445,  1030,
  1398,  1001,  1351,  1438,  1447,  1000,  1458,  1451,   129,  1016,
  1453,   139,  1456,   146,  1018,  1458,  1016,  1463,  1461,   153,
  1463,  1000,  1487,  1471,   153,  1001,     0,  1846,  1839,     2,
  1480,   160,  1010,  1001,  1787,  1011,     0,  1001,     2,  1487,
  1010,  1558,  1011,     0,  1001,     2,  1498,  1493,  1312,  1722,
  1312,  1498,  1498,     0,  1487,  1505,     2,  1505,  1503,  1032,
  1722,  1312,  1505,  1000,  1516,  1510,   165,  1487,  1516,  1514,
   169,  1487,  1523,  1516,  1000,  1523,  1521,   165,  1487,  1516,
  1523,  1000,  1530,  1528,   169,  1487,  1523,  1530,  1000,  1538,
  1534,  1033,  1312,  1536,   172,  1538,  1000,  1544,  1542,   160,
  1008,  1544,  1015,  1549,  1547,    50,  1549,   174,  1558,  1556,
     4,  1312,   172,  1312,  1549,  1558,  1000,  1567,  1563,  1421,
  1001,  1351,  1567,   113,  1458,  1567,  1573,  1573,  1001,  1351,
  1801,  1573,  1579,  1577,     4,  1567,  1579,  1000,  1595,  1589,
  1421,  1010,  1001,  1351,  1811,  1011,  1595,  1006,  1595,   113,
  1458,  1001,  1668,  1642,  1606,  1604,     4,  1010,  1001,  1351,
  1811,  1011,  1595,  1606,  1000,  1615,  1609,   181,  1611,   185,
  1613,   194,  1615,   204,  1642,  1619,  1365,  1579,  1630,   101,
  1421,  1010,  1001,  1351,  1011,     0,  1001,     2,  1006,  1642,
   101,   113,  1458,  1010,  1001,  1668,  1011,     0,  1001,     2,
  1006,  1651,  1649,   210,  1029,  1003,  1661,  1651,  1651,  1000,
  1661,  1659,     4,  1012,  1029,  1003,  1661,   999,  1661,  1000,
  1668,  1666,     0,  1005,     2,  1668,  1000,  1678,  1678,     0,
  1029,  1002,   172,  1029,  1002,  1678,     2,  1689,  1687,     4,
  1029,  1002,   172,  1029,  1002,  1678,  1689,  1000,  1696,  1694,
     4,  1009,  1689,  1696,  1000,  1701,  1699,   212,  1701,  1000,
  1707,  1705,     4,  1312,  1707,  1000,  1722,  1720,     4,  1001,
  1351,     0,  1029,  1002,   172,  1029,  1002,     2,  1707,  1722,
  1000,  1739,  1725,   210,  1727,   218,  1729,   221,  1731,   223,
  1733,   225,  1735,   228,  1737,   230,  1739,   233,  1754,  1742,
  1019,  1744,  1006,  1749,  1341,  1487,  1505,  1006,  1754,  1346,
  1487,  1505,  1006,  1765,  1757,   236,  1759,   242,  1765,   252,
  1010,  2030,  1011,  1779,  1773,  1768,   257,  1770,   263,  1773,
   252,  2030,  1779,  1777,   165,  2030,  1779,  1000,  1787,  1782,
   273,  1785,   283,  2030,  1787,  1000,  1793,  1791,   288,  1001,
  1793,  1000,  1801,  1799,   288,  1001,  1326,  1793,  1801,  1000,
  1811,  1804,  1668,  1811,     0,  1312,   172,  1312,  1549,     2,
  1818,  1816,   210,  1029,  1003,  1818,  1000,  1828,  1822,   290,
  1013,  1824,   185,  1826,   297,  1828,  1000,  1839,  1837,  1001,
   210,  1312,     4,  1312,     4,  1312,  1839,  1000,  1846,  1844,
     4,  1846,  1839,  1846,  1000,  1886,  1852,  1365,  1421,  1001,
  1351,  1859,  1365,   113,  1001,  1351,  1668,  1886,  1865,   101,
  1411,   108,  1001,  1351,  1874,   101,  1010,  1001,  1351,  1011,
     0,  1001,     2,  1886,   101,   113,  1010,  1001,  1351,  1668,
  1886,  1011,     0,  1001,     2,  1895,  1893,     4,  1001,  1351,
  1668,   999,  1895,  1000,  1902,  1900,     0,  1009,     2,  1902,
  1000,  1920,  1906,   305,  1001,  1909,   308,  1001,  1912,   310,
  1002,  1915,  1022,  1920,  1920,   315,  1009,     4,  1009,  1934,
  1924,  1023,  1934,  1929,  1024,   321,  1973,  1978,  1934,  1025,
  1005,     4,  1957,  1957,  1939,   228,  1001,   221,  1941,  2006,
  1946,     0,  2006,  1995,     2,  1950,   324,  2006,     2,  1955,
     0,   329,  1995,     2,  1957,   332,  1973,  1962,   228,  1001,
   221,  1964,  2006,  1969,     0,   329,  1995,     2,  1973,   324,
  1005,     2,  1978,  1976,   329,  1978,  1005,  1986,  1984,     4,
  1005,     4,  1005,  1986,  1000,  1995,  1990,   334,  1005,  1993,
   336,  1005,  1995,  1000,  2001,  1999,   334,   332,  2001,  1000,
  2006,  2004,   210,  2006,  1000,  2021,  2011,  2001,  1029,  1003,
  2014,  1001,  1986,  2019,     0,  2021,  1986,     2,  2021,   338,
  2030,  2024,   342,  2026,   346,  2028,   350,  2030,   353,  2061,
  2039,  1010,  1001,  1326,  1793,  1011,  1530,  1773,  2043,   233,
  1001,  1326,  2045,   357,  2049,   364,  1033,  1312,  2052,   371,
  1773,  2054,   379,  2059,   384,  1696,  1009,  1701,  2061,   391,
  2183,  2068,  1027,  1010,  2030,  1011,  1739,  2070,  1007,  2078,
  1341,  1010,  1487,  1505,  1011,  1754,  1006,  2082,   396,  1779,
  1006,  2086,   257,  1828,  1006,  2089,   403,  1006,  2097,  1346,
  1010,  1487,  1505,  1011,  1765,  1006,  2103,  1031,  1008,  1365,
  1558,  1006,  2107,   410,  1447,  1006,  2111,   101,  1463,  1006,
  2120,  1010,  1818,  1380,  1011,  1538,  1001,  1428,  1006,  2123,
  1606,  1615,  2127,   414,  1544,  1006,  2131,   420,  1015,  1006,
  2139,   426,  1021,  1696,  1009,  1689,   236,  1006,  2152,   429,
  1001,  1351,     0,  1029,  1002,   172,  1029,  1002,     2,  1707,
  1006,  2156,   436,  1006,  1017,  2161,   160,  1001,  1428,  1006,
  2166,   441,   108,  1001,  1006,  2170,   308,  1902,  1006,  2173,
   449,  1006,  2177,   464,  1001,  1006,  2181,   471,  1003,  1006,
  2183,  1006;

%CONSTINTEGER SS= 2061

!
%CONST %BYTE %INTEGER %ARRAY I TO E TAB(0 : 127) =       %C
X'40',X'40',X'40',X'40',X'40',X'40',X'40',X'40',
X'40',X'40',X'15',X'40',X'0C',X'40',X'40',X'40',
X'40',X'40',X'40',X'40',X'40',X'40',X'40',X'40',
X'40',X'40',X'40',X'40',X'40',X'40',X'40',X'40',
X'40',X'4F',X'7F',X'7B',X'5B',X'6C',X'50',X'7D',
X'4D',X'5D',X'5C',X'4E',X'6B',X'60',X'4B',X'61',
X'F0',X'F1',X'F2',X'F3',X'F4',X'F5',X'F6',X'F7',
X'F8',X'F9',X'7A',X'5E',X'4C',X'7E',X'6E',X'6F',
X'7C',X'C1',X'C2',X'C3',X'C4',X'C5',X'C6',X'C7',
X'C8',X'C9',X'D1',X'D2',X'D3',X'D4',X'D5',X'D6',
X'D7',X'D8',X'D9',X'E2',X'E3',X'E4',X'E5',X'E6',
X'E7',X'E8',X'E9',X'4A',X'5F',X'5A',X'6A',X'6D',
X'7C',X'81',X'82',X'83',X'84',X'85',X'86',X'87',
X'88',X'89',X'91',X'92',X'93',X'94',X'95',X'96',
X'97',X'98',X'99',X'A2',X'A3',X'A4',X'A5',X'A6',
X'A7',X'A8',X'A9',X'C0',X'40',X'D0',X'40',X'40'
%CONSTINTEGERARRAY OPC(1:126)=%C
M' JCC',M' JAT',M' JAF',0(4),
M' VAL',M' CYD',M'INCA',M'MODD',M'PRCL',M'   J',M' JLK',M'CALL',
M' ADB',M' SBB',M'DEBJ',M' CPB',M' SIG',M' MYB',M' VMY',M'CPIB',
M' LCT',M'MPSR',M'CPSR',M'STCT',M'EXIT',M'ESEX',M' OUT',M' ACT',
M'  SL',M'SLSS',M'SLSD',M'SLSQ',M'  ST',M'STUH',M'STXN',M'IDLE',
M' SLD',M' SLB',M'TDEC',M'INCT',M' STD',M' STB',M'STLN',M'STSF',
M'   L',M' LSS',M' LSD',M' LSQ',M'RRTC',M' LUH',M'RALN',M' ASF',
M'LDRL',M' LDA',M'LDTB',M' LDB',M'  LD',M'  LB',M' LLN',M' LXN',
M' TCH',M'ANDS',M' ORS',M'NEQS',M'EXPA',M' AND',M'  OR',M' NEQ',
M'  PK',M' INS',M'SUPK',M' EXP',M'COMA',M' DDV',M'DRDV',M'DMDV',
M'SWEQ',M'SWNE',M' CPS',M' TTR',M' FLT',M' IDV',M'IRDV',M'IMDV',
M' MVL',M'  MV',M'CHOV',M' COM',M' FIX',M' RDV',M'RRDV',M'RDVD',
M' UAD',M' USB',M'URSB',M' UCP',M' USH',M' ROT',M' SHS',M' SHZ',
M' DAD',M' DSB',M'DRSB',M' DCP',M' DSH',M' DMY',M'DMYD',M'CBIN',
M' IAD',M' ISB',M'IRSB',M' ICP',M' ISH',M' IMY',M'IMYD',M'CDEC',
M' RAD',M' RSB',M'RRSB',M' RCP',M' RSC',M' RMY',M'RMYD';
%CONSTINTEGERARRAY TSNAME (0:61)=X'1000'(8),
               X'1001',X'1000'(5),X'1001',X'1062',X'1001'(2),X'1062',
               X'1000'(2),X'52',X'51',X'62',X'1062'(7),
               X'1000',X'31',X'51',X'1062'(2),X'31',X'1000',
                X'51',X'62',X'1000'(2),X'35',X'1000',X'1035',
                X'31',X'35',X'1035',X'33',0,X'1000',X'31',X'52',X'51',
                X'61',X'72',X'61',X'72',X'51',X'62',X'1051',X'41';
!
%OWNINTEGERARRAY FIXED GLA(0:11)=0,
               X'50000000',0(2),-1,0,0(6);
%CONSTBYTEINTEGERARRAY BYTES(0:7)=0(3),1,2,4,8,16;
%CONSTBYTEINTEGERARRAY TRTAB(0:255)=0(48),
                    1(10),0(7),2(26),0(6),2(26),0(5),0(128)
%CONSTINTEGER MAXLEVELS=31,CONCOP=13,FIXEDGLALEN=48
!
! THE PRINCIPAL OPCODES ARE HERE DEFINED AS THEIR MNEMONICS(AMENDED)
!
%CONSTINTEGER LB=X'7A',SLB=X'52',STB=X'5A',ADB=X'20',CPB=X'26', %C
              MYB=X'2A',SBB=X'22',CPIB=X'2E',OUT=X'3C'
%CONSTINTEGER LD=X'78',LDA=X'72',INCA=X'14',STD=X'58',LDB=X'76', %C
              LDTB=X'74',LDRL=X'70',CYD=X'12',MODD=X'16',SLD=X'50'
%CONSTINTEGER STLN=X'5C',ASF=X'6E',ST=X'48',RALN=X'6C',LXN=X'7E',%C
              LLN=X'7C',LSS=X'62',SLSS=X'42',MPSR=X'32',STSF=X'5E',%C
              LUH=X'6A',STUH=X'4A',LSD=X'64',SLSD=X'44',PRCL=X'18', %C
              LSQ=X'66',SLSQ=X'46',STXN=X'4C',LCT=X'30',STCT=X'36'
%CONSTINTEGER JUNC=X'1A',JLK=X'1C',CALL=X'1E',EXIT=X'38',JCC=2, %C
              JAT=4,JAF=6,DEBJ=X'24'
%CONSTINTEGER IAD=X'E0',ICP=X'E6',USH=X'C8',ISB=X'E2',IRSB=X'E4',%C
              OR=X'8C',UCP=X'C6',IMY=X'EA',IMDV=X'AE',AND=X'8A', %C
              ISH=X'E8',IMYD=X'EC'
%CONSTINTEGER RAD=X'F0',RSB=X'F2',RRSB=X'F4',FLT=X'A8',RRDV=X'BC', %C
              RSC=X'F8',FIX=X'B8',RDV=X'BA',RDDV=X'BE',RMYD=X'FC', %C
              RMY=X'FA'
!
%CONSTINTEGER MVL=X'B0',MV=X'B2',SWEQ=X'A0',SWNE=X'A2',CPS=X'A4'
!
! DEFINE SOME MNEMONICS FOR THE VISIBLE REGISTERS (XCEPT LNB)
!
%CONSTINTEGER ACCR=0,DR=1,LNB=2,XNB=3,PC=4,CTB=5,TOS=6,BREG=7
%CONSTBYTEINTEGERARRAY LDCODE(0:7)=0,X'78',X'7C',X'7E',0,48,0,X'7A';
!
%CONSTSTRING(8)MDEP='S#NDIAG'
%CONSTSTRING(8)IOCPEP='S#IOCP';     ! EP FOR IOCP
%CONSTSTRING(8)SIGEP='S#SIGNAL';    ! EP FOR SIGNAL
%CONSTSTRING(11)AUXSTEP='ICL9CEAUXST';! DATA REF FOR INDIRECT AUX ST
%CONSTINTEGER SNPT=X'1006';         ! SPECIALNAME PTYPE
%CONSTINTEGER COMMALT=2,ENDALT=9,UNASSPAT=X'81818181',DECALT=8
!
%INTEGER DICTBASE, CONSTPTR, CONSTBTM, DFHEAD, CONSTHOLE, %C
         DUMMY FORMAT, P1SIZE, LEVELINF, IOCPDISP
!
%INTEGER ASL, NNAMES, ARSIZE, CABUF, PPCURR, CONSTLIMIT, OLDLINE, %C
         LINE, LENGTH, NEXTP, SNUM, RLEVEL, NMAX, USTPTR, PLABEL,%C
         LEVEL, CA, RR, LASTNAME, CDCOUNT, ASL CUR BTM
!
%INTEGER FAULTY, HIT, INHCODE, IMPS, TTOPUT, LIST, PARMDIAG, %C
            WARNFLAG, PARMTRACE, PARMLINE, PARMOPT, CTYPE, DCOMP, %C
           CPRMODE, PARMCHK, PRINTMAP, PARMARR, ALLLONG,%C
            COMPILER, LAST INST, SMAP, STACK, AUXST, SIGREFDIS, BFFLAG
!
%INTEGER MASK, RBASE, N, FREE FORMAT, %C
         P, Q, R, S, T, NEST, FNAME, LDPTR, GLACA, GLACABUF, %C
         GLACURR, CREFHEAD, SSTL, QMAX, STMTS, LASTAT, %C
         FILE ADDR, FILE PTR, FILE END, FILE SIZE, LASTEND, %C
         BIMSTR,STLIMIT,STRLINK,RECTB
!
%INTEGER MAX ULAB, XLABEL, SFLABEL
%LONGREAL CVALUE, IMAX, CTIME
%STRING(31)MAINEP
%RECORDFORMAT LISTF(%INTEGER S1,S2,S3,LINK)
%RECORDNAME LCELL(LISTF)
%INTEGER LOGEPDISP,EXPEPDISP
!
%SYSTEMINTEGERMAPSPEC COMREG(%INTEGER N)
%BEGIN
      FILE ADDR=COMREG(46);          ! SOURCE FILE IF CLEAN
      %IF -1<=FILE ADDR<=0 %THEN %START
         FILE SIZE=32000*(FILE ADDR+2)
      %FINISH %ELSE %START
         FILE PTR=FILE ADDR+INTEGER(FILE ADDR+4)
         FILE END=FILE ADDR+INTEGER(FILE ADDR)
         FILE SIZE=INTEGER(FILE ADDR)
      %FINISH
      %IF FILE ADDR=-1 %THEN FILE ADDR=0
      ARSIZE=INTEGER(COMREG(14)+8)-24*4096-300
      NNAMES=255
      %IF FILESIZE>10000 %THEN NNAMES=511
      %IF FILESIZE>32000 %THEN NNAMES=1023
      %IF FILESIZE>256*1024 %THEN NNAMES=2047
      ASL=3*NNAMES
%END
%BYTEINTEGERARRAYFORMAT AF(0:ARSIZE)
%BYTEINTEGERARRAYNAME A
%RECORDARRAY ASLIST(0:ASL)(LISTF)
%INTEGERARRAY WORD, TAGS(0:NNAMES)
!%ROUTINESPEC PRHEX(%INTEGER VALUE, PLACES)
%LONGREALFNSPEC FROMAR8(%INTEGER PTR)
%INTEGERFNSPEC FROMAR4(%INTEGER PTR)
%INTEGERFNSPEC FROMAR2(%INTEGER PTR)
%ROUTINESPEC TOAR8(%INTEGER PTR, %LONGREAL VALUE)
%ROUTINESPEC TOAR4(%INTEGER PTR, VALUE)
%ROUTINESPEC TOAR2(%INTEGER PTR,VALUE)
%ROUTINESPEC WARN(%INTEGER N,V)
%ROUTINESPEC FAULT(%INTEGER N, VALUE)
%ROUTINESPEC PRINT NAME(%INTEGER N)
%INTEGERFNSPEC MORE SPACE
%INTEGERFNSPEC NEWCELL
%ROUTINESPEC INSERTATEND(%INTEGERNAME S, %INTEGER A, B, C)
%ROUTINESPEC FROM12(%INTEGER CELL, %INTEGERNAME S1, S2)
%ROUTINESPEC FROM123(%INTEGER CELL, %INTEGERNAME S1, S2, S3)
%ROUTINESPEC POP(%INTEGERNAME C, P, Q, R)
%ROUTINESPEC PUSH(%INTEGERNAME C, %INTEGER S1, S2, S3)
%INTEGERFNSPEC FIND(%INTEGER LAB, LIST)
%INTEGERFNSPEC FIND3(%INTEGER LAB, LIST)
%ROUTINESPEC MLINK(%INTEGERNAME CELL)
%ROUTINESPEC REPLACE1(%INTEGER CELL, S1)
%ROUTINESPEC REPLACE2(%INTEGER CELL, S2)
%ROUTINESPEC REPLACE3(%INTEGER CELL,S3)
%ROUTINESPEC REPLACE123(%INTEGER CELL,A1,A2,S3)
%INTEGERFNSPEC FROM2(%INTEGER CELL)
%INTEGERFNSPEC FROM1(%INTEGER CELL)
%INTEGERFNSPEC FROM3(%INTEGER CELL)
%ROUTINESPEC BINSERT(%INTEGERNAME T,B,%INTEGER S1,S2,S3)
%ROUTINESPEC CLEARLIST(%INTEGERNAME HEAD)
%ROUTINESPEC MESSAGE(%INTEGER N)
%SYSTEMROUTINESPEC LPUT(%INTEGER A, B, C, D)
%SYSTEMLONGREALFNSPEC CPUTIME
!*DELSTART
%SYSTEMROUTINESPEC NCODE(%INTEGER START, FINISH, CA)
%ROUTINESPEC PRHEX(%INTEGER VALUE,PLACES)
%ROUTINESPEC CHECK ASL
!*DELEND
         ! START OF COMPILATION
         A==ARRAY(COMREG(14)+24*4096, 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.         *
!***********************************************************************
%ROUTINESPEC READ LINE(%INTEGER MODE,CHAR)
%ROUTINESPEC COMPARE
%ROUTINESPEC PNAME(%INTEGER MODE)
%ROUTINESPEC CONST(%INTEGER MODE)
%ROUTINESPEC TEXTTEXT(%INTEGER EBCDIC)
%INTEGER CCSIZE,DSIZE,NEXT
      CCSIZE=600; DSIZE=7*NNAMES
%INTEGERARRAY DISPLAY(0:MAXLEVELS)
%BYTEINTEGERARRAY  TLINE(-60:161),CC(0:CCSIZE),LETT(0:DSIZE+20)
%CONSTBYTEINTEGERARRAY ILETT(0: 491)= 11,
    'S','E','L','E','C','T','I','N','P','U','T', 12,'S','E','L','E',
    'C','T','O','U','T','P','U','T',  7,'N','E','W','L','I','N','E',
      5,'S','P','A','C','E', 10,'S','K','I','P','S','Y','M','B','O',
    'L', 10,'R','E','A','D','S','T','R','I','N','G',  8,'N','E','W',
    'L','I','N','E','S',  6,'S','P','A','C','E','S', 10,'N','E','X',
    'T','S','Y','M','B','O','L', 11,'P','R','I','N','T','S','Y','M',
    'B','O','L', 10,'R','E','A','D','S','Y','M','B','O','L',  4,'R',
    'E','A','D',  5,'W','R','I','T','E',  7,'N','E','W','P','A','G',
    'E',  4,'A','D','D','R',  6,'A','R','C','S','I','N',  3,'I','N',
    'T',  5,'I','N','T','P','T',  6,'F','R','A','C','P','T',  5,'P',
    'R','I','N','T',  7,'P','R','I','N','T','F','L',  4,'R','E','A',
    'L',  7,'I','N','T','E','G','E','R',  3,'M','O','D',  6,'A','R',
    'C','C','O','S',  4,'S','Q','R','T',  3,'L','O','G',  3,'S','I',
    'N',  3,'C','O','S',  3,'T','A','N',  3,'E','X','P', 11,'C','L',
    'O','S','E','S','T','R','E','A','M', 11,'B','Y','T','E','I','N',
    'T','E','G','E','R',  8,'E','V','E','N','T','I','N','F',
    6,'R','A','D','I','U','S',  6,'A','R','C','T','A','N',
      6,'L','E','N','G','T','H', 11,'P','R','I','N','T','S','T','R',
    'I','N','G',  2,'N','L',  8,'L','O','N','G','R','E','A','L',  7,
    'P','R','I','N','T','C','H',  6,'R','E','A','D','C','H',  6,'S',
    'T','R','I','N','G',  8,'R','E','A','D','I','T','E','M',  8,'N',
    'E','X','T','I','T','E','M',  6,'C','H','A','R','N','O',  8,'T',
    'O','S','T','R','I','N','G', 10,'F','R','O','M','S','T','R','I',
    'N','G',  6,'R','E','C','O','R','D',  5,'A','R','R','A','Y', 10,
    'S','E','T','M','A','R','G','I','N','S',4,'I','M','O','D',2,'P',
    'I',9,'E','V','E','N','T','L','I','N','E',11,'L','O','N','G',
    'I','N','T','E','G','E','R',12,'L','O','N','G','L','O','N','G',
    'R','E','A','L',9,'L','E','N','G','T','H','E','N','I',
     9,'L','E','N','G','T','H','E','N','R',
     8,'S','H','O','R','T','E','N','I',
     8,'S','H','O','R','T','E','N','R',
      6,'N','E','X','T','C','H',
      11,'H','A','L','F','I','N','T','E','G','E','R',255;
         IMAX=(-1)>>1;PLABEL=24999
         LETT(0)=0
         N=12;
         MAX ULAB=NNAMES+16384;   ! LARGEST VALID USER LABEL
         GLACURR=0; GLACA=FIXEDGLALEN; GLACABUF=GLACA
         PARMOPT=1 ;  PARMARR=1;  LAST INST=0
         PARMLINE=1; PARMTRACE=1;  PARMDIAG=1
         LIST=1; SFLABEL=20999; PARMCHK=1
         XLABEL=19999;      ! FOR EXIT STATEMENTS
         CABUF=0;  PPCURR=0;  OLDLINE=0; COMPILER=0
         LINE=0;  RLEVEL=0;  NMAX=0;  USTPTR=0
         LEVEL=0;  CA=0;  LASTAT=0
         FAULTY=0;  WARNFLAG=0; ALLLONG=0; INHCODE=0
         DCOMP=0;  BFFLAG=0;  CPRMODE=0;  PRINT MAP=0
         NEXT=1;  LDPTR=0
         IOCPDISP=0; CREFHEAD=0; AUXST=0
         RBASE=10;  LOGEPDISP=0;  EXPEPDISP=0; STRLINK=0
         RECTB=0
         SSTL=0;  STMTS=1;  SNUM=0;  LEVELINF=0
         CDCOUNT=0
         BIMSTR=0
         LOGEPDISP=0; EXPEPDISP=0
         MAINEP='S#GO';                 ! DEFAULT MAIN ENTRY
         DICTBASE=ADDR(LETT(0))
!
! OPEN OBJECT FILE HERE BEFORE MORE PAGES OF COMPILER CODE
! ARE PAGED IN AND SUB-SYSTEM PAGES MOVE OUT
!
         LPUT(0,0,0,0)
         CTIME=CPUTIME
         I=COMREG(27)
         STLIMIT=X'1F000'
         %IF I>>24&1#0 %THEN STLIMIT=COMREG(48)-4096
         %IF I&2=2 %THEN LIST=0
         %IF I&4=4 %THEN PARMDIAG=0
         %IF I&X'800000'#0 %THEN PARMLINE=0
         %IF I&16=16 %THEN PARMCHK=0
         %IF I&32=32  %THEN PARMARR=0
         %IF I&(128<<8)#0 %THEN PRINTMAP=1
         %IF I&64=64 %THEN PARMTRACE=0 %AND PARMDIAG=0
         FREE FORMAT=I&X'80000'
         STACK=I>>3&1
         SMAP=I>>7&1
         TTOPUT=I>>21&1
         %IF I&(1<<16)#0 %THEN %START
            PARMARR=0; PARMOPT=0
            PARMLINE=0; PARMCHK=0; PARMDIAG=0
         %FINISH
         %IF PARMOPT#0 %THEN PARMTRACE=1
         IMPS=I>>23&1;              ! BIT SET IF IMPS REQUESTED
         IMPS=1;                        ! FOR TESTING
         NEWLINES(3); SPACES(14)
         PRINTSTRING('E.R.C.C. NRIMP')
         %IF IMPS#0 %THEN PRINTSYMBOL('S')
         PRINTSTRING(' COMPILER RELEASE  7 VERSION 10NOV78')
         NEWLINES(3)
         WRITE(NNAMES,5); WRITE(ASL,5)
         NEWLINE
         ASL CUR BTM=ASL-240
         CONST LIMIT=4*ASL CUR BTM-8
         %CYCLE I=ASL CUR BTM,1,ASL-1
             ASLIST(I+1)_LINK=I
         %REPEAT
         ASLIST(ASL CUR BTM)_LINK=0
         ASLIST(0)_S1=-1
         ASLIST(0)_S2=-1
         ASLIST(0)_S3=-1
         ASLIST(0)_LINK=0
         %CYCLE I=0,1,NNAMES
             WORD(I)=0; TAGS(I)=0;
         %REPEAT
!
! NOW DECLARE THE SPECIAL NAMES WHICH ARE IN ARRAY ILETT.
!
         K=0; NEXT=1
         I=ILETT(0)
         %WHILE I<255 %CYCLE
            %CYCLE J=1,1,I
                CC(J)=ILETT(K+J)
            %REPEAT; CC(J+1)=';'
            R=2; Q=1; PNAME(1)
            PUSH(TAGS(LASTNAME),SNPT<<16!X'8000',0,SNUM<<16)
            SNUM=SNUM+1
            K=K+I+1; I=ILETT(K)
         %REPEAT
!
         COMREG(24)=16;                ! RETURN CODE
         DUMMY FORMAT=0;        ! DUMMY RECORD FORMAT
         DFHEAD=0
         PUSH(DFHEAD,0,0,0)
         PUSH(DUMMY FORMAT,0,0,DFHEAD); ! FOR BETTER ERROR RECOVERY
         LINE=0; LENGTH=0; Q=1
         R=1;  LEVEL=1
         %CYCLE
            %IF Q>=LENGTH %THEN QMAX=1 %AND READ LINE(0,0)
            P=SS; WARNFLAG=0
            RR=R
            R=R+3
            OLDLINE=LINE
            A(R)=LINE>>8
            A(R+1)=LINE&255
            R=R+2
            COMPARE
            FAULT(102, 0) %IF R>ARSIZE
            %IF HIT=0 %THEN %START
               FAULT(100,ADDR(CC(0)))
               R=RR
            %FINISH %ELSE %START
               %IF A(RR+5)=COMMALT %THEN R=RR %ELSE %START
                  I=R-RR
                  A(RR)=I>>16
                  A(RR+1)=I>>8&255
                  A(RR+2)=I&255
                  %IF A(RR+5)=DECALT %AND LEVEL>=2 %THEN %START
                     TO AR4(DISPLAY(LEVEL),RR)
                     DISPLAY(LEVEL)=RR+6
                  %FINISH
!*DELSTART
                  %IF SMAP#0 %THEN %START
                     NEWLINE;  WRITE(LINE, 5)
                     WRITE(RR,5);  NEWLINE; J=0
                     %CYCLE I=RR, 1, R-1
                        WRITE(A(I), 5)
                     J=J+1
                     %IF J>=20 %THEN NEWLINE %AND J=0
                     %REPEAT
                     NEWLINE
                  %FINISH
!*DELEND
                  %EXIT %IF A(RR+5)=ENDALT %AND 1<=A(RR+6)<=2;! ENDOF PROG OR FILE
                  %IF LEVEL=0 %THEN FAULT(14, 0) %AND %EXIT
               %FINISH
            %FINISH
         %REPEAT
         TO AR8(R,0); R=R+8
         P1SIZE=R
!QOUT         %CYCLE I=0,1,NEXT
!QOUT            A(R+I)=LETT(I)
!QOUT         %REPEAT
!QIN;         *LDTB_X'18000000'
!QIN;         *LDB_NEXT
!QIN;         *LDA_LETT+4
!QIN;         *CYD_0
!QIN;         *LDA_A+4
!QIN;         *INCA_R
!QIN;         *MV_%L=%DR
         DICTBASE=ADDR(A(R))
         R=R+NEXT+1
         ->BEND
%ROUTINE READ LINE(%INTEGER MODE,CHAR)
%ROUTINESPEC GET LINE
%INTEGER DEL, LL, LP
         LL=0;  LP=0; Q=1
         LENGTH=0;  DEL=0
NEXT:    LP=LP+1
         %IF LP>LL %THEN GET LINE %AND LP=1
         I=TLINE(LP)
         %IF MODE=0 %THEN %START
            %IF I='%' %THEN DEL=128 %AND ->NEXT
            DEL=0 %UNLESS 'A'<=I<='Z'
            ->NEXT %IF I=' '
            I=I!DEL
            LENGTH=LENGTH+1; CC(LENGTH)=I
            %IF I='''' %OR I=34 %THEN MODE=1 %AND CHAR=I
         %FINISH %ELSE %START
            LENGTH=LENGTH+1; CC(LENGTH)=I
            %IF I=CHAR %THEN MODE=0
         %FINISH
         ->NEXT %UNLESS I=NL
         %IF CC(LENGTH-1)='C'+128 %THEN LENGTH=LENGTH-2 %AND ->NEXT
         FAULT(101,0) %IF LENGTH>CCSIZE
         %RETURN
%ROUTINE GET LINE
%SYSTEMROUTINESPEC IOCP(%INTEGER A,B)
%INTEGER K
            LL=0
         %IF FILE ADDR=0 %THEN %START;  ! SOURCE NOT A 'CLEAN' FILE
            %UNTIL K=NL %CYCLE
               READ SYMBOL(K)
               TLINE(LL+1)=K
               LL=LL+1
            %REPEAT
         %FINISH %ELSE %START
!QOUT            %MONITOR 9 %IF FILEPTR>=FILE END
!QIN;              %SIGNAL %EVENT 9,1 %IF FILEPTR>=FILE END
            %UNTIL K=NL %OR K=0 %CYCLE
               K=BYTE INTEGER(FILEPTR); ! NEXT CHAR FROM SORCE FILE
               FILE PTR=FILE PTR+1
               TLINE(LL+1)=K
               LL=LL+1
            %REPEAT
         %FINISH
         %IF MODE=0 %AND LL=1 %THEN GET LINE %AND %RETURN
         LINE=LINE+1 %UNLESS MODE=0 %AND LENGTH>0
         %IF LIST#0 %THEN %START
            %IF MODE=0 %AND LENGTH>0 %THEN %C
               PRINTSTRING('     C') %ELSE WRITE(LINE, 5)
!            SPACES(4*LEVEL-MODE)
            %CYCLE K=0,-1,1-4*LEVEL
               TLINE(K)=' '
            %REPEAT
            %IF MODE#0 %THEN TLINE(K)=M''''
            K=K-1
            TLINE(K)=LL+4*LEVEL
            IOCP(15,ADDR(TLINE(K)))
         %FINISH
         %IF FREE FORMAT=0 %AND LL>73 %THEN TLINE(73)=10 %AND LL=73
%END
%END
%ROUTINE COMPARE
%INTEGER I, J, ITEM, RA, RL, RP, RQ, RR, RS, MARKER, ALT, PP, SSL
%SWITCH BIP(999:1033)
         RP=SYMBOL(P)
         RL=LEVEL
         P=P+1
         PP=P; ->COMM;                  !  ROUTINE REALLY STARTS HERE
BIP(999):                               ! REPEATED PHRASE
         A(RR)=ALT; P=PP
COMM:    RQ=Q;  RR=R;                   ! RESET VALUES OF LINE&AR PTRS
         SSL=STRLINK;                   ! SAVE STRING LINK
         ALT=1;                         ! FIRST ALTERNATIVE TO BE TRIED
         RA=SYMBOL(P);  RS=P;           ! RA TO NEXT PHRASE ALTERNATIVE
UPR:     R=R+1
SUCC:                                   ! SUCCESS ON TO NEXT ITEM
         RS=RS+1;                       ! RS=NEXT ALTERNATIVE MEANS THAT
                                        ! THIS ALT HAS BEEN COMPLETED SO
                                        ! EXIT WITH HIT=1
         %IF RS#RA %THEN ->NEXTBR
BIP(1000):                              ! NULL ALWAYS LAST & OK
         A(RR)=ALT
         HIT=1
         %RETURN
NEXTBR:  ITEM=SYMBOL(RS);               ! NEXT BRICK IN THE CURRENT ALT
!         WRITE(ITEM,5) %IF PRINTMAP#0
         %IF ITEM>=1300 %START;         ! BRICK IS A PHRASE TYPE
            P=ITEM; COMPARE
            %IF HIT=0 %THEN ->FAIL %ELSE ->SUCC
         %FINISH
         I=CC(Q);                       ! OBTAIN CURRENT CHARACTER
         ->BIP(ITEM) %IF ITEM>=999;     ! BRICK IS BUILT IN PHRASE
                                        ! BRICK IS LITERAL
         ->FAIL %UNLESS I=CLETT(ITEM+1)
         Q=Q+1
         K=CLETT(ITEM)
         K=K+ITEM
         ITEM=ITEM+2
         %WHILE ITEM<=K %CYCLE
            ->FAIL %UNLESS CC(Q)=CLETT(ITEM)
            Q=Q+1
            ITEM=ITEM+1
         %REPEAT;                       !CHECK IT WITH LITERAL DICT ENTRY
         ->SUCC;                        ! MATCHED SUCCESSFULLY
FAIL:                                   ! FAILURE - NOTE POSITION REACHD
         %IF RA=RP %START;              ! TOTAL FAILURE NO ALT TO TRY
            LEVEL=RL; HIT=0; %RETURN
         %FINISH
         QMAX=Q %IF Q>QMAX
         Q=RQ;  R=RR;                   ! RESET LINE AND A.R. POINTERS
         STRLINK=SSL
         RS=RA;  ALT=ALT+1;             ! MOVE TO NEXT ALT OF PHRASE
         RA=SYMBOL(RA);  ->UPR
BIP(1001):                              ! PHRASE NAME
BIP(1004):                              ! PHRASE OLDNAME
         ->FAIL %UNLESS TRTAB(I)=2
         PNAME(ITEM-1004)
         ->SUCC %IF HIT=1;  ->FAIL
BIP(1002):                              ! PHRASE INTEGER CONSTANT
BIP(1003):                              ! PHRASE CONST
         CONST(ITEM-1003)
         ->FAIL %IF HIT=0
         ->SUCC
BIP(1005):                              ! PHRASE N 
         ->FAIL %UNLESS '0'<=I<='9'
         S=0
         %WHILE '0'<=I<='9' %CYCLE
            S=10*S+I&15
            Q=Q+1; I=CC(Q)
         %REPEAT
         TOAR2(R,S)
         R=R+2; ->SUCC
BIP(1006):                              ! PHRASE S=SEPARATOR
         ->SUCC %IF I=NL
         ->FAIL %UNLESS I=';'
         Q=Q+1; ->SUCC
BIP(1007):
                                        ! PHRASE COMMENT TEXT
         ->TX %IF I=';' %OR I=NL
         ->FAIL %UNLESS I='!' %OR I='|' %OR (I='C'+128 %AND CC(Q+1)=%C
            'O'+128 %AND CC(Q+2)=CC(Q+3)='M'+128 %AND CC(Q+4)='E'+128 %C
            %AND CC(Q+5)='N'+128 %AND CC(Q+6)='T'+128)
         Q=Q+1+6*(I>>7); I=CC(Q)
         Q=Q+1 %AND I=CC(Q) %WHILE NL#I#';'
TX:      Q=Q+1 %IF I=';'
         ->SUCC
BIP(1008):                              ! PHRASE BIGHOLE
         TO AR4(R,0)
         R=R+4; ->SUCC
BIP(1009):                              ! PHRASE N255
         ->FAIL %UNLESS '0'<=I<='9'
         S=0
         %WHILE '0'<=I<='9' %CYCLE
            S=10*S+I&15
            Q=Q+1; I=CC(Q)
         %REPEAT
         ->FAIL %UNLESS 0<=S<=255
         A(R)=S; ->UPR
BIP(1010):                              ! PHRASE HOLE
         MARKER=R;  R=R+2;  ->SUCC
BIP(1011):                              ! PHRASE MARK
         I=R-MARKER
         A(MARKER+1)<-I
         A(MARKER)<-I>>8
         ->SUCC
BIP(1012):                              ! PHRASE READLINE?
         %WHILE I=NL %THEN READLINE(0,0) %AND RQ=1 %AND I=CC(Q)
         ->SUCC
BIP(1013):                              ! PHRASE CHECKIMPS
         ->FAIL %UNLESS IMPS=1;  ->SUCC
BIP(1014):                              ! PHRASE WARN
         %MONITOR; %STOP
BIP(1015):                              ! PHRASE DOWN=NEW TEXT LEVEL
         LEVEL=LEVEL+1
         TO AR4(R,0)
         DISPLAY(LEVEL)=R
         R=R+4
         ->SUCC
BIP(1016):                              ! PHRASE UP 1 TEXTUAL LEVEL
         DISPLAY(LEVEL)=0
         LEVEL=LEVEL-1
         ->SUCC
BIP(1017):                              ! PHRASE LISTON
         LIST=1;  ->SUCC
BIP(1018):                              ! PHRASE LISTOFF
         LIST=0;  ->SUCC
BIP(1019):                              ! PHRASE COLON FOR LABEL
         ->FAIL %UNLESS CC(Q-1)=':'
         ->SUCC
BIP(1020):                              ! PHRASE NOTE CONST
         %IF CTYPE=5 %THEN TOAR4(S-4,STRLINK) %AND STRLINK=S-4
         ->SUCC
BIP(1021):                              ! TRACE FOR ON CONDITIONS
         PARMTRACE=1; ->SUCC
BIP(1022):                              ! SET MNEMONIC
         S=M'    '
         %WHILE 'A'<=I<='Z' %CYCLE
            S=S<<8!I; Q=Q+1; I=CC(Q)
         %REPEAT
         ->FAIL %UNLESS I='_' %AND S#M'    '
         Q=Q+1; ->SUCC
BIP(1023):                              ! PRIMARY FORMAT MNEMOINC
         %CYCLE I=7,1,126
            ->PFND %IF OPC(I)=S
         %REPEAT; ->FAIL
PFND:    ->FAIL %IF 8<=I>>3<=11 %AND I&7<=3
         A(R)=2*I; ->UPR
BIP(1024):                              ! SECONDARY FORMAT MNEMONIC
         %CYCLE I=64,8,88
            %CYCLE J=0,1,3
               ->SFND %IF OPC(I+J)=S
            %REPEAT
         %REPEAT
         ->FAIL
SFND:    A(R)=2*(I+J); ->UPR
BIP(1025):                             ! TERTIARY FORMAT MNEMONIC
         %CYCLE I=1,1,3
            %IF OPC(I)=S %THEN A(R)=2*I %AND ->UPR
         %REPEAT; ->FAIL
BIP(1026):                              ! P(OP)=+,-,&,****,**,*,!!,!,
                                        ! //,/,>>,<<,.,\\,\;
         ->FAIL %UNLESS 32<I<127 %AND %C
            X'80000000'>>(I-32)&X'4237000A'#0
         Q=Q+1
         %IF I='+' %THEN A(R)=1 %AND ->UPR
         %IF I='-' %THEN A(R)=2 %AND ->UPR
         %IF I='&' %THEN A(R)=3 %AND ->UPR
         J=CC(Q)
         %IF I='*' %THEN %START
            %IF J#I %THEN A(R)=6 %AND ->UPR
            %IF CC(Q+1)=I=CC(Q+2) %THEN A(R)=4 %AND Q=Q+3 %AND ->UPR
            A(R)=5; Q=Q+1; ->UPR
         %FINISH
         %IF I='/' %THEN %START
            %IF J#I %THEN A(R)=10 %AND ->UPR
            A(R)=9; Q=Q+1; ->UPR
         %FINISH
         %IF I='!' %THEN %START
            %IF J#I %THEN A(R)=8 %AND ->UPR
            A(R)=7; Q=Q+1; ->UPR
         %FINISH
         %IF I='.' %THEN A(R)=13 %AND ->UPR
         %IF I=J='<' %THEN A(R)=12 %AND Q=Q+1 %AND ->UPR
         %IF I=J='>' %THEN A(R)=11 %AND Q=Q+1 %AND ->UPR
         %IF I='\' %THEN %START
            %IF J#I %THEN A(R)=15 %AND ->SUCC
            Q=Q+1; A(R)=14; ->SUCC
         %FINISH
         ->FAIL
BIP(1027):                              ! PHRASE CHECK UI
         ->SUCC %IF TRTAB(I)=2 %OR I='-'
         ->SUCC %IF X'80000000'>>(I&31)&X'04043000'#0
         ->FAIL
BIP(1028):                              ! P(+')=+,-,\,0
         %IF I='\' %THEN A(R)=3 %AND Q=Q+1 %AND ->UPR
BIP(1029):                              ! P(PLUS')=+,-,0
         %IF I='-' %THEN A(R)=2 %AND Q=Q+1 %AND ->UPR
         %IF I='+' %THEN A(R)=1 %AND Q=Q+1 %AND ->UPR
         A(R)=1032-ITEM; ->UPR
BIP(1030):                              ! P(,')=',',0
!
! THIS IS VERY AWKWARD AS IT MEANS IT IS VERY TO HARD TO FIND
! THE END OF A PARAMETER LIST WITHOUT CHURNING. BY MAKING THIS A BIP
! WE CAN PEEP AHEAD FOR ')' AND FAIL HERE.
!
         %IF I=')' %THEN ->FAIL
         %IF I=',' %THEN A(R)=1 %AND Q=Q+1 %ELSE A(R)=2
         ->UPR
BIP(1031):                              ! PHRASE CHECKTYPE IE ENSURE
                                        ! FIRST LETTER IS(B,H,I,L,R,S) &
                                        ! 3RD LETTER IS (A,L,N,R,T)
         ->FAIL %UNLESS I>128 %AND X'80000000'>>(I&31)&X'20C83000'#0%C
            %AND X'80000000'>>(CC(Q+2)&31)&X'400A2800'#0
         ->SUCC
BIP(1032):                              ! PHRASE CHECK COMPARATOR
         ->FAIL %UNLESS 32<I<=92 %AND %C
            X'80000000'>>(I&31)&X'1004000E'#0
         ->SUCC
BIP(1033):                              ! P(ASSOP)- ==,=,<-,->
         %IF I='=' %THEN %START
            %IF CC(Q+1)='=' %THEN A(R)=1 %AND Q=Q+2 %AND ->UPR
            A(R)=2; Q=Q+1; ->UPR
         %FINISH
         %IF I='<' %AND CC(Q+1)='-' %THEN A(R)=3 %AND Q=Q+2 %AND ->UPR
         %IF I='-' %AND CC(Q+1)='>' %THEN A(R)=4 %AND Q=Q+2 %AND ->UPR
         ->FAIL
%END;                                   !OF ROUTINE 'COMPARE'
%ROUTINE PNAME(%INTEGER MODE)
!***********************************************************************
!*       MODE=0 FOR OLD NAME(ALREADY IN DICT), MODE=1 FOR NEW NAME     *
!***********************************************************************
%CONSTINTEGERARRAY HASH(0:7)=71,47,97,79,29,37,53,59;
%INTEGER JJ, KK, LL, FQ, FS, T, S, I
!QIN;%LONGINTEGER DRDES,ACCDES
         HIT=0;  FQ=Q;  FS=CC(Q)
         %RETURN %UNLESS TRTAB(FS)=2 %AND M'"'#CC(Q+1)#M''''
                                        ! 1ST CHAR MUST BE LETTER
         T=1
         LETT(NEXT+1)=FS; JJ=71*FS
!QOUT         %CYCLE
!QOUT            Q=Q+1
!QOUT            I=CC(Q)
!QOUT            %EXIT %IF TRTAB(I)=0
!QOUT            JJ=JJ+HASH(T) %IF T<=7
!QOUT            T=T+1
!QOUT            LETT(NEXT+T)=I
!QOUT         %REPEAT
CYC:
!QIN;      *LB_Q
!QIN;      *ADB_1
!QIN;      *STB_Q
!QIN;      *LB_(CC+%B)
!QIN;      *LSS_(TRTAB+%B)
!QIN;      *JAT_4,<EXIT>
!QIN;      *STB_I
!QIN;      *LSS_%B;                          ! I TO ACC
!QIN;      *LB_T
!QIN;      *CPB_7
!QIN;      *JCC_2,<SKIP>
!QIN;      *IMY_(HASH+%B)
!QIN;      *IAD_JJ
!QIN;      *ST_JJ
SKIP:
!QIN;      *ADB_1
!QIN;      *STB_T
!QIN;      *LSS_I
!QIN;      *ADB_NEXT
!QIN;      *ST_(LETT+%B)
!QIN;      *J_<CYC>
EXIT:
         LETT(NEXT)=T;                  ! INSERT LENGTH
         S=T+1
         FAULT(103,0) %IF NEXT+S>DSIZE;!DICTIONARY OVERFLOW
         JJ=(JJ+113*T)&NNAMES
!QOUT         %CYCLE KK=JJ, 1, NNAMES
!QOUT            LL=WORD(KK)
!QOUT            ->HOLE %IF LL=0;               ! NAME NOT KNOWN
!QOUT            ->FND %IF STRING(ADDR(LETT(NEXT)))=STRING(ADDR(LETT(LL)))
!QOUT         %REPEAT
!QOUT         %CYCLE KK=0,1,JJ
!QOUT            LL=WORD(KK)
!QOUT            ->HOLE %IF LL=0;               ! NAME NOT KNOWN
!QOUT            ->FND %IF STRING(ADDR(LETT(NEXT)))=STRING(ADDR(LETT(LL)))
!QOUT         %REPEAT
!QIN;      *LDTB_X'18000000'
!QIN;      *LDB_S
!QIN;      *LDA_LETT+4
!QIN;      *STD_DRDES
!QIN;      *INCA_NEXT
!QIN;      *STD_ACCDES
!QIN;      *LB_JJ
CYC1:
!QIN;      *STB_KK
!QIN;      *LB_(WORD+%B)
!QIN;      *JAT_12,<HOLE>
!QIN;      *LSD_ACCDES
!QIN;      *LD_DRDES
!QIN;      *INCA_%B
!QIN;      *CPS_%L=%DR
!QIN;      *JCC_8,<FND>
!QIN;      *LB_KK
!QIN;      *CPIB_NNAMES
!QIN;      *JCC_7,<CYC1>
!QIN;      *LB_0
CYC2:
!QIN;      *STB_KK
!QIN;      *LB_(WORD+%B)
!QIN;      *JAT_12,<HOLE>
!QIN;      *LSD_ACCDES
!QIN;      *LD_DRDES
!QIN;      *INCA_%B
!QIN;      *CPS_%L=%DR
!QIN;      *JCC_8,<FND>
!QIN;      *LB_KK
!QIN;      *CPIB_JJ
!QIN;      *JCC_7,<CYC2>
         FAULT(104, 0);                 ! TOO MANY NAMES
HOLE:    %IF MODE=0 %THEN Q=FQ %AND %RETURN
         WORD(KK)=NEXT;  NEXT=NEXT+S
FND:     LASTAT=FQ;  HIT=1;  LASTNAME=KK
         A(R+1)<-LASTNAME
         A(R)=LASTNAME>>8; R=R+2
         LASTEND=Q
%END


%ROUTINE CONST(%INTEGER MODE)
!***********************************************************************
!*       SYNTAX CHECK AND EVALUATE ALL THE FORMS OF IMP CONSTANT       *
!*       MODE=0 FOR INTEGER CONSTANTS #0 FOR ANY SORT OF CONSTANT      *
!***********************************************************************
%INTEGER Z, DOTSEEN, EBCDIC, FS, CPREC, RR, S, T, SS
!QOUT%LONGREAL X,CVALUE,DUMMY
!QOUT%CONSTLONGREAL TEN=10
!QIN;%LONGLONGREAL X,CVALUE,DUMMY
!QIN;%CONSTLONGLONGREAL TEN=R'41A00000000000000000000000000000'
      CPREC=5;  RR=R;  R=R+1
      DOTSEEN=0;  HIT=0
      CVALUE=0;  DUMMY=0;  FS=CC(Q)
      S=0;  ->N %IF M'0'<=FS<=M'9'
      ->DOT %IF FS='.' %AND MODE=0 %AND '0'<=CC(Q+1)<='9'
                                        ! 1 DIDT MIN
      CTYPE=1;  EBCDIC=0
      ->STR %IF FS=M''''
      ->STR2 %IF FS=34
      ->NOTQUOTE %UNLESS CC(Q+1)=M'''';  Q=Q+2
      ->HEX %IF FS='X'
      ->MULT %IF FS='M'
      ->BIN %IF FS=M'B'
      ->RHEX %IF FS='R' %AND MODE=0
      ->OCT %IF FS='K'
      ->EBCD %IF FS='E'
      %IF FS='C' %THEN EBCDIC=1 %AND ->MULT
      %IF FS='D' %AND MODE=0 %THEN CPREC=7 %AND ->N
      Q=Q-2;  %RETURN
NOTQUOTE:                               ! CHECK FOR E"...."
      %RETURN %UNLESS FS='E' %AND CC(Q+1)=M'"'
      Q=Q+2
EBCD: EBCDIC=1;  Q=Q-1;  I=CC(Q)
STR:  A(RR)=5
      TEXTTEXT(EBCDIC)
      %IF A(RR+5)>1-EBCDIC %THEN CTYPE=5 %AND %RETURN
      R=RR+1
      %IF A(R+4)=0 %THEN S=0 %ELSE S=A(R+5)
      ->IEND
STR2:                                   ! DOUBLE QUOTED STRING
      A(RR)=5;  TEXTTEXT(0)
      CTYPE=5;  %RETURN
HEX:  T=0;                              ! HEX CONSTANTS
      %CYCLE
         I=CC(Q);  Q=Q+1
         %EXIT %IF I=M''''
         T=T+1
         %RETURN %UNLESS ('0'<=I<='9' %OR 'A'<=I<='F') %AND T<17
         %IF T=9 %THEN SS=S %AND S=0
         S=S<<4+I&15+9*I>>6
      %REPEAT
      %IF T>8 %START
         Z=4*(T-8)
         S=S!(SS<<Z)
         SS=SS>>(32-Z);  CPREC=6
      %FINISH
IEND: %IF CPREC=6 %THEN TOAR4(R,SS) %AND R=R+4
      TOAR4(R,S);  R=R+4
      HIT=1 %UNLESS MODE#0 %AND CPREC=6
      A(RR)=CPREC<<4!CTYPE
      %RETURN
RHEX:                                   ! REAL HEX CONSTANTS
      T=0
      %CYCLE
         I=CC(Q);  Q=Q+1
         %IF T&7=0 %AND T#0 %START
            TOAR4(R,S);  R=R+4;  S=0
         %FINISH
         %EXIT %IF I=M'''';  T=T+1
         %RETURN %UNLESS '0'<=I<='9' %OR 'A'<=I<='F'
         S=S<<4+I&15+9*I>>6
      %REPEAT
      %RETURN %UNLESS T=8 %OR T=16 %OR T=32
      %IF T=32 %THEN CPREC=7 %ELSE CPREC=4+T//8
      A(RR)=CPREC<<4!2
      HIT=1;  %RETURN
OCT:                                    ! OCTAL CONSTANTS
      T=0
      %CYCLE
         I=CC(Q);  Q=Q+1;  T=T+1
         %EXIT %IF I=M''''
         %RETURN %UNLESS '0'<=I<='7' %AND T<12
         S=S<<3!(I&7)
      %REPEAT
      ->IEND
MULT: T=0;                              ! MULTIPLE CONSTANTS
      %CYCLE
         I=CC(Q);  Q=Q+1;  T=T+1
         %IF I=M'''' %THEN %START
            %IF CC(Q)#M'''' %THEN %EXIT %ELSE Q=Q+1
         %FINISH
         %RETURN %IF T>=5
         %IF EBCDIC#0 %THEN I=ITOETAB(I)
         S=S<<8!I
      %REPEAT
      ->IEND
BIN:  T=0;                              ! BINARY CONST
      %CYCLE
         I=CC(Q);  Q=Q+1;  T=T+1
         %EXIT %IF I=M''''
         %RETURN %UNLESS '0'<=I<='1' %AND T<33
         S=S<<1!I&1
      %REPEAT
      ->IEND
N:                                      ! CONSTANT STARTS WITH DIGIT
      I=CC(Q)
      %UNTIL I<M'0' %OR I>M'9' %CYCLE
         CVALUE=TEN*CVALUE+(I&15)
         Q=Q+1;  I=CC(Q);               ! ONTO NEXT CHAR
      %REPEAT
      ->ALPHA %UNLESS MODE=0 %AND I='.'
DOT:  Q=Q+1;  X=TEN;  I=CC(Q)
      DOTSEEN=1;                        ! CONSTANT HAS DECIMAL POINT
      %WHILE M'0'<=I<=M'9' %CYCLE
         CVALUE=CVALUE+(I&15)/X
         X=TEN*X;  Q=Q+1;  I=CC(Q)
      %REPEAT
ALPHA:                                  ! TEST FOR EXPONENT
      %IF MODE=0 %AND CC(Q)='@' %THEN %START
         Q=Q+1;  X=CVALUE
         Z=1;  I=CC(Q)
         %IF I='-' %THEN Z=-1
         %IF I='+' %OR I='-' %THEN Q=Q+1
         CONST(2)
         %IF HIT=0 %THEN %RETURN
         HIT=0
         R=RR+1
         S=FROM AR4(R+1)*Z
         %IF S=-99 %THEN CVALUE=0 %ELSE %START
!QIN;           *MPSR_X'8080';              ! MASK OUT REAL OVERFLOW
            %WHILE S>0 %CYCLE
               S=S-1
               CVALUE=CVALUE*TEN
!QIN;              *JAT_15,<FAIL>
            %REPEAT
            %WHILE S<0 %AND CVALUE#0 %CYCLE
               S=S+1
               CVALUE=CVALUE/TEN
            %REPEAT
         %FINISH
      %FINISH
                                        ! SEE IF IT IS INTEGER
      %IF FS='D' %THEN %START
         I=CC(Q)
         %IF I='''' %THEN Q=Q+1 %ELSE %RETURN
         DOTSEEN=1;                     ! ENSURE NOT TAKEN AS INTEGER
      %FINISH
      %IF DOTSEEN=1 %OR CVALUE>IMAX %OR FRACPT(CVALUE)#0 %C
         %THEN CTYPE=2 %ELSE CTYPE=1 %AND S=INT(CVALUE)
      %IF CTYPE=1 %THEN ->IEND
      %IF CPREC=5 %THEN CPREC=6;        ! NO 32 BIT REAL CONSTS
      %IF CPREC=6 %THEN %START
!QIN;        *LSD_CVALUE
!QIN;        *AND_X'FF00000000000000'
!QIN;        *SLSD_CVALUE+8
!QIN;        *AND_X'0080000000000000'
!QIN;        *LUH_%TOS
!QIN;        *RAD_CVALUE
!QIN;        *ST_CVALUE
      %FINISH
      TOAR8(R,CVALUE);  R=R+8
      %IF CPREC=7 %THEN TOAR8(R,LONGREAL(ADDR(CVALUE)+8)) %C
         %AND R=R+8
      A(RR)=CPREC<<4+CTYPE
      HIT=1
FAIL: %END
%ROUTINE TEXTTEXT(%INTEGER EBCDIC)
%INTEGER J, QU, II
         I=CC(Q)
         S=R+4;  R=R+5; HIT=0
         %RETURN %UNLESS I=M'''' %OR I=34;! FAIL UNLESS  INITIAL QUOTE
         QU=I
         Q=Q+1
         %CYCLE
            I=CC(Q)
            %IF EBCDIC#0 %THEN II=ITOETAB(I) %ELSE II=I
            A(R)=II;  R=R+1
            %IF I=QU %THEN %START
               Q=Q+1
               %IF CC(Q)#QU %THEN %EXIT
            %FINISH
            %IF I=10 %THEN READLINE(1,QU) %ELSE Q=Q+1
            FAULT(106,0) %IF R-S>256
         %REPEAT
         R=R-1;  J=R-S-1
         A(S)=J;   HIT=1
%END
BEND:%END;                              ! OF BLOCK CONTAINING PASS 1
         %IF LEVEL>1 %THEN FAULT(15, 0)
         I=0
         NEWLINE
         PRINTCH(13)
         %IF FAULTY=0 %THEN %START
            WRITE(LINE, 5)
            PRINT STRING(' LINES ANALYSED IN')
            WRITE(INT(1000*(CPUTIME-CTIME)),5)
            PRINT STRING(' MSECS  -  SIZE=')
            WRITE(P1SIZE, 5)
            %IF LINE>90 %AND LIST#0 %THEN NEWPAGE %ELSE NEWLINE
         %FINISH %ELSE %START
            PRINTSTRING('CODE GENERATION NOT ATTEMPTED
')
            COMREG(24)=8
            COMREG(47)=FAULTY
            %STOP
         %FINISH
%BEGIN
!***********************************************************************
!*    SECOND OR CODE GENERATING PASS                                   *
!***********************************************************************
%INTEGERARRAY REGISTER, GRUSE, GRAT, GRINF, OLINK(0:7)
%BYTEINTEGERARRAY CODE, GLABUF(0:268)
%INTEGERARRAY PLABS, DESADS, PLINK(0:31), DVHEADS(0:12)
%INTEGERARRAY SET, STACKBASE, RAL, FLAG, L, M, NMDECS, ONWORD, ONINF,%C
         CYCLE, JUMP, LABEL, JROUND, DIAGINF, DISPLAY, SBR, %C
         AUXSBASE, NAMES (0:MAXLEVELS)
%INTEGERARRAY AVL WSP(0:4,0:MAXLEVELS)
%INTEGERARRAYFORMAT CF(0:12*NNAMES)
%INTEGERARRAYNAME CTABLE
%ROUTINESPEC CNOP(%INTEGER I, J)
%ROUTINESPEC PCLOD(%INTEGER FROM, TO)
%ROUTINESPEC PCONST(%INTEGER X)
%ROUTINESPEC PSF1(%INTEGER OPCODE,K,N)
%ROUTINESPEC PF1(%INTEGER OPCODE,KP,KPP,N)
%ROUTINESPEC PSORLF1(%INTEGER OPCODE,KP,KPP,N)
%ROUTINESPEC PF2(%INTEGER OPCODE,H,Q,N,MASK,FILLER)
%ROUTINESPEC PF3(%INTEGER OPCODE,MASK,KPPP,N)
%ROUTINESPEC NOTE CREF(%INTEGER CA)
%INTEGERFNSPEC PARAM DES(%INTEGER PREC)
%INTEGERFNSPEC MAPDES(%INTEGER PREC)
%INTEGERFNSPEC SPECIAL CONSTS(%INTEGER WHICH)
%ROUTINESPEC STORE CONST(%INTEGERNAME D,%INTEGER L,AD)
%ROUTINESPEC DUMP CONSTS
%ROUTINESPEC PLANT(%INTEGER VALUE)
%ROUTINESPEC PLUG(%INTEGER I, J, K, BYTES)
%ROUTINESPEC CODEOUT
%ROUTINESPEC PROLOGUE
%ROUTINESPEC EPILOGUE
%ROUTINESPEC CSS(%INTEGER P)
%ROUTINESPEC LOAD DATA
%ROUTINESPEC ABORT
!*DELSTART
%ROUTINESPEC PRINT USE
!*DELEND
         %CYCLE I=0,1,7
            REGISTER(I)=0; GRUSE(I)=0; GRINF(I)=0
         %REPEAT
         %CYCLE I=0, 1, MAXLEVELS
            SET(I)=0;  STACKBASE(I)=0;  RAL(I)=0
            CYCLE(I)=0;  JUMP(I)=0;  JROUND(I)=0
            LABEL(I)=0;  FLAG(I)=0; SBR(I)=0
            L(I)=0; M(I)=0; DIAGINF(I)=0
            DISPLAY(I)=0; ONWORD(I)=0; ONINF(I)=0
            DVHEADS(I)=0 %IF I<=12
            NAMES(I)=-1
            %CYCLE J=0,1,4
              AVL WSP(J,I)=0
            %REPEAT
         %REPEAT
         CTABLE==ARRAY(ADDR(ASLIST(1)),CF)
         CONST HOLE=0
         DCOMP=PRINTMAP
         LINE=0
         PROLOGUE
         NEXTP=1; LEVEL=1; STMTS=0
         RLEVEL=0; RBASE=0
         %CYCLE
!*DELSTART
            %IF DCOMP#0 %AND CA>CABUF %THEN CODEOUT %AND PRINTUSE
!*DELEND
            I=NEXTP
            NEXTP=NEXTP+A(NEXTP)<<16+A(NEXTP+1)<<8+A(NEXTP+2)
            LINE=A(I+3)<<8+A(I+4)
            %EXIT %IF LINE=0
            STMTS=STMTS+1
            CSS(I+5)
!            CHECK ASL %IF LINE&3=0
         %REPEAT
         LINE=99999
         EPILOGUE
         LOAD DATA
         %STOP
%ROUTINE LOAD DATA
!***********************************************************************
!*       PASS INFORMATION TO LPUT TO ENABLE IT TO GENERATE THE         *
!*       LOADER DATA AND COMPLETE THE PROGRAM FILE.                    *
!***********************************************************************
%INTEGER LANGFLAG,PARMS
         GLACA=(GLACA+7)&(-8)
         USTPTR=(USTPTR+7)&(-8)
         CODE OUT
         CNOP(0, 8)
         DUMP CONSTS
         %IF PARMTRACE=0 %THEN LANGFLAG=6 %ELSE LANGFLAG=1
         LANGFLAG=LANGFLAG<<24
         PARMS=(PARMDIAG<<1!PARMLINE)<<1!PARMTRACE
         FIXED GLA(4)=LANGFLAG!1<<16!(CPRMODE&1)<<8!PARMS;! LANG RLSE & MAINPROG
         I=GLACA-GLACABUF
         %IF INHCODE=0 %THEN %START
            LPUT(2, I, GLACABUF, ADDR(GLABUF(0))) %UNLESS I=0
                                        ! BACK OF GLAP
            LPUT(2, FIXEDGLALEN, 0, ADDR(FIXED GLA(0)));! FRONT OF GLAP
            LPUT(19,2,8,5);             ! RELOCATE GLA ST ADDRESS
            LPUT(19,2,12,4);            ! RELOCATE CODE ST ADDRESS
            I=X'E2E2E2E2'
            LPUT(4, 4, SSTL, ADDR(I))
!
         %FINISH
         SSTL=(SSTL+11)&(-8)
         PRINTSTRING('
CODE')
         WRITE(CA, 6);  PRINTSTRING(' BYTES      GLAP')
         WRITE(GLACA, 3);  PRINTSTRING("+")
         WRITE(USTPTR, 1);  PRINTSTRING(' BYTES      DIAG TABLES')
         WRITE(SSTL, 3);  PRINTSTRING(' BYTES
TOTAL')
         REGISTER(0)=CA;  REGISTER(1)=GLACA
         REGISTER(2)=0
         REGISTER(3)=SSTL
         REGISTER(4)=USTPTR
         K=CA+GLACA+SSTL+USTPTR;  REGISTER(5)=K
         WRITE(K, 5);  PRINTSTRING(' BYTES')
         NEWLINE;  PRINT CH(13);        ! MARKER FOR COMP TO PRINT 
                                        !SUMMARY
         %IF FAULTY=0 %THEN %START
            WRITE(STMTS, 7);  PRINTSTRING(' STATEMENTS COMPILED IN')
            WRITE(INT(1000*(CPUTIME-CTIME)),5)
            PRINTSTRING(' MSECS')
            COMREG(47)=STMTS;           ! NO OF STMTS FOR COMPER
         %FINISH %ELSE %START
            PRINTSTRING('PROGRAM CONTAINS');  WRITE(FAULTY, 2)
            PRINTSTRING(' FAULT'); PRINTSYMBOL('S') %IF FAULTY>1
            COMREG(47)=FAULTY;          ! NO OF FAULTS FOR COMPER
         %FINISH
         NEWLINES(2)
         NEWLINE
         I=0;  I=8 %IF FAULTY#0
         COMREG(24)=I
         %IF INHCODE=0 %THEN LPUT(7, 24, 0, ADDR(REGISTER(0)))
                                        ! SUMMARY INFO..REGISTER AS BUF
         %STOP
%END
!
!***********************************************************************
!*       IMP CODE PLANTING ROUTINES                                    *
!*       CODE AND GLAP ARE PUT INTO THE BUFFERS 'CODE,GLABUF(0:268)'   *
!*       BY A NUMBER OF TRIVIAL ROUTINES.LPUT IS CALLED TO ADD THE     *
!*       BUFFER TO THE OUTPUT FILE. THE BUFFERS ARE BASICALLY 0:255    *
!*       WITH A 12-BYTE MARGIN TO MINIMISE THE NUMBER OF TESTS FOR     *
!*       THE BUFFER FULL CONDITION                                     *
!*                                                                     *
!*       PPCURR(GLACURR) IS THE BUFFER POINTER                         *
!*       CA(GLACA)  IS THE RELATIVE ADDRESS OF THE NEXT BYTE           *
!*       CABUF(GLACABUF) IS CA(GLACA) FOR START OF BUFFER              *
!***********************************************************************
!*DELSTART
%ROUTINE RECODE(%INTEGER S,F,AD)
         %IF S#F %START
            PRINTSTRING('
CODE FOR LINE'); WRITE(LINE,5)
            NCODE(S,F,AD)
         %FINISH
%END
!*DELEND
%ROUTINE CODEOUT
         %IF PPCURR>0 %THEN %START
!*DELSTART
            RECODE(ADDR(CODE(0)), ADDR(CODE(PPCURR)), CABUF) %C
               %IF DCOMP#0
!*DELEND
            LPUT(1, PPCURR, CABUF, ADDR(CODE(0))) %IF INHCODE=0
            PPCURR=0;  CABUF=CA
         %FINISH
%END
%ROUTINE PLANT(%INTEGER HALFWORD)
!***********************************************************************
!*       ADD A HALF WORD OF BINARY TO THE BUFFER                       *
!***********************************************************************
         CODE(PPCURR)<-HALFWORD>>8
         CODE(PPCURR+1)<-HALFWORD
         PPCURR=PPCURR+2
         CA=CA+2
         CODEOUT %IF PPCURR>=256
%END
%ROUTINE PCONST(%INTEGER WORD)
!***********************************************************************
!*       ADD A WORD OF BINARY TO THE BUFFER                            *
!***********************************************************************
%INTEGER I
         %CYCLE I=24,-8,0
            CODE(PPCURR)=WORD>>I&255
            PPCURR=PPCURR+1
         %REPEAT
         CA=CA+4
         CODE OUT %IF PPCURR>=256
%END
%ROUTINE PSF1(%INTEGER OPCODE,K,N)
!***********************************************************************
!*       PLANT THE HALFWORD FORMS OF PRIMARY FORMAT NR INSTRNS         *
!*       IF N IS TOO LARGE FOR THE SHORT FORM PF1 IS CALLED TO PLANT   *
!*       THE CORRESPONDING LONG FORM                                   *
!***********************************************************************
%INTEGER KPP
!         ABORT %UNLESS 0<=K<=2 %AND OPCODE&1=0
         %IF (K=0 %AND -64<=N<=63) %OR (K#0 %AND 0<=N<=511) %START
            %IF K#0 %THEN N=N//4
            CODE(PPCURR)=OPCODE!K>>1
            CODE(PPCURR+1)=(K&1)<<7!N&127
            CA=CA+2
            PPCURR=PPCURR+2
            CODEOUT %IF PPCURR>=256
         %FINISH %ELSE %START
            %IF K=0 %THEN KPP=0 %ELSE KPP=2
            PF1(OPCODE,K>>1<<1,KPP,N)
         %FINISH
%END
%ROUTINE PF1(%INTEGER OPCODE,KP,KPP,N)
!***********************************************************************
!*       PLANT THE NORMAL FORMS OF PRIMARY FORMAT INSTRNS(IE THOSE     *
!*       WHICH DO NOT DEPEND ON THE SIZE OF N)                         *
!***********************************************************************
!         ABORT %UNLESS 0<=KP<=3 %AND 0<=KPP<=7 %AND OPCODE&1=0
         %IF KPP=PC %THEN %START
            %IF N<0 %THEN N=N&X'7FFFFFFF' %AND NOTE CREF(CA)
            N=(N-CA)//2
         %FINISH
         %IF KPP=LNB %OR KPP=XNB %OR KPP=CTB %THEN N=N//4
         CODE(PPCURR)=OPCODE!1
         CODE(PPCURR+1)=X'80'!KP<<5!KPP<<2!(N>>16&3)
         CA=CA+2; PPCURR=PPCURR+2
         %IF KPP<=5 %THEN %START
            CODE(PPCURR)=N>>8&255
            CODE(PPCURR+1)=N&255
            PPCURR=PPCURR+2
            CA=CA+2
         %FINISH
         CODEOUT %IF PPCURR>=256
%END
%ROUTINE PSORLF1(%INTEGER OPCODE,KP,KPP,N)
!***********************************************************************
!*       AS PF1 BUT CUT VALID FORMS TO SHORT FORM                      *
!***********************************************************************
%INTEGER INC
         INC=2
         %IF (KPP=0=KP %AND -64<=N<=63) %OR%C
            (KPP=LNB %AND KP&1=0 %AND 0<=N<=511) %START
            %IF KPP=LNB %THEN KP=1+KP>>1
            %IF KP#0 %THEN N=N//4
            CODE(PPCURR)=OPCODE!KP>>1
            CODE(PPCURR+1)=(KP&1)<<7!(N&127)
         %FINISH %ELSE %START
            %IF KPP=PC %THEN %START
            %IF N<0 %THEN N=N&X'7FFFFFFF' %AND NOTE CREF(CA)
            N=(N-CA)//2
         %FINISH
            %IF (1<<KPP)&B'101100'#0 %THEN N=N//4
            CODE(PPCURR)=OPCODE!1
            CODE(PPCURR+1)=((4!KP)<<3!KPP)<<2!(N>>16&3)
            %IF KPP<=5 %THEN %START
               CODE(PPCURR+2)=N>>8&255
               CODE(PPCURR+3)=N&255
               INC=4
            %FINISH
         %FINISH
         CA=CA+INC; PPCURR=PPCURR+INC
         CODEOUT %IF PPCURR>=256
%END
%ROUTINE PF2(%INTEGER OPCODE,H,Q,N,MASK,FILLER)
!***********************************************************************
!*       PLANT SECONDARY(STORE TO STORE) FORMAT INSTRNS                *
!*       THESE MAY BE 16 OR 32 BIT DEPENDING ON Q                      *
!***********************************************************************
!         ABORT %UNLESS 0<=H<=1 %AND 0<=Q<=1 %AND 0<=N<=127 %C
             %AND OPCODE&1=0
         PLANT(OPCODE<<8!H<<8!Q<<7!N)
         %IF Q#0 %THEN PLANT(MASK<<8!FILLER)
%END
%ROUTINE PF3(%INTEGER OPCODE,MASK,KPPP,N)
!***********************************************************************
!*       PLANT THE TERTIARY(JUMP) FORMAT INSTRUCTIONS                  *
!***********************************************************************
!         ABORT %UNLESS 0<=MASK<=15 %AND 0<=KPPP<=7 %AND OPCODE&1=0
         %IF KPPP=PC %THEN %START
            %IF N<0 %THEN N=N&X'7FFFFFFF' %AND NOTE CREF(CA)
            N=(N-CA)//2
         %FINISH
         CODE(PPCURR)=OPCODE!MASK>>3&1
         CODE(PPCURR+1)=(MASK&7)<<5!KPPP<<2!(N>>16&3)
         PPCURR=PPCURR+2
         CA=CA+2
         %IF KPPP<=5 %THEN %START
            CODE(PPCURR)=N>>8&255
            CODE(PPCURR+1)=N&255
            PPCURR=PPCURR+2; CA=CA+2
         %FINISH
         CODEOUT %IF PPCURR>=256
%END
%ROUTINE NOTE CREF(%INTEGER CA)
!***********************************************************************
!*    NOTE THAT A (PC+N) INSTRUCTION HAS N RELATIVE TO CONST TABLE     *
!*    NOT REATIVE TO CODE. REMEMBER THE ADDRESS OF THE INSTRUCTION     *
!*    SO THAT AN LPUT(18) CORRECTION CAN BE MADE AT END OF COMPILATION *
!***********************************************************************
%RECORDNAME CELL (LISTF)
      CELL==ASLIST(CREFHEAD)
      %IF CREFHEAD=0 %OR CELL_S3#0 %THEN %C
         PUSH(CREFHEAD,CA,0,0) %AND %RETURN
      %IF CELL_S2=0 %THEN CELL_S2=CA %ELSE CELL_S3=CA
%END
%ROUTINE PCLOD(%INTEGER FROM, TO)
!***********************************************************************
!*       PLANT A SERIES OF INTRUNS FROM ARRAY FIXED CODE               *
!***********************************************************************
%INTEGER I
!%CONSTINTEGERARRAY FIXED CODE(0:127)
!         %CYCLE I=FROM, 1, TO
!            PCONST(FIXED CODE(I))
!         %REPEAT
%END
%ROUTINE CNOP(%INTEGER I, J)
         PSF1(JUNC,0,1) %WHILE CA&(J-1)#I
%END
%ROUTINE PGLA(%INTEGER BDRY, L, INF ADR)
%INTEGER I, J
         J=GLACA;  GLACA=(J+BDRY-1)&(-BDRY)
         GLACURR=GLACURR+GLACA-J;       ! COMPLETE THE ROUNDING
         %IF L+GLACURR>256 %THEN %START
            %IF INHCODE=0 %C
               %THEN LPUT(2, GLACURR, GLACABUF, ADDR(GLABUF(0)))
            GLACURR=0;  GLACABUF=GLACA
         %FINISH
         %CYCLE I=0,1,L-1
            GLABUF(GLACURR+I)=BYTE INTEGER(I+INF ADR)
         %REPEAT
         GLACA=GLACA+L;  GLACURR=GLACURR+L
%END
%ROUTINE PLUG(%INTEGER AREA, AT, VALUE, BYTES)
!***********************************************************************
!*       WRITE UP TO ONE WORD INTO OBJECT FILE OUT OF SEQUENCE         *
!***********************************************************************
%INTEGERNAME WCABUF
%INTEGER I, RELAD, BUFAD
         WCABUF==CABUF;  BUFAD=ADDR(CODE(0))
         %IF AREA=2 %THEN WCABUF==GLACABUF %AND BUFAD=ADDR(GLABUF(0))
         RELAD=AT-WCABUF
         %IF RELAD>=0 %AND AREA<=3 %THEN %START
            %CYCLE I=0,1,BYTES-1
              BYTEINTEGER(RELAD+BUFAD+I)<-VALUE>>((BYTES-1-I)<<3)
            %REPEAT
         %FINISH %ELSE %START
            %IF RELAD=-2 %THEN CODEOUT
            %IF INHCODE=0 %THEN LPUT(AREA,BYTES,AT,ADDR(VALUE)+4-BYTES)
!*DELSTART
            NCODE(ADDR(VALUE)+4-BYTES,ADDR(VALUE)+4,AT) %IF DCOMP=1=AREA
!*DELEND
         %FINISH
%END

%INTEGERFN PARAM DES(%INTEGER PREC)
!***********************************************************************
!*    SET UP BNDED L=1 DESRIPTOR FOR PASSING VARIABLE BY REFERENCE     *
!*    ONLY THE TOP HALF IS SET UP                                      *
!***********************************************************************
%INTEGER K,DES
      K=DESADS(PREC)
      %RESULT=K %UNLESS K=0
      %IF PREC=4 %THEN DES=X'58000002' %ELSE DES=PREC<<27!1
      STORE CONST (K,4,ADDR(DES))
      DESADS(PREC)=K
      %RESULT=K
%END
%INTEGERFN MAPDES(%INTEGER PREC)
!***********************************************************************
!*    SET UP 8BIT ZERO ADDRESS UNSCALED BCI DESCRTR FOR MAPPING        *
!***********************************************************************
%INTEGER K,DES0,DES1
      K=DESADS(PREC+8)
      %RESULT=K %UNLESS K=0
      %IF PREC=4 %THEN DES0=X'58000002' %ELSE DES0=X'03000000'!PREC<<27
      DES1=0; STORE CONST(K,8,ADDR(DES0))
      DESADS(PREC+8)=K
      %RESULT=K
%END
%INTEGERFN SPECIAL CONSTS(%INTEGER WHICH)
!***********************************************************************
!*    PUTS CERTAIN SPECIAL CONSTANTS INTO THE CONSTANT TABLE ON        *
!*    DEMAND AND REMEMBERS THEIR POSN TO AVOID SEARCHONG               *
!***********************************************************************
%CONSTINTEGERARRAY SCS(0:5) =           X'40800000',0,
                                        X'41100000',0,
                                        1,0;
%INTEGER K
      K=DESADS(WHICH+16)
      %RESULT=K %UNLESS K=0
      STORE CONST(K,8,ADDR(SCS(2*WHICH)))
      DESADS(WHICH+16)=K
      %RESULT=K
%END
%ROUTINE STORE CONST(%INTEGERNAME D, %INTEGER L, AD)
!***********************************************************************
!*       PUT THE CONSTANT VAL OF LENGTH 'L' INTO THE CONSTANT TABLE    *
!*       A CHECK IS MADE TO SEE IF THE CONSTANT HAS ALREADY            *
!*       BEEN INSERTED IN WHICH CASE THE OLD COPY IS REUSED            *
!***********************************************************************
%INTEGER I, J, K, C1, C2, C3, C4, LP
      LP=L//4;  C2=0;  C3=0;  C4=0
      %CYCLE I=0,1,L-1
         BYTEINTEGER(ADDR(C1)+I)=BYTEINTEGER(AD+I)
      %REPEAT
      %IF PARMOPT#0 %THEN ->SKIP
      K=CONST BTM;                      ! AFTER STRINGS IN CTABLE
      %IF L=4 %THEN %START
         %WHILE K<CONST PTR %CYCLE
            %IF CTABLE(K)=C1 %AND CONSTHOLE#K %C
                %THEN D=4*K!X'80000000' %AND %RETURN
            K=K+1
         %REPEAT
      %FINISH %ELSE %START
         J=CONSTPTR-LP
         %WHILE K<=J %CYCLE
            %IF CTABLE(K)=C1 %AND CTABLE(K+1)=C2 %AND %C
               (CONSTHOLE<K %OR CONSTHOLE>=K+LP) %START
               %IF L=8 %OR (CTABLE(K+2)=C3 %C
                  %AND CTABLE(K+3)=C4) %THEN D=4*K!X'80000000' %C
                  %AND %RETURN
            %FINISH
            K=K+2
         %REPEAT
      %FINISH
SKIP:
      %IF L=4 %AND CONSTHOLE#0 %START
         CTABLE(CONSTHOLE)=C1
         D=4*CONSTHOLE!X'80000000'
         CONSTHOLE=0
         %RETURN
      %FINISH
      %IF L>4 %AND CONST PTR&1#0 %C
         %THEN CONSTHOLE=CONST PTR %AND CONSTPTR=CONST PTR+1
      D=4*CONST PTR!X'80000000'
      CTABLE(CONSTPTR)=C1
      CTABLE(CONSTPTR+1)=C2
      %IF L=16 %THEN CTABLE(CONSTPTR+2)=C2 %C
         %AND CTABLE(CONSTPTR+3)=C4
      CONST PTR=CONST PTR+LP
      %IF CONST PTR>CONST LIMIT %THEN FAULT(107,0)
%END
%ROUTINE GET ENV(%INTEGERNAME HEAD)
!***********************************************************************
!*       SAVE A COPY OF THE REGISTER STATE FOR FUTURE REFERENCE        *
!***********************************************************************
%INTEGER I
         %CYCLE I=0, 1, 7
            PUSH(HEAD, GRINF(I), GRAT(I), I<<8!GRUSE(I)) %C
               %IF GRUSE(I)#0
         %REPEAT
%END
%ROUTINE RESTORE(%INTEGER HEAD)
!***********************************************************************
!*       RESET THE REGISTERS TO ENVIRONMENT IN LIST HEADED BY 'HEAD'   *
!***********************************************************************
%INTEGER I, R, USE, INF, AT
         %CYCLE I=0, 1, 7
            %IF REGISTER(I)>=0 %THEN GRUSE(I)=0 %AND GRINF(I)=0
         %REPEAT
         %WHILE HEAD#0 %CYCLE
            POP(HEAD, INF, AT, I)
            R=I>>8;  USE=I&255
            %IF REGISTER(R)>=0 %THEN GRUSE(R)=USE %AND GRINF(R)=INF
            GRAT(R)=AT
         %REPEAT
%END
         %ROUTINE RELOCATE(%INTEGER GLARAD,VALUE,AREA)
!***********************************************************************
!*      PLANTS A WORD IN THE GLA (IF GLARAD<0) AND ARRANGES TO         *
!*       RELOCATE IT RELATIVE TO AN AREA(CODE=1,GLA=2,CST=4,GST=5      *
!*       IF THE RELOCATION IS RELATIVE TO SYMBOL TABLES THE WORD       *
!*       CAN NOT BE RELOCATED TILL SIZE OF THE CODE(OR GLA) IS KNOWN   *
!***********************************************************************
         %IF GLARAD<0 %THEN PGLA(4,4,ADDR(VALUE)) %AND GLARAD=GLACA-4
         LPUT(19,2,GLARAD,AREA)
         %END
         %ROUTINE GXREF(%STRING(31) NAME,%INTEGER MODE,XTRA,AT)
!***********************************************************************
!*       ASK LPUT TO ARRANGE FOR A DOUBLE WORD AT 'AT' IN THE GLA      *
!*       TO CONTAIN A DESCRIPTOR FOR NAME 'NAME'.                      *
!*       MODE=0 STATIC CODE XREF                                       *
!*       MODE=1 DYNAMIC CODE XREF                                      *
!*       MODE=2 DATA XREF XTRA=MINIMIUM LENGTH                         *
!***********************************************************************
%INTEGER LPUTNO
         %IF MODE=2 %THEN LPUTNO=15 %ELSE LPUTNO=MODE+12
         LPUT(LPUTNO,XTRA,AT,ADDR(NAME))
         %END
%ROUTINE CXREF(%STRING(255) NAME,%INTEGER MODE,XTRA,%INTEGERNAME AT)
!***********************************************************************
!*       CREATE A ZEROED AREA IN THE GLA AND CALL GXREF TO GET         *
!*       IT FILLED AT LOAD TIME WITH INFORMATION ON AN EXTERNAL OBJECT *
!*       PARAMETERS ARE AS FOR GXREF.                                  *
!***********************************************************************
%INTEGER Z1,Z2
         Z1=0; Z2=0
         PGLA(8,8,ADDR(Z1));       ! 2 ZERO WORDS
         AT=GLACA-8
         GXREF(NAME,MODE,XTRA,AT)
         %END
%ROUTINE CODEDES(%INTEGERNAME AT)
!***********************************************************************
!*       PUT A CODE DESCRIPTOR INTO THE PLT FOR USE BY DEFINE EP       *
!***********************************************************************
%INTEGER DESC1,DESC2
         DESC1=X'E1000000'; DESC2=0
         %IF CDCOUNT=0 %THEN FIXED GLA(0)=DESC1 %AND AT=0 %C
                        %ELSE PGLA(8,8,ADDR(DESC1)) %AND AT=GLACA-8
         CDCOUNT=CDCOUNT+1
%END
%ROUTINE DEFINE EP(%STRING(255)NAME, %INTEGER ADR,AT,MAIN)
!***********************************************************************
!*       AN EP CONSISTS OF A CODE DESCRIPTOR IN THE GLA(PLT) OF        *
!*       FILE CONTAINING THE EP. LPUT IS TOLD ABOUT THIS AND THE LOADER*
!*       ARRANGES TO PUT A DESCRIPTOR-DESCRIPTOR TO THE CODE-DESC      *
!*        IN THE GLA OF ANY FILE REFERENCES THIS EP. THIS FIRST WORD   *
!*       OF ICLS PLT IS THE MAIN EP AND WE MIMIC THIS AS FAR AS POSS   *
!***********************************************************************
         %IF AT=0 %THEN FIXED GLA(1)=ADR %ELSE PLUG(2,AT+4,ADR,4)
         RELOCATE(AT+4,ADR,1)
         LPUT(11,MAIN<<31!2,AT,ADDR(NAME)) %IF NAME#''
%END
%ROUTINE PROLOGUE
!***********************************************************************
!*       GENERATES THE SUBROUTINE THAT ALWAYS  ARE REQUIRED ONTO THE   *
!*       FRONT OF THE OBJECT PROGRAM WHERE THEY ARE DIRECTLY ADDRESABLE*
!***********************************************************************
%INTEGERFNSPEC STRINGIN(%INTEGER POS)
%ROUTINESPEC ERR EXIT(%INTEGER A, B, C)
%INTEGER I, K, L, STCA
         I=X'C2C2C2C2'
         LPUT(4,4,0,ADDR(I))
         SSTL=4
         %CYCLE I=0, 1, 31
            PLABS(I)=0; PLINK(I)=0
            DESADS(I)=0
         %REPEAT
!
! GENERATE THE FIXED-FLOAT CONSTANTS THAT MAY BE NEEDED
!
         PLABS(1)=CA
         %CYCLE I=0, 1, 1
            PCONST(UNASSPAT)
         %REPEAT
!
! GENERATE THE RUN TIME ERROR ROUTINE :-
! MDIAGS FOR NR IS %ROUTINE MDIAGS(%INT PC,LNB,ERROR,XTRA)
! PC IS A DUMMY (SEG FIELD ONLY USED) EXCEPT AFTER CONTINGENCY
! ON ENTRY TO THIS SUBROUTINE ERROR IS IN ACC. XTRA HAS BEEN STACKED
! ENTRY HAS BEEN BY JLK SO RETURN ADDRESS ALSO STACKED
!
!RTF      LB     TOS               RETURN ADDRESS TO B
!         SLB    TOS               XTRA TO B,RETURN ADDR TO TOS
!         PRCL   4                 TO PLANT PARAMS
!         JLK    +1                 STACK DUMMY PC
!         STLN   TOS               LNB AS SECOND PARAMETER
!         ST     TOS               ERROR NO AS THIRD PARAM
!         STB    TOS               XTRA AS FOURTH PARAMETER
!         LXN    (LNB+4)           POINTER TO GLA
!         RALN   9                 TO STORED LNB
!         CALL   ((XNB+10))        VIA XREF=DESCRIPTOR-DESCRIPTOR
!         J      TOS               BACK AFTER A MONITOR
!
!         PLUG(1,0,X'1B800000'!CA>>1,4);! FILL JUMP TO ERROR SEQUENCE
         PLABS(2)=CA
         PF1(LB,0,TOS,0)
         PF1(SLB,0,TOS,0)
         PSF1(PRCL,0,4)
         PSF1(JLK,0,1)
         PF1(STLN,0,TOS,0)
         PF1(ST,0,TOS,0)
         PF1(STB,0,TOS,0)
         PSF1(LXN,1,16)
         PSF1(RALN,0,9)
         PF1(CALL,2,XNB,40)
         PF1(JUNC,0,TOS,0)
!
! SUBROUTINE TO ADVANCE STACK FRONT BY B WORDS AND FILL WITH UNASSIGNED
!
!        JAT   12,*+13                   B IS ZERO
!        LSS   TOS
!        STSF  TOS
!        LDTB  STRING DECRIPTOR         SET UP DESCRIPTOR FOR MVL
!        LDA   TOS
!        ASF   B                        ADVANCE BY B WORDS
!        MYB   4                        CHANGE B TO BYTES
!        LDB   B                        AND MOVE TO BOUND FIELD
!        MVL   L=DR                     AND FILL WITH X80S
!        ST    TOS
!        J     TOS                      RETURN
!
         %IF PARMCHK=1 %THEN %START;      ! ONLY REQUIRED WITH CHKING
            CNOP(0,4); K=CA
            PCONST(X'58000000')
            PLABS(4)=CA
            PF3(JAT,12,0,13)
            PF1(LSS,0,TOS,0)
            PF1(STSF,0,TOS,0)
            PF1(LDTB,0,PC,K)
            PF1(LDA,0,TOS,0)
            PF1(ASF,0,BREG,0)
            PSF1(MYB,0,4)
            PF1(LDB,0,BREG,0)
            PF2(MVL,1,1,0,0,UNASSPAT&255)
            PF1(ST,0,TOS,0)
            PF1(JUNC,0,TOS,0)
         %FINISH
!
! SOME ERROR ROUTINES
!
         ERR EXIT(5, X'801', 0) %IF PARMOPT#0; ! UNASSIGNED VARIABLE
         ERR EXIT(6,  X'504', 0);               ! SWITCH LABEL UNSET
         ERR EXIT(7, X'505', 1);               ! ILLEGEAL EXPONENTIATION
         ERR EXIT(8,X'201', 0) %IF PARMOPT#0;  ! EXCESS BLOCKS
         ERR EXIT(9, X'601', 1);               ! CAPACITY EXCEEDED
         ERR EXIT(10,21, 0) ;              ! NO RESULT
         ERR EXIT(11,X'501', 0) %IF PARMOPT#0;    ! CYCLE NOT VALID
         ERR EXIT(12,X'701',0);                ! RES FAILS
         ERR EXIT(13,36,0) %IF PARMOPT#0;   ! WRONG NO OF PARAMS
!
! PUT THE STRINGS ONTO THE FRONT OF CONSTANT AREA
!
         CTABLE(0)=X'18000001'
         CTABLE(1)=4
         STCA=8; L=ADDR(CTABLE(0))
         CONST PTR=2;                   ! IN CASE NO STRINGS
         %WHILE STRLINK#0 %CYCLE
            I=STRLINK; STRLINK=FROM AR4(I)
            TO AR4(I,STRINGIN(I+4));          ! CHANGE LINK TO STRING ADDR
         %REPEAT
         STRLINK=X'80000000'
         CONST BTM=CONST PTR
         %IF PARMOPT#0 %THEN CTABLE(CONST PTR)=M'IDIA' %AND %C
               CONST PTR=CONST PTR+1
         GXREF(MDEP,0,2,40)
         LEVEL=1
         %CYCLE I=0,1,31
            %IF PLINK(I)#0 %THEN CLEAR LIST(PLINK(I))
         %REPEAT
         %RETURN
%INTEGERFN STRINGIN(%INTEGER POS)
!***********************************************************************
!*    PUT A STRING INTO THE CONSTANT AREA CHECKING FOR DUPLICATES      *
!***********************************************************************
%INTEGER J,K,IND,HD
%RECORDNAME CELL(LISTF)
      K=A(POS)
      %IF K=0 %THEN %RESULT=0
      IND=K&31; HD=PLINK(IND)
      %WHILE HD#0 %CYCLE
         CELL==ASLIST(HD)
         %IF CELL_S1=K %AND STRING(L+CELL_S2)=STRING(ADDR(A(POS))) %C
            %THEN %RESULT=CELL_S2-4
         HD=CELL_LINK
      %REPEAT
      HD=STCA
      BYTEINTEGER(L+STCA)=K; STCA=STCA+1
      %CYCLE J=POS+1,1,POS+K
         BYTE INTEGER(L+STCA)=A(J)
         STCA=STCA+1
      %REPEAT
      CONST PTR=((STCA+7)&(-8))>>2
      PUSH(PLINK(IND),K,HD,0)
      %RESULT=HD-4
%END
%ROUTINE ERR EXIT(%INTEGER LAB, ERRNO, MODE)
!***********************************************************************
!*       MODE=0 FOR DUMMY(ZERO) XTRA - MODE=1 XTRA IN ACC              *
!***********************************************************************
         PLABS(LAB)=CA
         %IF MODE=0 %THEN PSF1(LSS,0,0)
         PSF1(SLSS,0,ERRNO)
         PSF1(JLK,0,(PLABS(2)-CA)//2)
%END
%END
%ROUTINE CSS(%INTEGER P)
%ROUTINESPEC MERGE INFO
%ROUTINESPEC REDUCE ENV(%INTEGERNAME HEAD)
%ROUTINESPEC ENTER JUMP(%INTEGER MASK,STAD,FLAG)
%ROUTINESPEC ENTER LAB(%INTEGER M,FLAG)
%ROUTINESPEC REMOVE LAB(%INTEGER LAB)
%ROUTINESPEC CEND(%INTEGER KKK)
%ROUTINESPEC CBPAIR(%INTEGERNAME LB,UB)
%ROUTINESPEC CCOND(%INTEGER A,B)
%ROUTINESPEC CHECK STOF
%INTEGERFNSPEC REVERSE(%INTEGER MASK)
%ROUTINESPEC SET LINE
%INTEGERFNSPEC SET XORYNB(%INTEGER WHICH,RLEVEL)
%INTEGERFNSPEC XORYNB(%INTEGER USE,INF)
%ROUTINESPEC GET IN ACC(%INTEGER ACC,SIZE,AC,AREA,DISP)
%INTEGERFNSPEC AREA CODE
%ROUTINESPEC CUI(%INTEGER CODE)
%ROUTINESPEC ASSIGN(%INTEGER A,B)
%ROUTINESPEC CSTART(%INTEGER MODE)
%ROUTINESPEC CREATE AH(%INTEGER MODE)
%ROUTINESPEC TORP(%INTEGERNAME HEAD,BOT,NOPS)
%ROUTINESPEC CSEXP(%INTEGER REG,MODE)
%ROUTINESPEC CSTREXP(%INTEGER A,B)
%ROUTINESPEC CRES(%INTEGER LAB)
%ROUTINESPEC EXPOP(%INTEGER A,B,C,D)
%ROUTINESPEC  TEST APP(%INTEGERNAME NUM)
%ROUTINESPEC SKIP EXP
%ROUTINESPEC SKIP APP
%ROUTINESPEC NO APP
%INTEGERFNSPEC DOPE VECTOR(%INTEGER A,B,%INTEGERNAME C,D)
%ROUTINESPEC DECLARE ARRAYS(%INTEGER A,B)
%ROUTINESPEC DECLARE SCALARS(%INTEGER A,B)
%ROUTINESPEC MAKE DECS(%INTEGER Q)
%ROUTINESPEC SAVE AUX STACK
%ROUTINESPEC RESET AUX STACK
%ROUTINESPEC CRSPEC(%INTEGER M)
%ROUTINESPEC CFPDEL
%ROUTINESPEC CLT
%ROUTINESPEC CQN(%INTEGER P)
%ROUTINESPEC GET WSP(%INTEGERNAME PLACE,%INTEGER SIZE)
%ROUTINESPEC RETURN WSP(%INTEGER PLACE,SIZE)
%INTEGERFNSPEC TSEXP(%INTEGERNAME VALUE)
%ROUTINESPEC CRCALL(%INTEGER RTNAME)
%ROUTINESPEC NAMEOP(%INTEGER Z,REG,SIZE,NAMEP)
%ROUTINESPEC CNAME(%INTEGER Z,REG)
%ROUTINESPEC CANAME(%INTEGER Z,BS,DP)
%ROUTINESPEC CSNAME(%INTEGER Z,REG)
%ROUTINESPEC TEST ASS(%INTEGER REG,TYPE,SIZE)
%ROUTINESPEC COPY TAG(%INTEGER KK)
%ROUTINESPEC REDUCE TAG
%ROUTINESPEC REPLACE TAG (%INTEGER KK)
%ROUTINESPEC RT JUMP(%INTEGER CODE,%INTEGERNAME L)
%ROUTINESPEC STORE TAG(%INTEGER KK,SLINK)
%ROUTINESPEC UNPACK
%ROUTINESPEC PACK(%INTEGERNAME PTYPE)
%ROUTINESPEC DIAG POINTER(%INTEGER LEVEL)
%ROUTINESPEC RDISPLAY(%INTEGER KK)
%ROUTINESPEC RHEAD(%INTEGER KK)
%ROUTINESPEC ODD ALIGN
%INTEGERFNSPEC PTR OFFSET(%INTEGER RLEV)
%ROUTINESPEC PPJ(%INTEGER MASK,N)
%ROUTINESPEC CRFORMAT(%INTEGERNAME OPHEAD)
%INTEGERFNSPEC DISPLACEMENT(%INTEGER LINK)
%INTEGERFNSPEC COPY RECORD TAG(%INTEGERNAME SUBS)
%ROUTINESPEC SAVE IRS
%ROUTINESPEC COPY DR
%ROUTINESPEC BOOT OUT(%INTEGER REG)
%ROUTINESPEC CHANGE RD(%INTEGER REG)
%ROUTINESPEC FORGET(%INTEGER REG)
%ROUTINESPEC REMEMBER
%ROUTINESPEC NOTE ASSMENT(%INTEGER REG,ASSOP,VAR)
%SWITCH SW(1:24)
%RECORDFORMAT RD(%BYTEINTEGER UPTYPE,PTYPE,XB,FLAG,%C
   %INTEGER D,XTRA)
%INTEGER SNDISP,ACC,K,KFORM,STNAME
%INTEGER TCELL,ADISP,JJ,JJJ,KK,QQ,MARKER,REPORTUI,XDISP, %C
      BASE,AREA,ACCESS,DISP,EXTRN, CURR INST,VALUE,STRINGL, %C
      PTYPE,I,J,OLDI,USEBITS,TWSPHEAD,KKK, %C
      MARKIU,MARKUI,MARKC,MARKE,MARKR
%INTEGER LITL,ROUT,NAM,ARR,PREC,TYPE
         CURR INST=0
         TWSPHEAD=0
         %INTEGERARRAY SGRUSE,SGRINF(0:7)
         ->SW(A(P))
SW(24):                               ! REDUNDANT SEP
SW(2):                                ! <CMARK> <COMMENT TEXT>
CSSEXIT:  LAST INST=CURR INST
         %WHILE TWSPHEAD#0 %CYCLE
            POP(TWSPHEAD,JJ,KK,QQ)
            RETURN WSP(JJ,KK)
         %REPEAT
         %RETURN
SW(1):                                !(UI)(S)
         FAULT(57,0) %UNLESS LEVEL>=2
         MARKER=P+1+A(P+1)<<8+A(P+2)
         P=P+3
         ->LABFND %IF A(MARKER)=1
         SET LINE; MASK=15
         %IF A(MARKER)=2 %THEN CUI(0) %AND ->CSSEXIT
         MARKE=0; MARKR=0
         MARKUI=P; MARKIU=MARKER+1
         MARKC=MARKIU+1
         ->CONEXP %IF A(MARKER)=3
         ->WHILE
LABFND:  ->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
         ENTER LAB(FROM AR2(P+3),0); ->CSSEXIT
SW(5):                                 ! %CYCLE
         FAULT(57,0) %UNLESS LEVEL>=2
!***********************************************************************
!*       THE LAYOUT OF AN ENTRY ON THE CYCLE LIST IS:-                 *
!*        S1= CNAME<<16!LABEL NO                                       *
!*        S2= EL<<16! CYCLE WORK AREA DISPLACEMENT FROM RBASE          *
!*        S3= NOT USED                                                 *
!*        WHERE :-                                                     *
!*        CNAME= CYCLE CONTROL NAME                                    *
!*        LABEL= NO OF INTERNAL LABEL FOR REPEAT TO JUMP TO            *
!*          EL=LABEL NO FOR EXIT STATEMENT (TOP BIT SET WHEN USED)     *
!***********************************************************************
         %BEGIN
         %INTEGER PP,Q,INC,NAME,TNAME,PASS,OPEN,XTRA,KK
         SET LINE
         INC=0; XTRA=0
         OPEN=A(P+1)-1; P=P+2; PP=P
         %IF OPEN #0 %THEN %START;      ! OPEN CYCLES ENTRY AS WHILE
            PASS=X'10000000'
         %FINISH %ELSE %START
            NAME=FROM AR2(P)
            P=P+2
            TNAME = TAGS(NAME)
            PASS=NAME<<16
            COPY TAG (NAME)
            FAULT(25,NAME) %UNLESS TYPE=1 %AND PREC=5 %AND ROUT=ARR=0
            WARN(4,NAME) %UNLESS I=RLEVEL
            GET WSP(INC,2);             ! WORKAREA TO INC
            POP(TWSPHEAD,JJ,KK,Q);      ! MUST NOT BE FREED BEFORE REPEAT
            Q=P; SKIP EXP; JJ=P;        ! Q TO 1ST EXP, JJ TO SECOND
            %IF PARMOPT=0 %AND IMOD(TSEXP(XTRA))=1 %AND XTRA#0 %START
               XTRA=XTRA<<16
            %FINISH %ELSE %START
               P=JJ
               CSEXP(ACCR,X'51');           ! INCREMENT EXPRESSION TO ACC
               PSF1(ST,1,INC);          ! AND TO WORK AREA
            %FINISH
            %IF PARMOPT#0 %THEN PPJ(20,11);  ! FAULT ZERO INCREMENT
            JJ=P
            %IF PARMOPT=0 %AND IMOD(TSEXP(KK))=1 %AND KK#0 %START
               XTRA=XTRA!(KK&X'FFFF')
            %FINISH %ELSE %START
               P=JJ
               CSEXP(ACCR,X'51');           ! FINAL VALUE TO ACC
               PSF1(ST,1,INC+4);        ! AND TO WORK AREA
            %FINISH
            P=Q; CSEXP(BREG,X'51');         ! INITIAL VALUE TO B
            %IF PARMOPT#0 %THEN %START; ! VALIDATE CYCLE
               PSF1(LSS,1,INC+4);       ! FINAL
               PF1(ISB,0,BREG,0);       ! FINAL-INITIAL
               PSF1(IMDV,1,INC);        ! (F-I)//INC
               PPJ(22,11);              ! -VE REPITIONS
               PF1(LSS,0,TOS,0);        ! REMAINDER
               PPJ(36,11);              ! IS NOT ZERO
            %FINISH
            GRUSE(ACCR)=0
            GRUSE(DR)=0
            GRUSE(XNB)=0
         %FINISH
         PLABEL=PLABEL-1; PASS=PASS!PLABEL
         ENTER LAB(PLABEL,0)
         %IF OPEN#0 %THEN PLABEL=PLABEL-1 %ELSE %START
            COPY TAG(NAME)
            BASE=I; AREA=-1
            PSORLF1(STB,2*NAM,AREA CODE,K)
            NOTE ASSMENT(BREG,2,NAME)
         %FINISH
         XLABEL=XLABEL-1
         PUSH(CYCLE(LEVEL),PASS,XLABEL<<16!INC,XTRA)
         %END; ->CSSEXIT
!
SW(6):                                 ! REPEAT
         FAULT(57,0) %UNLESS LEVEL>=2
         %BEGIN
         %INTEGER NAME,TOPREG,DSP,WSPL,LAB,XTRA,ELABEL,EUSED, %C
                 IT,IV,FT,FV,CELL
         %SWITCH CTYPE(0:3)
         EUSED=0
         %IF -1<=FROM1(CYCLE(LEVEL))<=0 %THEN FAULT(1,0) %AND ->BEND
         POP(CYCLE(LEVEL),J,DSP,XTRA)
         ELABEL=DSP>>16&X'7FFF';    ! FOR ANY EXITS
         EUSED=DSP>>31
         DSP=DSP&X'7FFF'; LAB=J&X'FFFF'
         ->CTYPE(J>>28)
CTYPE(0):                              ! STEP CYCLE LOCAL SCALAR CONTROL
         SET LINE
         TOPREG=3; WSPL=2; NAME=J>>16
         %IF PARMCHK=1 %THEN %START;     ! CHECK CYCLE ENTERD OK
            PSF1(LSS,1,DSP)
            TEST ASS(ACCR,1,4)
         %FINISH
!
! SET UP CYCLE PARAMETERS FROM WKAREA UNLESS THEY ARE CONSTANT
!
         IT=1; FT=1
         IV=DSP; FV=DSP+4
         %IF XTRA>>16#0 %THEN IT=0 %AND IV=XTRA&X'FFFF0000'//X'10000'
         %IF XTRA&X'FFFF' #0 %THEN FT=0 %AND FV=XTRA<<16//X'10000'
!
! GET CONTROL TO B DIRECTLY
!
         COPY TAG(NAME)
         BASE=I; AREA=-1
         ACCESS=2*NAM; DISP=K
         NAMEOP(2,BREG,4,NAME)
!
! NOW PLANT CODE TO DO THE TEST AND BRANCH.
!
         %IF IT=0=FT %AND IV=-1 %AND FV=1 %START
            CELL=FIND3(LAB,LABEL(LEVEL))
            XTRA=FROM1(CELL)&X'FFFFFF'
            REPLACE1(CELL,XTRA!X'1000000')
            XTRA=(XTRA-CA)//2
            PSF1(DEBJ,0,XTRA)
         %FINISH %ELSE %START
            %IF IT=0 %AND IV=1 %THEN PSF1(CPIB,FT,FV) %ELSE %START
               PSF1(CPB,FT,FV);            ! COMPARE B WITH FINAL
               PSF1(ADB,IT,IV);             ! ADB INCREMENT(CC UNALTERED)
            %FINISH
            ENTER JUMP(7,LAB,0);            ! BNE <BEGIN ANOTHER TRAVERSE>
         %FINISH
         GRUSE(BREG)=0
         RETURN WSP(DSP,WSPL);           ! WORKAREA TO FREE LIST
         %IF PARMCHK=1 %THEN %START
            PF1(LSS,0,PC,PLABS(1))
            PSF1(ST,1,DSP);             ! INC TO UNASSGND
            GRUSE(ACCR)=0
         %FINISH
         ->BEND
CTYPE(1):                               ! '%WHILE' '%CYCLE'
         ENTER JUMP(15,LAB,0);          ! UNCONDITIONALLY TO WHILE CLAUS
         ENTER LAB(LAB-1,B'111');       ! CONDITIONAL/REPLACE ENV
        ->BEND
CTYPE(2):                               ! '%UNTIL' ... '%CYCLE'
         LINE=DSP
         SET LINE
         P=XTRA
         CCOND(1,LAB)
BEND:    %IF EUSED#0 %THEN ENTER LAB(ELABEL,B'11')
         REMOVE LAB(LAB)
         %END; ->CSSEXIT
SW(23):                                ! '%CONTROL' (CONST)
         J=FROM AR4(P+2)
         CODEOUT
         DCOMP=J>>28; ->CSSEXIT
!
SW(3):                                 ! (%IU)(COND)%THEN(UI)(ELSE')
         FAULT(57,0) %UNLESS LEVEL>=2
         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
         SET LINE
CONEXP:  %BEGIN
!***********************************************************************
!*       THIS BLOCK COMPILES CONDITIONAL EXPRESSIONS.IT REQUIRES THE   *
!*       FOLLOWING GLOBAL POINTERS 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)                               *
!***********************************************************************
         MARKIU=A(MARKIU);              ! ALT OF IU 1=%IF,2=%UNLESS
         KKK=-1
         %IF MARKR>0 %AND A(MARKR)<=2 %START;! '%START' OR '%THENSTART'
            KKK=SFLABEL-1
            P=MARKC; CCOND(MARKIU,KKK)
            CSTART(1)
            ->BEND
         %FINISH
         %IF A(MARKUI)=2 %AND A(MARKUI+3)=2 %THEN %C
            KKK=FROM AR2(MARKUI+1);     ! UI = SIMPLE LABEL
!
         %IF A(MARKUI)=8 %AND CYCLE(LEVEL)#0 %START; ! VALID EXIT
            KKK=FROM2(CYCLE(LEVEL))
            REPLACE2(CYCLE(LEVEL),KKK!X'80000000')
            KKK=KKK>>16&X'7FFF'
         %FINISH
!
         %IF KKK>=0 %THEN %START;  ! FIRST UI IS'->'<LABEL>
            NMDECS(LEVEL)=NMDECS(LEVEL)!1
            P=MARKC; CCOND(3-MARKIU,KKK)
            %IF MARKE>0 %AND A(MARKE)<=2 %START; ! THERE IS AN ELSE CLAUSE
               %IF A(MARKE)=1 %THEN CSTART(0) %ELSE %START
                  P=MARKE+1; MASK=15
                  CUI(0)
               %FINISH
            %FINISH
            ->BEND
         %FINISH
!
         PLABEL=PLABEL-1; KKK=PLABEL
         P=MARKC; CCOND(MARKIU,KKK)
         P=MARKUI; MASK=15; CUI(1)
         %UNLESS MARKE>0 %AND A(MARKE)<=2 %START;   ! UNLESS %ELSE FOLLOWS
            ENTER LAB(KKK,B'11'!REPORTUI<<2); ->BEND;! CONDITIONAL&MERGE
         %FINISH
!
         %IF A(MARKE)=1 %THEN %START;      ! '%ELSESTART'
            %IF REPORTUI=0 %THEN %C
               ENTER JUMP(15,SFLABEL-1,B'10');! LONG JUMP BUT SAVE ENV
            CSTART(2)
            ENTER LAB(KKK,B'111');         ! CONDITIONAL & REPLACE ENV
         %FINISH %ELSE %START;             ! '%ELSE<UI>'
            P=MARKE+1
            PLABEL=PLABEL-1; JJJ=PLABEL
            %IF REPORTUI=0 %THEN %C
               ENTER JUMP(15,JJJ,B'11');   ! SHORT JUMP AND SAVE ENV
            ENTER LAB(KKK,B'111');         ! CONDITIONAL REPLACE ENV
            MASK=15; CUI(2)
            ENTER LAB(JJJ,B'11'!REPORTUI<<2);! CONDITIONAL MERGE
         %FINISH
BEND:    %END; ->CSSEXIT
SW(4):
         %BEGIN;                       ! '%FINISH(ELSE')(S)
         %INTEGER J,CODE,CYC,FLAB
         POP(SBR(LEVEL),CODE,FLAB,CYC)
         %IF CODE=3 %THEN NMDECS(LEVEL)=NMDECS(LEVEL)&X'FFFFFFEF'
         %IF CODE<0 %THEN FAULT(51,0) %AND ->BEND
         %IF CYC#CYCLE(LEVEL) %THEN FAULT(52,0)
!
         %IF A(P+1)<=2 %THEN %START;    ! %ELSE CLAUSE PRESENT
            FAULT(47,0) %UNLESS CODE=1; ! DANGLING ELSE
            %IF A(P+1)=1 %THEN %START;  ! %ELSE %START
!
! PLANT A ROUND NEXT START-FINISH %UNLESS PREVIOUS INSTRUCTION WAS ->
!
               ENTER JUMP(15,SFLABEL-1,B'10') %IF LAST INST=0
               CSTART(2)
            %FINISH %ELSE %START;       ! %ELSE (UI)
               %IF LAST INST=0 %THEN %START
                  PLABEL=PLABEL-1; J=PLABEL
                  ENTER JUMP(15,J,B'11')
               %FINISH
               P=P+2
!
! PLANT THE LABEL FOR THE JUMP ROUND THE START FINISH BLOCK JUST ENDED
! THE LABEL IS CONDITIONAL ON THERE HAVING BEEN A JUMP. ENVIRONMENTS ARE
! MERGED UNLESS THE PREVIOUS INSTN IS A -> ETC WHEN ENV IS REPLACED
!
               ENTER LAB(FLAB,B'011'!LAST INST<<2)
               SET LINE; MASK=15
               %IF LAST INST#0 %THEN CUI(0) %AND ->BEND
               CUI(2); FLAB=J
               LAST INST=REPORT UI
            %FINISH
!
         %FINISH %ELSE %START
            ->BEND %IF CODE=0
         %FINISH
!
         ENTER LAB(FLAB,B'011'!LAST INST<<2)
BEND:    %END; ->CSSEXIT
SWITCH:  %BEGIN;                       ! SWITCH LABEL
         %INTEGER HEAD,BASEPT,BP,FNAME
         %INTEGERARRAY BITS(0:2)
         FORGET(-1)
         FNAME=FROM AR2(P+3)
         ->SERR %UNLESS A(P)=1 %AND A(P+5)=1;  ! 1ST OF UI + APP
         ->SERR %UNLESS A(P+9)#3 %AND A(P+10)=2 %AND A(P+11)=X'51'
         ->SERR %UNLESS A(P+16)=2=A(P+17);     !NO R.OF.EXP. OR R.OF.APP
         ->SERR %UNLESS A(P+18)=2;             ! NO ENAME
         COPY TAG(FNAME)
         HEAD=K
         %IF OLDI#LEVEL %OR TYPE#6 %THEN FAULT(4,FNAME) %AND ->BEND
         FROM123(HEAD,BASEPT,KKK,KK);      ! EXTRACT TABLE ADDR,LB & UB
         MLINK(HEAD);                      ! K POINTS TO BIT LIST
         JJ=FROM AR4(P+12)
         JJ=-JJ %IF A(P+9)=2
         ->INBD %IF KKK<=JJ<=KK
SERR:    FAULT(5,FNAME); ->BEND
INBD:    Q=JJ-KKK
         %WHILE Q>=96 %THEN MLINK(HEAD) %AND Q=Q-96
!
! ASLIST(HEAD) IS THE START OF 96 BIT ENTRY IN THE BIT LIST
! CHECK BIT NO Q TO SEE IF LABEL ALREADY SET AND THEN SET BIT Q
!
         FROM123(HEAD,BITS(0),BITS(1),BITS(2))
         QQ=Q>>5;                      ! RIGHT WORD
         Q=Q&31; JJJ=1<<Q;             ! BIT IN WORD
         FAULT(6,FNAME) %UNLESS BITS(QQ)&JJJ=0
         BITS(QQ)=BITS(QQ)!JJJ
         REPLACE123(HEAD,BITS(0),BITS(1),BITS(2))
!
! OPTIMISED (ARR=2) SWITCHES USE HALFWORDS AND BASEPT POINTS TO THE
! ZEROETH NOT THE FIRST ELEMENT
!
         BP=4//ARR
         %IF ARR=2 %THEN KKK=0
         Q=CA-BASEPT
         QQ=BASEPT+(JJ-KKK)*BP;         ! REL POSITION OF LABEL
         PLUG(1,QQ,Q,BP);                ! OVERWRITE THE WORD IN TABLE
         %IF ARR=2 %AND Q>X'FFFF' %THEN ABORT
BEND:    %END;   ->CSSEXIT
SW(7):                                 ! (%WU)(SC)(COND)(RESTOFWU)
         FAULT(57,0) %UNLESS LEVEL>=2
         MARKIU=P+1;                   ! TO WHILE/UNTIL
         MARKC=MARKIU+3;               ! TO (SC)(COND)
         MARKR=P+2+FROM AR2(P+2);      ! TO RESTOF WU
         MARKUI=MARKR+1;               ! TO P(UI) IF ANY
WHILE:   %BEGIN
         %INTEGER L1,L2
         MARKIU=A(MARKIU);             ! =1 FOR'WHILE' =2 FOR'UNTIL'
         SFLABEL=SFLABEL-1
         L1=SFLABEL
         PLABEL=PLABEL-1;              ! RESERVE 2 LABELS
         L2=PLABEL
         ->WCYCLE %IF MARKR>0 %AND A(MARKR)<=2
         SET LINE
         ENTER LAB(L1,0);             ! UNCONDITIONAL LAB FOR REPEAT
         %IF MARKIU=1 %THEN %START
            P=MARKC
            CCOND(1,L2)
         %FINISH
!
         MASK=15; P=MARKUI
         CUI(1)
!
         %IF MARKIU=1 %THEN %START
            ENTER JUMP(15,L1,0);        ! UNCODITIONALLY TO WHILE COND
            ENTER LAB(L2,B'111')
         %FINISH %ELSE %START
            P=MARKC; CCOND(1,L1);       ! UNTIL CONDITION AT END
         %FINISH
         ->BEND
WCYCLE:
!***********************************************************************
!*       WHILE CYCLES JUST LIKE %WHILE...%THEN<UI> BUT %UNTIL CYCLES   *
!*       STORE AWWAY AN A.R. TO BE COMPILED TO PUT THE                 *
!*       CONDITION AT THE END. IF IT WAS PUT AT THE BEGINING 2 EXTRA   *
!*       JUMPS ARE NEEDED TO OBTAIN THE CORRECT EFFECT.                *
!*       WHILE CYCLES:- S1=FLAG(=1)<<28! LABEL FOR REPITITION          *
!*                      S2=LAB FOR EXIT<<16 ! LAB FOR TERMINATION      *
!*                      S3= NOT USED                                   *
!*       UNTIL CYCLES:- S1=FLAG(=2)<<28! LAB FOR REPITITION            *
!*                      S2=LAB FOR EXIT<<16! LINE NO OF CONDITION      *
!*                      S3= POINTER TO AR FOR CONDITION                *
!***********************************************************************
         XLABEL=XLABEL-1
         ENTER LAB(L1,0);                 ! UNCONDITIONAL FOR REPEAT
         %IF MARKIU=2 %THEN %START;       ! '%UNTIL....%CYCLE'
            L2=LINE
         %FINISH %ELSE %START;            ! '%WHILE...%CYCLE
            SET LINE
            P=MARKC
            CCOND(1,L1-1)
            SFLABEL=SFLABEL-1
         %FINISH
         PUSH(CYCLE(LEVEL),L1!MARKIU<<28,XLABEL<<16!L2,MARKC)
BEND:      %END; ->CSSEXIT
!
SW(8):                                 ! SIMPLE DECLN
         FAULT(57,0) %UNLESS LEVEL>=2
         FAULT(40,0) %IF NMDECS(LEVEL)&1#0
         P=P+5;CLT;ROUT=0; LITL=0
         %IF A(P)#1 %THEN %START;      ! ARRAY DECLARATIONS
            FAULT(70,0) %IF TYPE=5 %AND ACC=0
            NAM=0
            SET LINE
            QQ=2-A(P+1); P=P+2;        ! QQ=1 FOR ARRAYFORMATS
            DECLARE ARRAYS(QQ,0)
           %FINISH
         ->CSSEXIT
!
SW(9):                                 ! %END
         %BEGIN
         %SWITCH S(1:5)
         -> S(A(P+1))
S(1):                                  ! ENDOFPROGRAM
S(2):                                  ! ENDOFFILE
         %IF CPRMODE=0 %THEN CPRMODE=2
         FAULT(15,0) %UNLESS LEVEL+CPRMODE=3
         FAULT(56,0) %UNLESS A(P+1)=CPRMODE
         CEND(CPRMODE)
         ->BEND
S(3):                                  ! ENDOFLIST
         LIST=0;
         ->BEND
S(4):                                  ! END
         CEND(FLAG(LEVEL))
BEND:    %END
         ->CSSEXIT
!
SW(11):
         %BEGIN
         %INTEGER MARKER1,KK,KKK
         %STRING(34)XNAME
         P=P+1; MARKER1=FROM AR2(P)+P; ! (SEX)(RT)(SPEC')(NAME)(FPP)
AGN:     Q=P; KK=FROM AR2(MARKER1+5);  ! KK ON NAME
         EXTRN=A(P+2)
         LITL=EXTRN&3
         %IF A(MARKER1)=1 %THEN %START;! P<%SPEC'>='%SPEC'
            P=P+2;  CRSPEC(1-EXTRN>>2);! 0 FOR ROUTINESPEC
                                       ! 1 FOR EXTERNAL (ETC) SPEC
            ->BEND
         %FINISH
         COPY TAG(KK)
         %IF OLDI=LEVEL %THEN %START
            %IF CPRMODE=0 %THEN CPRMODE=2;! FLAG AS FILE OF ROUTINES
!
            %IF (CPRMODE=2 %AND LEVEL=1) %START
               %IF EXTRN=3 %THEN EXTRN=2
               XNAME<-STRING(DICTBASE+WORD(KK))
               %IF EXTRN=1 %THEN XNAME<-'S#'.XNAME
               %IF EXTRN=4 %THEN XNAME=''
               JJ=FROM1(K);             ! CODE DESCRIPTOR REL ADDR
               %IF EXTRN#4 %THEN USEBITS=2
               DEFINE EP(XNAME,CA,JJ,0)
               %IF JJ#0 %THEN PSF1(INCA,0,-JJ)
            %FINISH %ELSE %START;    ! EXTERNALS IN PRGM OR WRNG LEVEL
               FAULT(55,KK) %UNLESS EXTRN=4; EXTRN=4
            %FINISH
            %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=(A(P)-1)<<1;         ! SET NAME ARRAY BIT FOR MAPS
               PACK(KKK);               ! AND STORE PTYPE IN KKK
            %FINISH
         %FINISH
         %UNLESS OLDI=LEVEL %AND J=15 %AND PTYPE=KKK %START
            P=Q+2; CRSPEC(0); P=Q; ->AGN
         %FINISH
         %BEGIN
         %INTEGER PTR,PTYPEP
         J=0; REPLACE TAG(KK);!  BODY GIVEN SO UPDATE TAGS INFO
         JJ=K; PLABEL=PLABEL-1
         %UNLESS COMPILER=1 %OR (CPRMODE=2 %AND LEVEL=1) %START
            %IF JROUND(LEVEL+1)=0 %START;    ! NOT JUMP OUTSTANDING
               JROUND(LEVEL+1)=PLABEL
               ENTER JUMP(15,PLABEL,0)
            %FINISH
         %FINISH
         PTYPEP=PTYPE
         P=MARKER1+6
         RHEAD(KK)
         N=20
         %IF A(P+1)=1 %THEN %START;   ! FORMAL PARAMETERS TO DEAL WITH
            %UNTIL A(P)=2 %CYCLE;     ! UNTIL NO MORE FP-PART
               P=P+2
               CFPDEL
               PTR=P
               %UNTIL A(PTR-1)=2 %CYCLE;! CYCLE DOWN NAMELIST
                  MLINK(JJ)
                  %IF JJ#0 %THEN %START
                     FROM12(JJ,J,JJJ);! EXTRACT PTYPE XTRA INFO
                     %UNLESS J=PTYPE %AND (PTYPE#5 %OR JJJ>>16=ACC) %C
                        %THEN FAULT(9,FROM AR2(PTR))
                  %FINISH %ELSE FAULT(8,KK);! MORE FPS THAN IN SPEC
                  PTR=PTR+3
               %REPEAT
               DECLARE SCALARS(0,0)
            %REPEAT;              ! UNTIL NO MORE FP-PART
            N=(N+3)&(-4);         ! TO WORD BOUNDARY AFTER ALL SYSTEM
                                  ! STANDARD PARAMETERS HAVE BEEN DECLARED
         %FINISH
         MLINK(JJ)
         FAULT(10,KK) %UNLESS JJ=0
         PTYPE=PTYPEP
         %IF PTYPE&X'F0F'=5 %THEN N=N+8;! STR FNS RESULT PARAM IS STACKED
                                        ! AS XTRA PARM JUST BEFORE DISPLAY
         RDISPLAY(KK)
         MAKE DECS(MARKER1+1)
         %END
BEND:    %END; ->CSSEXIT
!
SW(13):                                !REALS(LN)
         ALL LONG=A(P+1)&1;->CSSEXIT
!
SW(14):                                !%BEGIN
%BEGIN
         PTYPE=0
         %IF LEVEL=1 %AND RLEVEL=0 %AND CPRMODE=0 %START
            CODE DES(JJ)
            DEFINE EP(MAINEP, CA, JJ, 1)
            RLEVEL=1; RBASE=1
            L(1)=0; M(1)=0; DIAGINF(1)=0; AUXSBASE(1)=0
            CPRMODE=1
            N=24;  NMAX=N
            FORGET(-1)
            DIAG POINTER(LEVEL+1)
!
! LAY DOWN A CONTINGENCY AGAINST ERROR IN PROGRAM
! IE COMPILE EXTERNAL CALL 'S#SIGNAL(0,PC,LNB,FLAG)'
!
            CXREF(SIGEP,0,2,SIGREFDIS); ! REFERENCE TO SIGNAL
!
! THE CODE PLANTED IS AS FOLLOWS:-
!         STD   (LNB+3)              SAVE DESCRIPTOG TO GLA(PLT)
!         LXN   (LNB+4)               TO GLA(PLT)
!         STLN  (XNB+5)               SAVE LNB FOR STOP SEQUENCE
!         ASF   1                    FOR REPORT WORD
!         PRCL  4                    TO PLANT PARAMS
!         LSS   0
!         ST    TOS                  FIRST PARAM
!         JLK   +3                   2ND PARAM AND JUMP ROUND NEXT INSTR
!         JCC   15,PERM15            TO RECOVERY SUBROUTINE
!         STLN  TOS                  3RD PARAM
!         LDTB  WORD DES             DESC USED FOR 'INTEGER()'
!         LDA   (XNB+5)              ADD IN LNB
!         INCA  +20                  TO WORD 5 OF FRAME(REPORT WORD)
!         STD   TOS                  4TH AND LAST PARAM
!         RALN  10
!         CALL  SIGREF
!
            PSF1(STD,1,12)
            PSF1(LXN,1,16)
            PF1(STLN,0,XNB,20)
!            PSF1(ASF,0,1)
!
! THE NEXT 8 INSTRUCTIONS ARE REQUIRED TO SET SF 6 WORDS IN FRONT OF LNB
! AN ASF 1 WORKS AS WELL EXCEPT FOR K-STAND ALONE WHEN THERE MAY BE
! A USELESS REDUNDANT DESCRIPTOR ON THE STACK
!
            PF1(STLN,0,TOS,0)
            PF1(LSS,0,TOS,0)
            PSF1(IAD,0,24)
            PF1(STSF,0,TOS,0)
            PF1(ISB,0,TOS,0)
            PSF1(ISH,0,-2)
            PF1(ST,0,BREG,0)
            PF1(ASF,0,BREG,0)
!
            PSF1(PRCL,0,4)
            PSF1(LSS,0,0)
            PF1(ST,0,TOS,0)
            PSF1(JLK,0,3)
            PPJ(15,15)
            PF1(STLN,0,TOS,0)
            PF1(LDTB,0,PC,PARAM DES(5))
            PF1(LDA,0,XNB,20)
            PSF1(INCA,0,20)
            PF1(STD,0,TOS,0)
            PSF1(RALN,0,10)
            PF1(CALL,2,XNB,SIGREFDIS)
!
! SET THE PROGRAM MASK TO MASK OUT UNDERFLOW AND ALLOW ALL OTHER INTS
!
!         MPSR  X'40C0'
!
            PF1(MPSR,0,0,X'40C0')
            PTYPE=1
         %FINISH %ELSE SET LINE;       ! SO 'ENTERED FROM LINE' IS OK
         RHEAD(-1)
         RDISPLAY(-1)
         MAKE DECS(P+1)
%END
         ->CSSEXIT
!
SW(15):
                                        ! '%ON'(EVENT')(N)(NLIST)'%START'
         FAULT(57,0) %UNLESS LEVEL>=2
         FAULT(40,0) %IF NMDECS(LEVEL)&1#0
         NMDECS(LEVEL)=NMDECS(LEVEL)!X'11';! NO MORE DECS AND IN ONCOND
         %IF STACK=0 %THEN %START
            SAVE AUX STACK
            DISP=AUXSBASE(LEVEL)
            PSF1(LSS,2,DISP);           ! SAVE TOP OF AUX STACK
            PSF1(ST,1,DISP+12)
         %FINISH
         GRUSE(ACCR)=0
         ENTER JUMP(15,SFLABEL-1,B'10');! JUMP ROUND ON BODY
         CSTART(3)
!
         P=P+2; JJ=0;                   ! SET UP A BITMASK IN JJ
         %UNTIL A(P-1)=2 %CYCLE;        ! UNTIL NO MORE NLIST
            KK=A(P)
            FAULT(26,0) %UNLESS 1<=KK<=14
            JJ=JJ!1<<(KK-1)
            P=P+2
         %REPEAT
         KK=CA; PGLA(4,4,ADDR(CA))
         RELOCATE(GLACA-4,KK,1);        ! ENTRY ADDRESS IN PLT
         ONWORD(LEVEL)=JJ<<18!(GLACA-4)
         FORGET(-1)
         PSF1(ST,1,N);                  ! STORE EVENT,SUBEVENT&LINE
         ONINF(LEVEL)=N; N=N+8
         %IF STACK=0 %THEN %START
            PSF1(LSS,1,DISP+12);        ! RESET AUX STACK TOP
            PSF1(ST,2,DISP)
         %FINISH
         ->CSSEXIT
SW(16):  
         FAULT(57,0) %UNLESS LEVEL>=2
         %BEGIN;                       ! %SWITCH (SWITCH LIST)
         %INTEGER Q,RANGE,KKK,KK,LB,PP,D0,D1,OPHEAD,V
         Q=P
         FAULT(56,0) %UNLESS LEVEL>=2
         CNOP(0,4)
         PLABEL=PLABEL-1
         ENTER JUMP(15,PLABEL,B'10')
         ARR=1
         %IF PARMOPT=0 %AND(COMPILER#0 %OR P1SIZE<128000) %THEN ARR=2
         %UNTIL A(Q)=2 %CYCLE;         ! UNTIL NO'REST OF SW LIST'
            P=P+3
            %WHILE A(P)=1 %THEN P=P+3
            CBPAIR(LB,KK);             ! LOWER BOUND TO LB UPPER TO KK
            RANGE=(KK-LB+1)
            %IF CA-2*LB<0 %THEN ARR=1;  ! ZEROETH ELEMENT OFF FRONT
            PTYPE=X'56'+ARR<<8;         ! WORD LABEL ARRAY
            PP=P; P=Q+1
            %UNTIL A(P-1)=2 %CYCLE;    !  DOWN NAMELIST
               K=FROM AR2(P)
               P=P+3
               OPHEAD=0; R=LB
!
! SET UP A BIT LIST (96 BITS PER CELL) TO CHECK FOR SWITCH LABELS
! SET TWICE
!
               %UNTIL R>KK %CYCLE
                  PUSH(OPHEAD,0,0,0)
                  R=R+96
               %REPEAT
!
! FOR CHECKING MODE USE A BOUNDED WORD DESCRIPTOR AND WORD SIZE
! ENTRIES PRESET TO "SW LABEL NOT SET". OPTIMISEING USE 2BYTE STRING
! ARRAYS WITH BASE SET TO ZEROETH ELEMENT
!
               %IF ARR=1 %THEN %START
                  D0=5<<27!RANGE
                  D1=CA
               %FINISH %ELSE %START
                  D0=X'58000002'; D1=CA-2*LB
               %FINISH
               PGLA(8,8,ADDR(D0))
               SNDISP=GLACA>>2-2;       ! WORD PLT DISP
               RELOCATE(GLACA-4,D1,1);  ! RELOCATE RELATIVE TO CODE
               PUSH(OPHEAD,D1,LB,KK)
               KFORM=0; ACC=4
               J=1; STORE TAG(K,OPHEAD)
!
!THE TABLE WILL CONSIST OF RELATIVE DISPLACEMENTS FROM THE TABLE HEAD
! TO THE LABEL POSN. SET ALL TO GO TO PLAB(6) INITIALLY
!
               V=PLABS(6)-D1
               %CYCLE KKK=LB,1,KK
                  %IF ARR=1 %THEN PCONST(V) %ELSE PLANT(0)
               %REPEAT
            %REPEAT;                   ! FOR ANY MORE NAMES IN NAMELIST
            Q=PP; P=Q
         %REPEAT;                      ! UNTIL A(Q)=2
         ENTER LAB(PLABEL,B'110')
         %END;->CSSEXIT
!
SW(17):       LIST=1; ->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. LPUT ARRANGES    *
!*       FOR THE LOADER TO RELOCATE THE HEADERS.                       *
!*      EXTERNALS ARE IDENTICAL WITH OWN BUT ALSO HAVE A DATA EP DEFN  *
!*       IN THE LOAD DATA SO THEY CAN BE FOUND AT LOAD TIME            *
!*      EXTRINSICS HAVE A DATA REFERENCE AND A DUMMY HEADER IN THE GLA *
!*      THE LOADER USES THE FORMER TO RELOCATE THE LATTER.             *
!***********************************************************************
%ROUTINESPEC CLEAR(%INTEGER L)
%ROUTINESPEC STAG(%INTEGER J,DATALEN)
%ROUTINESPEC XTRACT CONST(%INTEGER CONTYPE,CONPREC)
%ROUTINESPEC INIT SPACE(%INTEGER A,B)
%INTEGER LENGTH,BP,PP,SIGN,CBASE,MODE,UICONST,ICONST,TAGDISP,EPTYPE, %C
         EPDISP,AH1,AH2,AH3,AH4,AD,FNAM,FINF,SPOINT,CONSTSFOUND,CPREC,%C
         EXTRN,NNAMES,MARK,LPUTP,MARKER1,LB,CTYPE,CONSTP,FORMAT,PTSIZE
%LONGREAL RCONST,LRCONST
%STRING(255) SCONST,NAMTXT
%INTEGERNAME STPTR
         LPUTP=5; STPTR==USTPTR;     ! NORMAL CASE GLA SYMBOLTABLES
!         FAULT(40,0) %IF NMDECS&1#0
         EXTRN=A(P+1)&3; LITL=EXTRN
         %IF LITL<=1 %THEN LITL=LITL!!1
         KFORM=0; SNDISP=0
         %IF EXTRN=0 %THEN LPUTP=4 %AND STPTR==SSTL
         P=P+3; CBASE=0
         MODE=A(P-1);                ! MODE =1 FOR NORMAL OWNS
         ->RECORD %IF MODE>1;        ! MODE =2 FOR OWN RECORDS
         CLT;                        ! MODE =3 FOR OWN RECORD ARRAYS
         %IF A(P)=1 %THEN CQN(P+1) %ELSE ARR=1 %AND NAM=0
         %IF TYPE=5 %AND ACC=0=NAM %THEN FAULT(70,0) %AND ACC=2
         ROUT=0; PACK(PTYPE)
         -> NON SCALAR %IF ARR#0 %AND NAM=0
         P=P+1
         %UNTIL A(MARK)=2 %CYCLE;    ! UNTIL <RESTOFOWNDEC> NULL
         MARK= P+1+FROM AR2(P+1)
         NNAMES=1
         PP=P+3; P=PP+2;             ! PP ON FIRST NAME'
         %WHILE A(P)=1 %THEN NNAMES=NNAMES+1 %AND P=P+3
         P=P+1;                         ! P ON CONST'
!
! OBTAIN THE INITIAL CONSTANT,ITS TYPE(CTYPE) AND SIGN(SIGN)
!
         ICONST=0; UICONST=0
         RCONST=0; LRCONST=0; SCONST=''
         SIGN=3; CTYPE=TYPE; CONSTSFOUND=0; CPREC=PREC
         %IF NAM#0 %THEN CTYPE=1 %AND CPREC=5
!
         %IF A(P)=1 %THEN %START;     ! CONSTANT GIVEN
            P=P+1
            XTRACT CONST(CTYPE,CPREC)
         %FINISH
!
         %UNTIL NNAMES=0 %CYCLE;         ! DOWN <NAMELIST>
            J=0; K=FROM AR2(PP)
            NAMTXT=STRING(DICTBASE+WORD(K))
            %IF NAM#0 %THEN %START;     ! OWNNAMES AND ARRAYNAMES
               %IF EXTRN=3 %THEN FAULT(46,K);! NO EXTRINSIC NAMES
               UICONST=X'FFFF'!PREC<<27
               PGLA(8,ACC,ADDR(UICONST))
               TAGDISP=GLACA-ACC; EPDISP=TAGDISP
            %FINISH %ELSE %START
            %IF TYPE=5 %THEN %START;         ! STRING
               QQ=STPTR; AD=ADDR(SCONST)
               %IF EXTRN=3 %THEN %START;     ! EXTRINSIC STRINGS
                  AH3=0; AH2=PREC<<27!ACC;   ! DUMMY STRING HEADER
               %FINISH %ELSE %START
                  LPUT(LPUTP,ACC,QQ,AD) %IF INHCODE=0;! O/P STRING
                  STPTR=(STPTR+ACC+3)&(-4)
                  AH3=QQ; AH2=3<<27!ACC
               %FINISH
               PGLA(8,8,ADDR(AH2))
               TAGDISP=GLACA-8
               %IF EXTRN=3 %THEN GXREF(NAMTXT,2,2<<24!ACC,TAGDISP+4) %C
                  %ELSE RELOCATE(TAGDISP+4,AH3,LPUTP)
               EPTYPE=5; EPDISP=QQ;        ! DATA IN GLA SYMBOL TABLES
            %FINISH %ELSE %START;           ! INTEGER & REAL
               %IF EXTRN=3 %THEN %START;    ! EXTRINSICS
                  PTYPE=PTYPE!1<<10;        ! EXTRINSICS VIA PTR
                  AH2=PREC<<27; AH3=0
                  PGLA(8,8,ADDR(AH2))
                  TAGDISP=GLACA-8
                  GXREF(NAMTXT,2,2<<24!ACC,TAGDISP+4)
               %FINISH %ELSE %START;        ! OWN,EXTERNAL&CONST
                  %IF TYPE=2 %THEN %START
                     AD=ADDR(RCONST)
                  %FINISH %ELSE %START;     ! INTEGER VARIABLES
                     AD=ADDR(ICONST)+4-ACC
                  %FINISH
                  %IF EXTRN#0 %THEN %C
                     PGLA(ACC,ACC,AD);      ! PUT CONSTANT INTO GLA
                  TAGDISP=GLACA-ACC;        ! OFFSET OF VAR FOR TAGS
                  EPDISP=TAGDISP;           ! AND FOR ENTRY DEFN
                  EPTYPE=2;                ! DATA IN ADRESSABLE GLA
               %FINISH
            %FINISH
            %FINISH
            STAG(TAGDISP,ACC)
            %IF EXTRN=0=NAM %START;         ! CONST = LITERAL
               %IF PREC<=6 %THEN REPLACE2(TAGS(K),INTEGER(AD&(-4)));! BYTES!
               %IF PREC=6 %THEN REPLACE3(TAGS(K),INTEGER(AD+4))
               %IF PREC=7 %THEN REPLACE3(TAGS(K),ADDR(A(CONSTP)))
            %FINISH
            PP=PP+3
            NNAMES=NNAMES-1
         %REPEAT
         P=MARK
         %REPEAT
         ->BEND
RECORD:                                ! <XOWN>'%RECORD'<NAMELIST>
!***********************************************************************
!*       NO INITIALISATION OF OWN RECORDS ALLOWED SO THEY ARE ALL      *
!*       CLEARED TO ZERO.                                              *
!***********************************************************************
         MARKER1=P+1+FROM AR2(P+1);        ! TO FORMAT NAME
         FNAM=FROM AR2(MARKER1)
         COPYTAG(FNAM)
         FINF=TCELL
         %IF PTYPE#4 %THEN FAULT(62,FNAM) %AND ->BEND
         PTYPE=X'133'!LITL<<14
         KFORM=FINF; UNPACK
         %IF MODE=3 %THEN FORMAT=2-A(P) %AND P=P+2 %AND ->RECIN
         P=P+1; BP=ACC;                 ! SIZE OF RECORD FROM FORMAT
         PTYPE=X'33'; J=0
         %IF A(P-1)#3 %THEN CQN(P-1) %AND PACK(PTYPE)
         P=P+1; PTSIZE=ACC;           ! SIZE OF HOLE FOR POINTER
         %UNTIL A(P)=2 %CYCLE
            P=P+1; K=FROM AR2(P)
            NAMTXT=STRING(DICTBASE+WORD(K))
            %IF NAM#0 %THEN %START;     ! OWNNAMES AND ARRAYNAMES
               %IF EXTRN=3 %THEN FAULT(46,K);! NO EXTRINSIC NAMES
               UICONST=X'FFFF'!PREC<<27
               PGLA(8,PTSIZE,ADDR(UICONST))
               TAGDISP=GLACA-PTSIZE; EPDISP=TAGDISP
            %FINISH %ELSE %START
               %IF EXTRN=3 %THEN %START;     ! EXTRINISIC
                  PTYPE=PTYPE!X'400';      ! FORCE NAM=1 (IE VIA POINTER)
                  AH2=X'18000000'+BP
                  AH3=0
                  PGLA(8,8,ADDR(AH2))
                  TAGDISP=GLACA-8
                  GXREF(NAMTXT,2,2<<24!BP,TAGDISP+4); ! RELOCATE BY EXTERNAL
               %FINISH %ELSE %START
                  EPDISP=(GLACA+15)&(-8)
                  AH3=EPDISP
                  AH2=X'18000000'+BP;      ! TOP WORD OFDESRCIPTOR
                  PGLA(8,4,ADDR(AH2));     ! ADDED 18MAR76 TO FIX BUG
                  RELOCATE(-1,AH3,2);      ! PUT DISP INTO GLA
                  TAGDISP=EPDISP;          ! AND RELOCATE REL APPROPIATE AREA
                  EPTYPE=2;                ! DATA IN GLA TABLES
                  I=0; ICONST=0
                  %WHILE I<BP %CYCLE
                     PGLA(4,4,ADDR(ICONST))
                     I=I+4
                  %REPEAT
               %FINISH
            %FINISH
            ACC=BP;                     ! ACC TO SIZE OF RECORD
            STAG(TAGDISP,BP)
            P=P+2
         %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 CLEARED TO ZERO                         *
!***********************************************************************
         P=P+1
         FORMAT=2-A(P)
RECIN:   PP=P+1; P=P+3; NNAMES=1
         K=FROM AR2(PP)
         NAMTXT=STRING(DICTBASE+WORD(K))
         %IF TYPE>=3 %THEN BP=ACC %ELSE BP=BYTES(PREC)
         AH4=12+DOPE VECTOR(TYPE,BP,QQ,LB)
         %IF LB=0 %AND J=1 %AND TYPE<=2 %THEN %C
            ARR=2 %AND PACK (PTYPE)
         LENGTH=QQ//BP;                 ! NO OF ELEMENTS
         CONSTS FOUND=0
         SPOINT=STPTR
         %IF MODE#3 %AND FORMAT=0 %THEN %START;   ! NOT A RECORD ARRAY
            %IF A(P)=1 %THEN P=P+1 %AND INIT SPACE(QQ,LENGTH)
         %FINISH
         %IF CONSTS FOUND=0 %THEN %START;! NO CONSTANTS GIVEN
                                         ! SO CLEAR AN AREA TO ZERO
            CONSTS FOUND=LENGTH
            CLEAR(QQ) %UNLESS LENGTH<1 %OR EXTRN=3 %OR FORMAT#0
         %FINISH %ELSE %START
            FAULT(46,K) %IF EXTRN=3 %OR FORMAT#0
         %FINISH
         %IF EXTRN=3 %THEN EPDISP=0 %ELSE EPDISP=SPOINT
!
! OUTPUT AN ARRAYHEAD INTO THE GLA RELATIVE TO THE START OF THE SYMBOL-
! TABLES IN WHICH THE ARRAY RESIDES.
!
         %IF TYPE<=2 %THEN AH1=PREC<<27!(1-PARMARR)<<24!LENGTH %ELSE %C
            AH1=3<<27!1<<25!QQ
         %IF PREC=4 %THEN AH1=X'58000002'
         AH2=EPDISP
         AH3=5<<27!3*J;                 ! DV DESPTR = WORD CHKD
         %IF TYPE<=2 %AND PARMARR=0=FORMAT %AND J=1 %THEN AH2=AH2-BP*LB
         PGLA(8,16,ADDR(AH1))
         TAGDISP=GLACA-16
         %IF EXTRN=3 %THEN %START;     ! EXTRINSIC ARRAYS
            GXREF(NAMTXT,2,2<<24!QQ,TAGDISP+4);   ! RELOCATE ADDR(A(FIRST))
         %FINISH %ELSE %START
            RELOCATE(TAGDISP+4,AH2,LPUTP);! RELOCATE ADDR(A(FIRST))
         %FINISH
         RELOCATE(TAGDISP+12,AH4,1);   ! RELOCATE DV POINTER
         AH4=(AH4<<1>>3)!X'80000000'
         NOTE CREF(AH4!(TAGDISP+12)>>2<<16)
         EPTYPE=5;                    ! DATA IN GLA SYMBOL TABLES
         STAG(TAGDISP,QQ)
         -> BEND
         %ROUTINE INIT SPACE(%INTEGER SIZE,NELS)
!***********************************************************************
!*       P IS TO FIRST ENTRY FOR CONSTLIST                             *
!***********************************************************************
%INTEGER RF,I,K,ELSIZE,AD,SPP,ELSEEN,LENGTH
%BYTEINTEGERARRAY SP(0:SIZE+256)
         %IF TYPE=1 %THEN AD=ADDR(ICONST)+4-ACC
         %IF TYPE=2 %THEN AD=ADDR(RCONST)
         %IF TYPE=5 %THEN AD=ADDR(SCONST)
         SPP=0; ELSEEN=0
         ELSIZE=SIZE//NELS
         %UNTIL A(P-1)=2 %CYCLE
            XTRACT CONST(TYPE,PREC)
            %IF A(P)=2 %THEN RF=1 %ELSE RF=FROMAR2(P+1) %AND P=P+2
            P=P+2
            FAULT(44,0) %IF RF=0
            %CYCLE I=1,1,RF
               %CYCLE K=0,1,ELSIZE-1
                  %IF ELSEEN<=NELS %THEN SP(SPP)=BYTE INTEGER(AD+K) %C
                     %AND SPP=SPP+1
               %REPEAT
               ELSEEN=ELSEEN+1
            %REPEAT
         %REPEAT;             ! UNTIL P<ROCL>=%NULL
         %IF ELSEEN#NELS %THEN FAULT(45,ELSEEN)
         STPTR=(STPTR+3)&(-4)
         LENGTH=(SIZE+3)&(-4)
         LPUT(LPUTP,LENGTH,STPTR,ADDR(SP(0))) %IF INHCODE=0
         STPTR=STPTR+LENGTH
         CONSTS FOUND=ELSEEN
         %END
         %ROUTINE CLEAR(%INTEGER LENGTH)
         STPTR=(STPTR+3)&(-4)
         LENGTH=(LENGTH+3)&(-4)
         LPUT(LPUTP,LENGTH,STPTR,0)%IF INHCODE=0
         STPTR=STPTR+LENGTH
         %END
         %ROUTINE STAG(%INTEGER J,DATALEN)
         %IF EXTRN=2 %THEN %C
            LPUT(14,EPTYPE<<24!DATALEN,EPDISP,ADDR(NAMTXT))
         RBASE=CBASE
         STORE TAG(K,J)
         RBASE=RLEVEL
         %END
%ROUTINE XTRACT CONST(%INTEGER CONTYPE,CONPREC)
!***********************************************************************
!*       P POINTS TO P<+'> OF <+'><CONST>  AND IS UPDATED              *
!*       THE CONST IS CONVERTED TO ALL LEGAL FORM AND THE INTEGER      *
!*       IS LEFT IN ICONST, THE REAL IN RCONST AND THE STRING IN SCONST*
!***********************************************************************
%INTEGER LENGTH,CPREC
         SIGN=A(P); CTYPE=A(P+1); CPREC=CTYPE>>4; CTYPE=CTYPE&7
         CONSTP=P+2
         %IF CTYPE=2 %THEN %START; ! REAL CONSTANT
            RCONST=FROMAR8(P+2); P=P+10
            LRCONST=0
            %IF CPREC=7 %THEN LRCONST=FROMAR8(P) %AND P=P+8
            %IF SIGN=2 %THEN RCONST=-RCONST
         %FINISH
!
         %IF CTYPE=5 %THEN SCONST=STRING(ADDR(A(P+6)))%C
            %AND P=P+A(P+6)+7
!
         %IF CTYPE=1 %THEN %START; ! INTEGER CONSTANT
            ICONST=FROMAR4(P+2); P=P+6
            %IF SIGN=2 %THEN ICONST=-ICONST
            %IF CPREC=6 %THEN %START
               UICONST=ICONST
               ICONST=FROM AR4(P); P=P+4
            %FINISH %ELSE %START
               %IF ICONST<0 %THEN UICONST=-1 %ELSE UICONST=0
            %FINISH
            %IF CONTYPE=2 %THEN RCONST=ICONST;! INTEGER A SPECIAL CASE OF REAL
         %FINISH
         LENGTH=BYTEINTEGER(ADDR(SCONST))
!
! FAULT ANY OBVIOUS ERRORS IE:-
! CONSTANT FOR EXTRINSIC OR INCOMPATIBLE TYPE OR STRING TOO LONG
!
         %IF EXTRN=3 %OR (CTYPE=2 %AND CONTYPE#2) %OR %C
            (CONTYPE=5 %AND CTYPE#5) %OR %C
            (CTYPE=5 %AND (CONTYPE#5 %OR SIGN#3 %OR LENGTH>=ACC)) %C
            %OR (CONTYPE=1 %AND ((CONPREC=3 %AND ICONST>255) %OR %C
            (CONPREC=4 %AND ICONST>X'FFFF'))) %THEN FAULT(44,0)
     %END
BEND:    %END; ->CSSEXIT
SW(18):
         P=P+1
         CRSPEC(2); ->CSSEXIT
SW(19):
         ABORT
SW(10):
         %BEGIN;                       ! %RECORD (RDECLN)
!***********************************************************************
!*       RECORDS ARE ALLOCATED AT COMPILE TIME WHEN POSSIBLE           *
!*       SEE CRFORMAT FOR ACTION ON RECORD FORMAT DECLARATIONS         *
!***********************************************************************
%INTEGER MODE,RECL,ALLOC,FNAM,FINF,NAME,OPHEAD
         P=P+1; MODE=A(P); SNDISP=0
         %IF MODE=1 %THEN %START;      ! DEAL WITH FORMAT
            NAME=FROM AR2(P+1); P=P+3
            CRFORMAT(OPHEAD); K=NAME
            PTYPE=4; J=0
            KFORM=OPHEAD
            STORE TAG(K,OPHEAD)
            ->BEND
         %FINISH
         P=P+1; MARKER=P+FROM AR2(P)
         FNAM=FROM AR2(MARKER);       ! FORMAT NAME
         COPY TAG(FNAM)
         FINF=TCELL
         %IF TYPE#4 %THEN %START
            FINF=DUMMY FORMAT
            ACC=4; FAULT(62,FNAM)
         %FINISH
         RECL=ACC
         %IF MODE=2%THEN %START;       ! '%RECORDSPEC'
            COPY TAG(FROM AR2(P+2))
            %IF A(P+4)=1 %AND TYPE=4 %START;! SPEC FOR FORMAT ELEMENT
               P=P+5
               Q=DISPLACEMENT(TCELL)
               UNPACK
            %FINISH
            %IF TYPE=3 %AND NAM=1 %AND FROM3(TCELL)&X'FFFF'=0 %START
               REPLACE3(TCELL,FINF!K<<16)
               REPLACE2(TCELL,SNDISP<<16!RECL)
            %FINISH %ELSE FAULT(63,0)
         %FINISH %ELSE %START;         ! RECORD DECLARATION
            FAULT(57,0) %UNLESS LEVEL>=2
            FAULT(40,0) %IF NMDECS(LEVEL)&1#0
            TYPE=3; PREC=3; ROUT=0
           %IF A(P+2)=1 %THEN %START;  ! SIMPLE RECORD AND RECORDNAMES
               ALLOC=ACC; CQN(P+3)
               ACC=ALLOC; P=P+4
               DECLARE SCALARS(1,FINF)
            %FINISH %ELSE %START;      ! ARRAYS OF RECORDS
               NAM=0
               Q=2-A(P+3); P=P+4;      ! Q=1 FOR ARRAY FORMAT
               DECLARE ARRAYS(Q,FINF)
            %FINISH
         %FINISH
BEND:    %END;->CSSEXIT
!
SW(20):
                                        ! '*' (UCI) (S)
         FAULT(57,0) %UNLESS LEVEL>=2
         %BEGIN
         %ROUTINESPEC CIND
         %INTEGER FNAME,ALT,OPCODE,FORM,H,Q,MASK,FILLER
         %SWITCH SW(1:5),F(1:3),POP(1:6),TOP(1:4)
         ALT=A(P+1); P=P+2
         OPCODE=CALL
         ->SW(ALT)
SW(1):SW(2):
         FNAME=FROM AR2(P)
         COPY TAG(FNAME)
         FAULT(33,FNAME) %UNLESS ROUT=NAM=0 %AND ARR=0 %AND %C
            PREC>4 %AND I=RBASE %AND TYPE#7
         %IF ALT=1 %THEN PSF1(ST,1,K) %ELSE  %C
            GET IN ACC(ACCR,BYTES(PREC)>>2,0,LNB,K)
         ->EXIT
SW(3):                                  ! PUT (HEX HALFWORD)
         PLANT(FROM AR2(P+3))
         ->EXIT
SW(5):                                  ! CNOP
         CNOP(A(P),A(P+1))
         ->EXIT
SW(4):                                  ! ASSEMBLER
         FORM=A(P);                     ! FORM=PRIMARY,SECONDARY OR 3RY
         OPCODE=A(P+1)
         P=P+2; ->F(FORM)
F(1):                                   ! ALL PRIMARY FORMAT INSTRUCTIONS
         ALT=A(P); P=P+1
         ->POP(ALT)
POP(1):                                 ! LABELNAME
         FNAME=FROM AR2(P); P=P+2
         ENTER JUMP(OPCODE<<24!3<<23,FNAME,0)
         ->EXIT
POP(2):                                 ! DIRECT SYMBOLIC
         CIND
POPI:    PSORLF1(OPCODE,ACCESS,AREA,DISP)
         ->EXIT
POP(3):                                ! INDIRECT SYMBOLIC
         CIND
         ACCESS=4-A(P); P=P+1
         ->POPI
POP(4):                                 ! DR SYMBOLICALLY MODIFIED
         CIND; ACCESS=1; ->POPI
POP(5):                                 ! (DR) & (DR+B)
         ACCESS=4-A(P); AREA=7
         DISP=0; P=P+1
         ->POPI
POP(6):                                 ! B
         ACCESS=0
         AREA=7; DISP=0; ->POPI
F(2):                                   ! SECONDARY (STORE-TO STORE)FORMAT
         MASK=0; FILLER=0; Q=0; FNAME=0
         H=2-A(P)
         %IF H=0 %THEN FNAME=FROM AR2(P+1)-1 %AND P=P+2
         FAULT(33,0) %UNLESS 0<=FNAME<=127
         ALT=A(P+1); P=P+2
         %IF ALT=1 %THEN %START
            Q=1
            MASK=FROM AR2(P)
            FILLER=FROM AR2(P+2)
            P=P+4
            FAULT(33,0) %UNLESS 0<=MASK!FILLER<=255
         %FINISH
         PF2(OPCODE,H,Q,FNAME,MASK,FILLER)
         ->EXIT
F(3):                                   ! TERTIARY FORMAT
         MASK=FROM AR2(P)
         ALT=A(P+2)
         FAULT(33,0) %UNLESS 0<=MASK<=15
         P=P+3; ->TOP(ALT)
TOP(1):                                 ! LABEL
         FNAME=FROM AR2(P); P=P+2
         ENTER JUMP(OPCODE<<24!MASK<<21,FNAME,0)
         ->EXIT
TOP(2):                                 ! SYMBOLIC OPERAND
         CIND
         FAULT(33,0) %IF AREA>=6
         %IF AREA=LNB %OR AREA=XNB %OR AREA=CTB %THEN DISP=DISP//4
TOPI:    PF3(OPCODE,MASK,AREA,DISP)
         ->EXIT
TOP(3):                                 ! (DR) & (DR+B)
         DISP=0; AREA=8-A(P)
         P=P+1; ->TOPI
TOP(4):                                 ! (DR+N)
         DISP=FROM AR2(P); P=P+2
         AREA=1; ->TOPI
         %ROUTINE CIND          
!***********************************************************************
!*       COMPILE A SYMBOLIC OPERAND BY SETTING ACCESS,AREA &DISP       *
!***********************************************************************
%INTEGER ALT,FN,FN2,D,CTYPE,CPREC
%SWITCH SW(1:4)
         ALT=A(P); ACCESS=0
         P=P+1; ->SW(ALT)
SW(1):                                  ! (=')(PLUS')(ICONST)
         P=P+1;                         ! PAST (=')
         D=A(P); CTYPE=A(P+1)
         CPREC=CTYPE>>4; CTYPE=CTYPE&7
         FN=FROM AR4(P+2); FN2=ADDR(A(P+2))
         P=P+2+BYTES(CPREC)
         %IF D=2 %THEN %START
            %IF CTYPE=2 %THEN FN=FN!!X'80000000' %ELSE FN=-FN
         %FINISH
CNST:    ->LIT %UNLESS CTYPE=1 %AND CPREC<=5 %AND %C
            X'FFFE0000'<=FN<=X'1FFFF'
         AREA=0; DISP=FN
         %RETURN
LIT:     FAULT(33,0) %UNLESS 1<=CTYPE<=2 %AND 5<=CPREC<=7
         STORE CONST(DISP,BYTES(CPREC),FN2)
         AREA=PC; ACCESS=0
         %RETURN
SW(2):                                  ! (NAME)(OPTINC)
         FN=FROM AR2(P); P=P+2
         COPY TAG(FN)
         %IF (LITL=1 %AND ARR=0) %START
            CTYPE=TYPE; CPREC=PREC
            ALT=TAGS(FN)
            FROM123(ALT,D,FN,FN2)
            %IF CPREC#7 %THEN FN2=ADDR(ASLIST(ALT)_S2)
            ->CNST
         %FINISH
         %IF TYPE>=6 %OR TYPE=4 %OR %C
            (ROUT=1 %AND NAM=0) %THEN FAULT(33,FN) %AND %RETURN
         %IF ROUT=1 %THEN K=FROM1(K)
         AREA=LNB
         %IF I#RBASE %THEN AREA=SET XORYNB(XNB,I)
         ALT=A(P); D=FROM AR2(P+1)
         %IF ALT=1 %THEN K=K+D
         %IF ALT=2 %THEN K=K-D
         P=P+1; P=P+2 %IF ALT<=2
         DISP=K; %RETURN
SW(3):                                  ! '('(REG)(OPTINC)')'
         AREA=A(P)+1; ALT=A(P+1); P=P+2
         DISP=0
         D=FROM AR2(P)
         %IF ALT=1 %THEN DISP=D
         %IF ALT=2 %THEN FAULT(33,0)
         %IF AREA=PC %THEN DISP=CA+2*DISP %ELSE DISP=4*DISP
         P=P+2 %UNLESS ALT=3
         %RETURN
SW(4):                                  ! '%TOS'
         AREA=6; DISP=0
%END
EXIT:    GRUSE(ACCR)=0
         GRUSE(DR)=0
         GRUSE(BREG)=0
         GRUSE(XNB)=0 %IF OPCODE=CALL %OR OPCODE=LXN %OR OPCODE=JLK %C
               %OR OPCODE=OUT
         GRUSE(CTB)=0 %IF OPCODE=CALL %OR OPCODE=LCT %OR OPCODE=JLK %C
            %OR OPCODE=OUT
%END
         ->CSSEXIT
SW(21):
                                        ! '%TRUSTEDPROGRAM'
         COMPILER=1 %IF PARMARR=0; ->CSSEXIT
SW(22):                                 ! '%MAINEP'(NAME)
         KK=FROM AR2(P+1)
         FAULT(33,0) %UNLESS CPRMODE=0
         MAINEP<-STRING(DICTBASE+WORD(KK))
         ->CSSEXIT
         %ROUTINE CRFORMAT(%INTEGERNAME OPHEAD)
!***********************************************************************
!*       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,NLIST,FORM,RL,MRL,UNSCAL,SC,DESC,FN,INC,Q,R,A0,A1,A2, %C
         DV,RFD,LB,OB
%SWITCH RFEL(1:5)
%ROUTINESPEC SN(%INTEGER Q)
%ROUTINESPEC ROUND
         NLIST=0; OPHEAD=0; FORM=0; ACC=0; OB=0
         MRL=0; INC=0;                 ! INC COUNTS DOWN RECORD
NEXT:    ROUT=0; LITL=0; NAM=0; RFD=A(P)
         %IF RFD<=2 %THEN P=P+1 %AND CLT
         ->RFEL(RFD)
RFEL(1):                               ! (TYPE) (QNAME')(NAMELIST)
         CQN(P); P=P+1
         PACK(PTYPE); D2=0
         RL=3
         %IF NAM=0 %AND 3<=PREC<=4 %THEN RL=PREC-3
AGN:     ROUND ; J=0
         %UNTIL A(P-1)=2 %CYCLE
            D1=INC; SN(P)
            P=P+3; INC=INC+ACC
         %REPEAT
         P=P+RFD>>2<<1;                ! EXTRA  2 FOR RECORDS TO SKIP FORMAT
TRY END: -> END %IF A(P)=2
         P=P+1; -> NEXT
RFEL(2):RFEL2:                         ! (TYPE)%ARRAY(NAMELIST)(CBPAIR)
         Q=P; ARR=1; PACK(PTYPE)
         %IF TYPE<=2 %THEN UNSCAL=0 %AND SC=PREC %C
                     %ELSE UNSCAL=1 %AND SC=3
         %IF PREC=4 %THEN DESC=X'58000002' %ELSE %C
            DESC=SC<<27!UNSCAL<<25!(1-PARMARR)<<24
         %UNTIL A(P-1)=2 %CYCLE;       ! UNTIL <RESTOFARRAYLIST> NULL
            P=P+3 %UNTIL A(P-1)=2
            DV=DOPE VECTOR(TYPE,ACC,R,LB)+12;! DOPE VECTOR INTO SHAREABLE S.T.
            %IF TYPE=5 %OR PREC=3 %THEN RL=0 %ELSE RL=3
            ROUND
            %UNTIL A(Q-1)=2 %CYCLE;       ! HEAD  INTO GLA FOR EACH ARRAY
               A0=R; %IF UNSCAL=0 %THEN A0=A0//ACC
               %IF PREC=4 %THEN A0=0;   ! STRING DESCRIPTORS !
               A0=A0!DESC; A1=INC
               %IF TYPE<=2  %AND PARMARR=0 %AND J= 1 %THEN %C
                  A1=A1-LB*ACC
               A2=5<<27!3*J
               PGLA(4,16,ADDR(A0))
               D1=GLACA-16
               RELOCATE(D1+12,DV,1);    ! RELOCATE DV POINTER
               NOTE CREF(X'80000000'!(DV<<1>>3)!(D1+12)>>2<<16)
               D2=INC
               SN(Q); INC=INC+R
               Q=Q+3
            %REPEAT
            P=P+1; Q=P
         %REPEAT
         P=P+2 %IF RFD=5
         -> TRY END
RFEL(3):                               ! %RECORD (%ARRAY) %NAME
         TYPE=3; PREC=3; NAM=1
         ARR=2-A(P+1); P=P+2
         PACK(PTYPE); D2=0
         RL=3; ACC=8+8*ARR
         FORM=0
         ->AGN
RFEL(4):                               ! RECORDS IN RECORDS
RFEL(5):                                ! RECORDARRAYS IN RECORDS
         Q=P+FROM AR2(P+1)+1
         FN=FROM AR2(Q)
         COPY TAG(FN);               ! COPY FORMAT TAG & SET ACC
         FAULT(62,FN) %UNLESS PTYPE=4
         TYPE=3; PREC=3; FORM=TCELL
         %IF RFD=4 %THEN %START
            PTYPE=X'33'; P=P+3; D2=0
            RL=3; ->AGN
         %FINISH
         P=P+3; ->RFEL2
END:                                   ! FINISH OFF
         RL=MRL; ROUND
         ACC=INC;                      ! SIZE ROUNDED APPROPRIATELY
         FAULT(98,0) %UNLESS INC<=X'7FFF'
         CLEAR LIST(NLIST)
         %RETURN
         %ROUTINE SN(%INTEGER Q)
!***********************************************************************
!*       CHECK THE SUBNAME HAS NOT BEEN USED BEFORE IN THIS FORMAT     *
!*       AND ENTER IT WITH ITS DESCRIPTORS INTO THE LIST.              *
!***********************************************************************
         FNAME=FROM AR2(Q)
         FAULT(7,FNAME) %UNLESS FIND(FNAME,NLIST)=-1
         BINSERT(OPHEAD,OB,FNAME<<20!PTYPE<<4!J,D2<<16!ACC,D1<<16!FORM)
         PUSH(NLIST,0,FNAME,0)
         %END
         %ROUTINE ROUND
         MRL=RL %IF RL>MRL
         INC=INC+1 %WHILE INC&RL#0
         %END
         %END;                         ! OF ROUTINE CRFORMAT
         %INTEGERFN     DISPLACEMENT(%INTEGER LINK)
!***********************************************************************
!*         SEARCH A FORMAT LIST FOR A SUBNAME                          *
!*      A(P) HAS ENAME--LINK IS HEAD OF RFORMAT LIST. RESULT IS DISP   *
!*      FROM START OF RECORD                                           *
!***********************************************************************
%RECORDNAME LCELL(LISTF)
%INTEGER RR,II,ENAME,CELL
         ENAME=A(P)<<8+A(P+1); CELL=0
         %IF LINK#0 %THEN %START;    ! CHK RECORDSPEC NOT OMITTED
            LINK=FROM3(LINK)&X'7FFF';   ! LINK TO SIDE CHAIN
            CELL=LINK; II=-1; ACC=-1
            %WHILE LINK>0 %CYCLE
               LCELL==ASLIST(LINK)
               TCELL=LINK
               %IF LCELL_S1>>20=ENAME %START;      ! RIGHT SUBNAME LOCATED
                  RR=LCELL_S1
                  SNDISP=LCELL_S2
                  K=LCELL_S3
                  J=RR&15; PTYPE=RR>>4&X'FFFF'
                 ACC=SNDISP&X'FFFF'; SNDISP=SNDISP&X'FFFF0000'//X'10000'
                  KFORM=K&X'FFFF'; K=K&X'FFFF0000'//X'10000'
                  %RESULT=K
               %FINISH
               LINK=LCELL_LINK
            %REPEAT
         %FINISH
         FAULT(65,ENAME)
         %IF CELL>0 %THEN %C
         PUSH(ASLIST(CELL)_LINK,ENAME<<20!7<<4,0,0)
         PTYPE=7; TCELL=0
         %RESULT=-1
         %END
         %INTEGERFN     COPY RECORD TAG(%INTEGERNAME SUBS)
!***********************************************************************
!*       PRODUCE PTYPE ETC FOR A COMPOUND NAME BY CHAINING DOWN ONE    *
!*       ONE OR MORE RECORD FORMAT LISTS. ON EXIT RESULT =0 IF NO      *
!*       SUBNAME FOUND OR SUBNAME IS OF TYPE RECORD WITH NO FURTHER    *
!*       SUBNAME ATTACHED. RESULT#0 IF BONE-FIDE SUBNAME LOCATED       *
!*       ON ENTRY KFORM HAS POINTER TO THE (FIRST ) FORMAT LIST AND    *
!*       P POINTS TO THE A.R. ENTRY FOR (FIRST) ENAME                  *
!***********************************************************************
%INTEGER Q,FNAME
         SUBS=0
         %UNTIL TYPE#3 %CYCLE
            FNAME=KFORM
            P=P+2; SKIP APP
            %RESULT=0 %IF A(P)=2 %OR FNAME<=0;! NO (FURTHER) ENAME
            SUBS=SUBS+1
            P=P+1; Q=DISPLACEMENT (FNAME)
            UNPACK
         %REPEAT
         %RESULT=Q+1;       ! GIVES 0 IF SUBNAME NOT KNOWN
         %END
%ROUTINE CRNAME(%INTEGER Z,REG,MODE,BS,AR,DP,%INTEGERNAME NAMEP)
!***********************************************************************
!*       DEAL WITH RECORD ELEMENT NAMES.Z AS FOR CNAME.CLINK=TAGS(RN)  *
!*       MODE=ACCESS FOR RECORD(NOT THE ELEMENT!)                      *
!*       ON EXIT BASE,AREA & DISP POINT TO REQUIRED ELEMENT            *
!*       RECURSIVE CALL IS NEEDED TO DEAL WITH RECORDS IN RECORDS      *
!*       DEPTH SHEWS  RECURSIVE LEVELS- NEEDED TO AVOID MIS SETTING    *
!*       REGISTER IN USE IF RECORDNAME IN RECORD HAS THE SAME NAME AS  *
!*       A GENUINE RECORD NAME.                                        *
!***********************************************************************
%INTEGER DEPTH,FNAME
%ROUTINESPEC CENAME(%INTEGER MODE,FNAME,BS,AR,DP,XD)
         DEPTH=0
         FNAME=KFORM;                  ! POINTER TO FORMAT
         %IF ARR=0 %OR (Z=6 %AND A(P+2)=2) %START;! SIMPLE RECORD
            %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
            CENAME(MODE,FNAME,BS,AR,DP,0)
         %FINISH %ELSE %START
            CANAME(ARR,BS,DP)
            CENAME(ACCESS,FNAME,BASE,AREA,DISP,0)
         %FINISH; %RETURN
!
%ROUTINE CENAME(%INTEGER MODE,FNAME,BS,AR,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                              *
!***********************************************************************
%ROUTINESPEC FETCH RAD
%ROUTINESPEC LOCALISE(%INTEGER SIZE)
%INTEGER Q,QQ,D,C,W
         DEPTH=DEPTH+1
         %IF A(P)=2 %THEN %START;      ! ENAME MISSING
            ACCESS=MODE; AREA=AR; XDISP=XD
            BASE=BS; DISP=DP;          ! FOR POINTER
            %IF Z<14 %THEN %START;     ! NOT A RECORD OPERATION
               %UNLESS 3<=Z<=4 %OR Z=6 %START;   ! ADDR(RECORD)
                  FAULT(64,0); BASE=RBASE; AREA=-1
                  DISP=0; ACCESS=0; PTYPE=1; UNPACK
               %FINISH
            %FINISH
            %RETURN
         %FINISH
         P=P+1;                        ! FIND OUT ABOUT SUBNAME
         Q=DISPLACEMENT(FNAME);        ! TCELL POINTS TO CELL HOLDING
         UNPACK;                       ! INFO ABOUT THE SUBNAME
         %IF Q=-1=ACC %OR PTYPE=7 %START;! WRONG SUBNAME(HAS BEEN FAULTED)
            P=P+2; SKIP APP; P=P-3
            ACCESS=0; BASE=RBASE; DISP=0; AREA=-1
            %RETURN
         %FINISH
         ->AE %IF ARR=1;                ! ARRAYS INCLUDING RECORDARRAYS
         %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
         %IF TYPE<=2 %OR TYPE=5 %OR %C
               (TYPE=3 %AND A(P)=2 %AND (3<=Z<=4 %OR Z=6)) %START
            ACCESS=MODE+4+4*NAM; BASE=BS;
            AREA=AR; 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
         %IF NAM=1 %THEN %START
            LOCALISE(8);                ! PICK UP RECNAME DESCR &STCK
            AR=AREA; DP=DISP; BS=BASE
            NAMEP=-1
         %FINISH
         CENAME(MODE,KFORM,BS,AR,DP,XD)
         %RETURN
AE:                                    ! ARRAYS AND ARRAYNAMES AS ELEMEN
         NAMEP=-1
         FROM123(TCELL,Q,SNDISP,K)
         ACC=SNDISP&X'FFFF'; SNDISP=SNDISP&X'FFFF0000'//X'10000'
         KFORM=K&X'FFFF'; K=K&X'FFFF0000'//X'10000'
         C=ACC; D=SNDISP; Q=K; QQ=KFORM
         %IF (Z=6 %OR Z=12) %AND A(P+2)=2 %START;! 'GET ARRAYHEAD' CALL
               P=P+3
            %IF NAM=1 %THEN %START
               ACCESS=MODE+8; BASE=BS
               AREA=AR; DISP=DP; XDISP=XD+Q
               %RETURN
            %FINISH
!
! PASSING AN ARRAY IN A RECORD BY NAME MUST CONSTRUCT PROPER ARRAYHEAD
! FROM THE RECORD RELATIVE ONE AT Q(GLA)
!
            FETCH RAD
            AREA=-1; DISP=Q
            BASE=0; ACCESS=0;
            CREATE AH(1)
         %FINISH %ELSE %START;         ! ARRAY ELEMENTS IN RECORDS
            %IF NAM=1 %THEN %START;    ! ARRAYNAMES-FULLHEAD IN RECORD
               XD=XD+Q
               LOCALISE(16);           ! MOVE HEAD UNDER LNB
               CANAME(1,BASE,DISP);  ! ARRAY MODE SETS DISP,AREA&BASE
            %FINISH %ELSE %START;      ! ARRAY RELATIVE HEAD IN GLA
               %IF MODE=2 %AND BS=RBASE %THEN W=DP+4 %ELSESTART
                  FETCH RAD;            ! RECORD ADDR TO ACC
                  GET WSP(W,1)
                  PSF1(ST,1,W); XD=0
               %FINISH
               CANAME(1,0,Q);         ! RECORD REL ARRAY ACCESS
               %IF PARMARR=0 %AND (PREC=3 %OR TYPE>=3) %THEN %START
                  PSF1(ADB,1,W)
                  PSF1(ADB,0,XD) %UNLESS XD=0
                  GRUSE(BREG)=0
               %FINISH %ELSE %START
                  GET IN ACC(DR,2,0,AREA CODE,Q)
                  PSF1(INCA,1,W)
                  PSF1(INCA,0,XD) %UNLESS XD=0
                  FORGET (DR)
                  ACCESS=3
                  %IF TYPE=3 %OR Z=4 %START; ! WILL BE A FURTHER CALL
                                             ! ON ROUTINE CENAME
                     GET WSP(DISP,2)
                     PSF1(STD,1,DISP)
                     AREA=LNB; BASE=RBASE
                  %FINISH %ELSE AREA=7 %AND DISP=0
               %FINISH
            %FINISH
            %IF TYPE=3 %THEN CENAME(ACCESS,QQ,BASE,AREA,DISP,0)
         %FINISH
         %RETURN
%ROUTINE FETCH RAD
!***********************************************************************
!*       SET ACC TO 32 BIT ADDRESS OF RECORD.                          *
!***********************************************************************
         ACCESS=MODE+4
         AREA=AR; BASE=BS
         DISP=DP; XDISP=XD
         NAMEOP(4,ACCR,4,-1)
         %END
%ROUTINE LOCALISE(%INTEGER SIZE)
!***********************************************************************
!*       REMOVES A DESCRIPTOR OR ARRAYHEAD FROM A RECORD AND STORES    *
!*       IT IN A TEMPORARY UNDER LNB.                                  *
!***********************************************************************
%INTEGER HOLE
         ACCESS=MODE+4
         AREA=AR; BASE=BS; DISP=DP
         XDISP=XD
         NAMEOP(2,ACCR,SIZE,-1)
         GET WSP(HOLE,SIZE>>2)
         PSF1(ST,1,HOLE)
         MODE=2; AREA=LNB
         BASE=RBASE; DISP=HOLE; XD=0
         %END;                         ! OF ROUTINE LOCALISE
         %END;                         ! OF ROUTINE CENAME
         %END;                         ! OF ROUTINE CRNAME
         %ROUTINE CSTREXP(%INTEGER MODE,REG)
!***********************************************************************
!*       PLANT IN-LINE CODE FOR CONCATENATION. A WORK AREA UNDER       *
!*       BASE REGISTER COVER IS USUALLY REQUIRED. THE CURRENT LENGTH   *
!*       OF STRING IN THE WORK AREA IS KEPT IN A REGISTER (BREG)       *
!*       WHICH IS PROTECTED THROUGH THE NORMAL INTERMEDIATE-RESULT     *
!*       MECHANISMS.                                                   *
!*       ON ENTRY:-                                                    *
!*       MODE=0    NORMAL. WK AREA NOT USED FOR ONE OPERAND EXPSSNS    *
!*       MODE=1     STRING MUST GO TO WORK AREA                        *
!*       (AND TO COME)                                                 *
!*       MODE=3    CONCATENATE INTO LHS OF =ASSNMNT (E.G. A=B.C)       *
!*       MODE=4    OPTIMISE  S=S.T   BY NOT COPYING S                  *
!*       2**4 BIT OF MODE IS SET IF WK-AREA NOT TO BE FREED ON EXIT    *
!*       ON EXIT:-                                                     *
!*       BASE,DISP & INDEX DEFINE RESULT                               *
!*       VALUE#0 %IF RESULT IN A WORK AREA(CCOND MUST KNOW)            *
!*       STRINGL SET IF STRING LENGTH KNOWN. NEST DEFINES LENREG       *
!***********************************************************************
%INTEGER PP,WKAREA,DOTS,REXP,ERR,CLEN,KEEPWA
%INTEGERFNSPEC STROP
         KEEPWA=MODE&16; MODE=MODE&15
         PP=P; STRINGL=0
         REXP=2-A(P+1+FROM AR2(P+1));         ! =0 %IF ONE OPERAND EXP
         -> NORMAL %UNLESS A(P+3)=4 %AND REXP=0 %AND MODE=0
         -> SIMPLE %IF A(P+4)=2
         -> NORMAL %UNLESS A(P+4)=1
!         COPY TAG(FROM AR2(P+5))
!         %IF PTYPE=SNPT %THEN PTYPE=TSNAME(K)
!         -> NORMAL %UNLESS ROUT=0 ; ! BEWARE OF MAP=FN
!         -> NORMAL %IF PARMARR=1 %AND(ARR#0 %OR A(P+7)=1)
SIMPLE:  P=P+4
         ERR=STROP
         -> ERROR %UNLESS ERR=0
         VALUE=0
         P=P+1; NEST=0
         %IF REG=ACCR %THEN COPY DR
         %RETURN
ERROR:   FAULT(ERR,0)
         BASE=RBASE; DISP=0
         VALUE=0; ACCESS=0
         P=PP; SKIP EXP
         %RETURN
NORMAL:  CLEN=0; P=P+3;                ! LENGTH OF CONSTANT PART
         ERR=72; ->ERROR %UNLESS A(P)=4
         P=P+1
         GET WSP(WKAREA,268);          ! GET NEXT OPERAND
         DOTS=0;                        ! NO OPERATORS YET
NEXT:    STRINGL=0
         ERR=STROP;                    ! GET NEXT OPERAND
         -> ERROR %UNLESS ERR=0
         %IF REGISTER(ACCR)#0 %THEN BOOT OUT(ACCR)
         PSF1(LB,0,WKAREA);             ! BYTE DISP FROM LNB
         PPJ(0,19+DOTS);                ! TO SUBROUTINE 19 OR 20
         %IF A(P)=2 %THEN -> TIDY;     ! NO MORE OPERATIONS
         ERR=72; -> ERROR %UNLESS A(P+1)=CONCOP; ! CONCATENATE
         DOTS=DOTS!1
         P=P+2; -> NEXT
TIDY:                                  ! FINISH OFF
         VALUE=WKAREA
         P=P+1;                        ! PAST REST OF EXPRN
         RETURN WSP(WKAREA,268) %IF KEEPWA=0
         STRINGL=0
         %RETURN
         %INTEGERFN STROP
!***********************************************************************
!*       DEALS WITH OPERAND FOR CONCATENATION. RETURN RESULT=0 FOR     *
!*       VALID OPERAND OTHERWISE AN ERROR NUMBER.                      *
!***********************************************************************
%INTEGER CTYPE,VAL,MODE
         MODE=A(P);                    ! ALTERNATIVE OF OPERAND
         %RESULT=75 %IF MODE>2
         %IF MODE#1 %THEN %START
            CTYPE=A(P+1);             ! GET CONST TYPE & LOSE AMCK FLAGS
            %IF CTYPE=5 %THEN %START
               STRINGL=A(P+6)
               DISP=FROM AR4(P+2)
               P=P+STRINGL+7
            %FINISH %ELSE %START
               VAL=FROM AR4(P+2)
               %RESULT=71 %UNLESS CTYPE=X'51' %AND VAL=0
               P=P+6
               DISP=0
               STRINGL=0
            %FINISH
            PF1(LDRL,0,PC,STRLINK)
            PSF1(INCA,0,DISP) %IF DISP#0
            %IF STRINGL#1 %THEN %START
               %IF STRINGL<=63 %THEN PSF1(LDB,0,STRINGL) %C
                               %ELSE PF1(LDB,2,7,0);! ((DR))
            %FINISH
            GRUSE(DR)=0
         %FINISH %ELSE %START
            P=P+1;                      ! MUST CHECK FIRST
            REDUCE TAG;                 ! SINCE CNAME ONLY LOADS STRINGS
            %RESULT=71 %IF 7#TYPE#5;    ! AND LONGINTS TO DR!
            CNAME(2,DR)
            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 3 PARAMS:-        *
!*       P1  POINTS TO LHS(A)                                          *
!*       P2    STRING TO CONTAIN FRAGMENT (PASSED BY NAME)             *
!*       P3 THE EXPRESSION PASSED AS DESCRIPTOR                        *
!*       SUBROUTINE TRIES TO PERFORM THE RESOLUTION AND SETS THE       *
!*       CONDITION CODE =8 IF IT SUCCEEDS.                             *
!*                                                                     *
!*       ON ENTRY LHS IS DEFINED BY DESCRIPTOR REG.                    *
!*       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
%RECORD R(RD)
         LAST=0;                       ! =1 WHEN END OF EXPRNSN FOUND
         SEXPRN=0;                     ! RESOLUTION(BRKTD) EXPRESSNS
         PSF1(INCA,0,1);                  ! TO FIRST CHAR
         P1=P; P=P+3
         ->RES %IF A(P)=4 %AND TYPE=5;   ! LHS MUST BE A STRING
ERROR:   FAULT(74,0)
         P=P1; SKIP EXP; %RETURN
RES:     P=P+1;                        ! TO P(OPERAND)
         PSF1(PRCL,0,4)
         %IF SEXPRN=0 %THEN W=STD %ELSE W=ST
         PF1(W,0,TOS,0)
         %IF A(P)=3 %THEN PSF1(LSD,0,0) %ELSE %START;! B OMITTED
            ->ERROR %UNLESS A(P)=1;       ! P(OPERAND)=NAME
            P=P+1; P2=P
            CNAME(3,ACCR)
            ->ERROR %UNLESS TYPE=5 %AND A(P+1)=CONCOP;! DOT OPERATOR
            P=P+2
         %FINISH
         PF1(ST,0,TOS,0);               ! B (OR DUMMY) TO P2
         ->ERROR %UNLESS A(P)=3;       ! P(OPERAND)='('(EXPR)')'
         SEXPRN=SEXPRN+1; P=P+1
         CSTREXP(0,DR);                 ! TO REGISTER DR
!
         PF1(STD,0,TOS,0)
         PSF1(RALN,0,11)
         PPJ(-1,16)
                                       ! DEAL WITH CC#8 IE RESLN FAILED
         %IF LAB#0 %THEN ENTER JUMP(7,LAB,B'11') %ELSE PPJ(7,12)
!
         -> END %IF A(P)=2
         ->ERROR %UNLESS A(P+1)=CONCOP %AND A(P+2)=1
         P2=P+1; P=P2+1
         P=P+3 %AND SKIP APP %UNTIL A(P)=2
         %IF A(P+1)=1 %THEN P=P2 %AND ->RES
         P1=P+1
         REGISTER(ACCR)=1
         OLINK(ACCR)=ADDR(R)
         R_PTYPE=1; R_XB=ACCR
         R_FLAG=9
         P=P2+2; CNAME(1,DR)
         %IF R_FLAG#9 %THEN PF1(LSD,0,TOS,0)
         REGISTER(ACCR)=0
         PF1(STUH,0,BREG,0)
         PF1(LUH,0,BREG,0)
         PF2(MVL,0,0,0,0,0)
         %IF ROUT#0 %OR NAM#0 %THEN PPJ(0,18);! ASSNMNT CHECK (Q.V)
         PF2(MV,1,1,0,0,UNASSPAT&255)
         GRUSE(ACCR)=0
         %IF PARMARR=1 %START
            PSF1(USH,0,8)
            PSF1(USH,0,-40)
            PPJ(36,9)
         %FINISH
         P=P1
END:
         P=P+1
         %END
%ROUTINE SAVE AUX STACK
!***********************************************************************
!*       COPY AUX STACK DESCRPTR & POINTER INTO CURRENT STACK FRAME    *
!***********************************************************************
%INTEGER XYNB, DR0, DR1
      %IF AUXST=0 %THEN %START;         ! FIRST REF PUT REF IN PLT
         DR0=X'30000001'; DR1=0
         PGLA(8,8,ADDR(DR0))
         AUXST=GLACA-8
         GXREF(AUXSTEP,2,X'02000008',AUXST+4)
      %FINISH
      %IF AUXSBASE(LEVEL)=0 %START
         XYNB=SET XORYNB(-1,-1)
         PF1(LD,2,XYNB,AUXST)
         PF1(LSS,2,7,0)
         PSF1(STD,1,N)
         PSF1(ST,1,N+8)
         AUXSBASE(LEVEL)=N; N=N+16
         GRUSE(DR)=0; GRUSE(ACCR)=0
      %FINISH
%END
%ROUTINE RESET AUX STACK
!***********************************************************************
!*       IF ANY ARRAYS HAVE BEEN PUT ON THE AUXSTACK THEN UNDECLARE    *
!***********************************************************************
         %IF AUXSBASE(LEVEL)#0 %START
            PSF1(LB,1,AUXSBASE(LEVEL)+8)
            PSF1(STB,2,AUXSBASE(LEVEL))
            GRUSE(BREG)=0
         %FINISH
%END
         %ROUTINE RT EXIT
!***********************************************************************
!*       THIS ROUTINE COMPILES CODE FOR ROUTINE EXIT(IE '%RETURN')     *
!***********************************************************************
         RESET AUX STACK
         PSF1(EXIT,0,-X'40')
         %END
%ROUTINE CLAIM ST FRAME(%INTEGER AT,VALUE)
!***********************************************************************
!*       FILL ASF INSTN IN RT ENTRY SEQUENCE TO CLAIM THE STACKFRAME   *
!***********************************************************************
%INTEGER INSTR, WK
         WK=AT>>18;               ! BYTES CLAIMED BY ENTRY SEQ
         AT=AT&X'3FFFF';            ! ADRR OF ASF INSTRN
         INSTR=(ASF+12*PARMCHK)<<24!3<<23!(VALUE-WK+3)>>2
         PLUG(1,AT,INSTR,4)
%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
         %ROUTINESPEC DTABLE(%INTEGER LEVEL)
         SET LINE %UNLESS KKK=2
         FORGET(-1)
         BIT=1<<LEVEL
!
! FIRST CHECK FOR ANY '%STARTS' WITHOUT FINISHES
!
         %WHILE SBR(LEVEL)#0 %CYCLE
            FROM12 (SBR(LEVEL),J,KP)
            FAULT(53,0);               ! FINISH MISSING
            A(2)=4; A(3)=3; CSS(2); ! SO COMPILE IT IN
         %REPEAT
!
! 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 COMPILER=0 %AND LAST INST=0 %C
            %THEN PPJ(15,10);          ! RUN FAULT 11
         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 LABEL(LEVEL)#0 %CYCLE
            POP(LABEL(LEVEL),I,J,KP)
            I=I>>24
            %IF J&X'FFFF'#0 %THEN %START
            J=J&X'FFFF'
               CLEAR LIST(J)
               %IF 0<KP<=MAX ULAB %THEN FAULT(11,KP)
            %FINISH %ELSE %START
               %IF I=0 %AND KP<MAX ULAB %THEN WARN(3,KP)
            %FINISH
         %REPEAT
!
         %CYCLE JJ=0,1,4
            CLEAR LIST(AVL WSP(JJ,LEVEL));! RELEASE TEMPORARY LOCATIONS
         %REPEAT
!
         DTABLE(LEVEL);                ! OUTPUT DIAGNOSTIC TABLES
!
! CLEAR DECLARATIONS - POP UP ANY GLOBAL NAMES THAT WERE REDECLARED
! DESTROY SIDE CHAINS FOR ROUTINES,FORMATS AND SWITCHES
!
!
! CHECK FOR MISSING REPEATS
!
       %WHILE CYCLE(LEVEL)#0 %THEN FAULT(13,0)%AND %C
         POP(CYCLE(LEVEL),I,I,I)
!
! NOW CLAIM THE STACK FRAME BY FILING THE ASF IN THE BLOCK ENTRY CODING
!
         NMAX=(NMAX+3)&(-4)
         %IF KKK=2 %THEN %RETURN
       %IF KKK>=X'1000' %OR KKK=1 %THEN CLAIM ST FRAME(SET(RLEVEL),NMAX)
!
! NOW PLANT THE BLOCK EXIT SEQUENCE
!
         %IF KKK&X'3FFF'=X'1000' %AND LAST INST=0 %THEN RT EXIT
         PPJ(15,21) %IF KKK=1 %AND LAST INST=0;! %STOP AT %ENDOFPROGRAM
         %IF KKK=0 %THEN %START;         ! BEGIN BLOCK EXIT
            %IF PARMTRACE=1 %THEN %START;    ! RESTORE DIAGS POINTERS
               PSF1(LD,1,12)
               DIAG POINTER(LEVEL-1)
               PSF1(STD,1,12)
            %FINISH
            %IF STACK#0 %START
               JJ=NMDECS(LEVEL)>>14
               %IF JJ#0 %THEN %START;   ! ARRAYS TO BE UNDECLARED
                  PF1(STSF,0,TOS,0)
                  PF1(LSS,0,TOS,0)
                  PSF1(ISB,1,JJ)
                  PSF1(USH,0,-2)
                  PF1(ST,0,TOS,0)
                  PF1(ASF,0,TOS,0)
                  GRUSE(ACCR)=0
               %FINISH
            %FINISH %ELSE RESET AUX STACK
         %FINISH
!
! RETURN TO PREVIOUS LEVEL PROVIDED THERE IS A VALID ONE !
!
         %UNLESS LEVEL>2 %OR (LEVEL=2 %AND CPRMODE=2) %THEN %START
            %IF KKK=1 %AND LEVEL=2 %THEN KKK=2 %ELSE %C
                                   FAULT(14,0) %AND %STOP
         %FINISH
         LEVEL=LEVEL-1
         %IF KKK>=X'1000' %THEN %START
            RLEVEL=RLEVEL-1
            RBASE=RLEVEL
         %FINISH
!
! RESTORE INFORMATION ABOUT THE (NEW) CURRENT LEVEL
!
         POP(LEVELINF,KP,N,KP)
         NMAX=N>>16 %IF KKK>=X'1000'
         N=N&X'7FFF'
         %IF KKK=2 %THEN CEND(KKK);    ! ROUND AGAIN FOR 'ENDOFPROGRAM'
!
! COMPLETE THE JUMP AROUND ALL NON-EXTERNAL ROUTINES EXCEPT WHEN
! %TRUSTEDPROGRAM IS IN OPERATION.
!
         %IF KKK>=X'1000' %AND COMPILER=0 %AND(RLEVEL>0 %OR CPRMODE#2)%C
            %THEN %START
            JJ=NEXTP+6
            %UNLESS A(NEXTP+5)=11 %AND A(JJ+FROMAR2(JJ))=2 %START
               ENTER LAB(JROUND(LEVEL+1),0)
               JROUND(LEVEL+1)=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)<<20 ! 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.                                    *
!***********************************************************************
%STRING(31) RT NAME
%STRING(11) LOCAL NAME
%RECORDNAME LCELL(LISTF)
%CONSTINTEGER LARRROUT=X'F300'
%INTEGER DPTR,LNUM,ML,KK,JJ,Q,DEND,BIT,S1,S2,S3,S4,LANGD,II
%INTEGERARRAY DD(0:300);       ! BUFFER FOR SEGMENT OF SST
!
! FILL ALL OUTSTANDING REFERENCES TO THIS DIAGS BLOCK
!
         BIT=1<<LEVEL
         LANGD=KKK>>14<<30!LEVEL<<18;  ! GET LITL FROM PTYPE
         %WHILE RAL(LEVEL)#0 %CYCLE
            POP(RAL(LEVEL),Q,JJ,KK)
            PLUG(Q,JJ,KK!SSTL,4)
         %REPEAT
         PUSH(RAL(LEVEL-1),4,SSTL+4,LANGD) %IF PARMTRACE#0
         DD(0)=L(LEVEL)<<16!(DIAGINF(LEVEL))
         DD(1)=LANGD
         DD(2)=DISPLAY(RLEVEL)<<16!FLAG(LEVEL)&X'3FFF'
         ML=M(LEVEL);                   ! ROUTINE NAME(=0 FOR %BEGIN)
         LNUM=BYTEINTEGER(DICTBASE+ML); ! LENGTH OF THE NAME
         DPTR=4; DEND=0
         %IF LNUM=0 %THEN DD(3)=0 %ELSE %START
            Q=DICTBASE+ML
            RT NAME<-STRING(Q);         ! FOR RTS MOVE IN 1ST 32 CHARS
            LNUM=BYTE INTEGER(ADDR(RT NAME))
            STRING(ADDR(DD(3)))=RTNAME; ! AND UPDATE POINTER PAST
            DPTR=DPTR+LNUM>>2;          ! ACTUAL NO OF CHARS
         %FINISH
         DD(DPTR)=ONWORD(LEVEL);        ! ON CONDITION WORD
         DPTR=DPTR+1
         JJ=NAMES(LEVEL)
         %WHILE 0<=JJ<X'3FFF' %CYCLE
            LCELL==ASLIST(TAGS(JJ))
                                         ! OBTAIN NEXT NAME FORM DECLNS
            %IF LCELL_S1&X'F000'=0 %THEN WARN(2,JJ)
!
! GET ONLY THE MINIMUM OF DETALS NECESSARY
!
            S1=LCELL_S1; S2=LCELL_S2
            S3=LCELL_S3; S4=LCELL_LINK
            LCELL_LINK=ASL; ASL=TAGS(JJ)
            TAGS(JJ)=S4&X'3FFFF'
            PTYPE=S1>>16; TYPE=PTYPE&15
            I=S1>>4&15
            J=S1&15
            K=S3>>16
!
! ALLOW OWNS (LITL=0) AND EXTERNALS (=2) NOT CONSTS(=1) OR EXTRINSIC(=3)
!
            %IF PARMDIAG#0 %AND PTYPE&X'7300'<=X'200' %AND DPTR<297 %C
               %AND (TYPE=1 %OR TYPE=2 %OR TYPE=5) %START
               Q=DICTBASE+WORD(JJ);     ! ADDRESS OF NAME
               %IF I=0 %THEN II=1 %ELSE II=0;   ! GLA OR LNB BIT
               DD(DPTR)=PTYPE<<20!II<<18!K
               LOCAL NAME<-STRING(Q);   ! TEXT OF NAME FROM DICTIONARY
               LNUM=BYTE INTEGER(ADDR(LOCAL NAME))
               STRING(ADDR(DD(DPTR))+4)=LOCAL NAME;! MOVE IN NAME 
               DPTR=DPTR+(LNUM+8)>>2
            %FINISH
            %IF J=15 %THEN FAULT(28,JJ);! SPEC BUT NO BODY GIVEN
            %IF PTYPE&X'3000'#0 %OR TYPE=4 %OR TYPE=6 %THEN %C
            CLEAR LIST(K) %ELSE %START
               %IF I#0 %AND K>511 %AND PTYPE&LARRROUT=0 %AND TYPE#7 %C
                  %THEN WARN(5,JJ)
            %FINISH
            JJ=S4>>18
         %REPEAT
         DD(DPTR)=-1;                   ! 'END OF SEGMENT' MARK
         DPTR=DPTR<<2+4
         %IF PARMTRACE=1 %THEN %START
            LPUT(4,DPTR,SSTL,ADDR(DD(0)));! ADD TO SHARABLE SYM TABS
            SSTL=SSTL+DPTR
         %FINISH
         %END;                          ! OF ROUTINE DTABLE
         %END
%ROUTINE MAKE DECS(%INTEGER Q)
!***********************************************************************
!*    Q IS TO AR ENTRY FOR HEAD OF LINKED DECLARATIONS                 *
!***********************************************************************
%INTEGER QQ,HEAD,PRIO,COUNT,SL
%INTEGERNAME THEAD
%RECORDNAME CELL(LISTF)
      SL=LINE; QQ=FROM AR4(Q)
      HEAD=0; COUNT=0
      %WHILE QQ#0 %CYCLE
         COUNT=COUNT+1
         ABORT %UNLESS A(QQ+5)=8;       ! LINE IS A DECLARATION
         P=QQ+10; CLT
         %IF PREC=3 %OR A(P)#1 %OR A(P+1)# 3 %START
               INSERT AT END(HEAD,X'FFFF',QQ,0) %IF A(P)=1
            %FINISH %ELSE %START
            PRIO=PREC<<4!TYPE
            THEAD==HEAD
            %CYCLE
               CELL==ASLIST(THEAD)
               %IF THEAD=0 %OR PRIO<CELL_S1 %THEN %C
                  PUSH(THEAD,PRIO,QQ,0) %AND %EXIT
               THEAD==CELL_LINK
            %REPEAT
         %FINISH
         QQ=FROM AR4(QQ+6)
      %REPEAT
!
!     NOW MAKE THE ORDEREED DECLARATIONS
! FIRST GRAB TWO TEMPORARIES IF SPACE IS LIKELY TO BE TIGHT
!
      %IF COUNT>=7 %START
         GET WSP(QQ,2);                 ! A DIUBLE WORD
         %IF AVL WSP(1,LEVEL)=0 %THEN GET WSP(QQ,1)
      %FINISH
      %WHILE HEAD#0 %CYCLE
         POP(HEAD,PRIO,QQ,COUNT)
         LINE=FROM AR2(QQ+3)
         P=QQ+10; CLT
         ROUT=0; LITL=0
         CQN(P+1); P=P+2
         DECLARE SCALARS(1,0)
      %REPEAT
      LINE=SL
%END
%ROUTINE DECLARE SCALARS(%INTEGER PERMIT,XTRA)
!***********************************************************************
!*       THIS ROUTINE DECLARES A LIST OF SCALARS FROM INFORMATION      *
!*       IN THE GLOBAL VARIABLES ROUT,NAM,ARR,PREC,TYPE & ACC.IT WORKS *
!*       OUT ROUNDING FACTORS FOR ITSELF.                              *
!*       P POINTS TO THE NAMELIST ON ENTRY AND IS UPDATED.             *
!***********************************************************************
%INTEGER INC,Q,SCHAIN,DMADE,D0
      PACK(PTYPE); J=0
      INC=ACC; DMADE=0; SNDISP=0
      %IF PTYPE=X'33' %THEN INC=(INC+3)&(-4)
      %IF NAM#0 %AND ROUT=0 %AND ARR=0 %THEN INC=8
      %IF NAM>0 %AND ARR>0 %THEN INC=16
      %IF PTYPE=X'35' %AND ACC=0 %THEN FAULT(70,0)
      %IF PERMIT#0 %AND (INC=8 %OR INC=16) %THEN ODD ALIGN
      %IF PTYPE=X'33' %OR (PTYPE=X'35' %AND PERMIT#0)%START
         D0=X'18000000'+ACC
         STORE CONST(Q,4,ADDR(D0))
         PF1(LDTB,0,PC,Q)
         GRUSE(DR)=0
      %FINISH
      %IF PTYPE=X'35' %START
         INC=8
         %IF PERMIT#0 %START
            PF1(STSF,0,TOS,0)
            PF1(LDA,0,TOS,0)
         %FINISH
      %FINISH
      N=(N+3)&(-4)
      %IF PTYPE=X'33' %THEN %START
         PSF1(LDA,1,PTR OFFSET(RBASE))
         PSF1(INCA,0,N+8)
      %FINISH
      %UNTIL A(P-1)=2 %CYCLE;      ! DOWN THE NAMELIST
         DMADE=DMADE+1
         K=FROM AR2(P)
         %IF PTYPE=X'31' %AND PERMIT=0 %THEN N=N+3;! BYTE PARAMS
         %IF PTYPE=X'41' %AND PERMIT=0 %THEN N=N+2
         SCHAIN=N
         %IF ROUT=1 %THEN %START
            SCHAIN=0; J=13
            PUSH(SCHAIN,N,1000,0)
         %FINISH
         KFORM=XTRA
         P=P+3
         %IF PTYPE=X'33' %THEN %START
            PSF1(STD,1,N)
            N=N+8; SCHAIN=N
            %IF A(P-1)=1 %THEN PSF1(INCA,0,INC+8)
         %FINISH
         %IF PTYPE=X'35' %AND PERMIT#0 %START
            PSF1(STD,1,N)
            %IF A(P-1)=1 %THEN PSF1(INCA,0,(ACC+3)&(-4)) %ELSE %START
               Q=((ACC+3)>>2)*DMADE
               PSF1(ASF+12*PARMCHK,0,Q)
               %IF PARMCHK#0 %THEN PPJ(0,4)
            %FINISH
         %FINISH
         STORE TAG(K,SCHAIN)
         N=N+INC
      %REPEAT
      N=(N+3)&(-4) %IF PERMIT#0;! NO ROUNDING AMONG PARAMS
   %END
%INTEGERFN DOPE VECTOR(%INTEGER TYPEP, ELSIZE, %INTEGERNAME ASIZE,LB)
!***********************************************************************
!*        CONSTRUCTS THE DOPE-VECTOR FOR A CONSTANT ARRAY IN THE       *
!*       SHAREABLE SYMBOL TABLES AND RETURNS ITS DISPLACEMENT AS RESULT*
!*       EVENTUALLY ALL NON DYNAMIC DOPE VECTORS SHOULD GO VIA HERE    *
!*       P IS TO ALT (MUST BE 1!) OF P<CBPAIR>                         *
!*       DOPE VECTOR CONSISTS OF :-                                    *
!*       DESRIPTOR (SCALED WORD) POINTING AT FIRST TRIPLE BND=3*ND     *
!*       SIZE (IN BYTES OF ENTIRE ARRAY) FOR STACK ADJUSTMENT          *
!*       AND ND TRIPLES EACH CONSISTING OF:-                           *
!*       LBI - THE LOWER BOUND OF THE ITH DIMENSION                    *
!*       MI - THE STRIDE FOR THE ITH DIMENSION                         *
!*       CBI THE UPPER CHECK =(UBI-LBI+1)*MI                           *
!*       WHERE M1=1(SCALED ARRAYS) OR THE ELEMENT SIZE AND             *
!*       MI = M(I-1)*RANGE(I-1)                                        *
!***********************************************************************
%INTEGER I, JJ, K, ND, D, UNSCAL, PP, M0, HEAD
%RECORDNAME LCELL(LISTF)
%INTEGERARRAY DV(0:39);                 ! ENOUGH FOR 12 DIMENSIONS
         ND=0;  PP=P
         ND=ND+1 %AND P=P+13 %UNTIL A(P)=2
         P=PP
!
! NOW ONE CAN WORK OUT AND FILL IN THE TRIPLES
!
         %IF TYPEP>2 %OR (TYPEP=1 %AND PREC=4)%C
                      %THEN UNSCAL=1 %AND M0=ELSIZE %C
                      %ELSE UNSCAL=0 %AND M0=1
         %CYCLE D=ND,-1,1
            CBPAIR(I, JJ)
            K=3*D
            DV(K)=I
            DV(K+1)=M0
            M0=M0*(JJ-I+1)
            DV(K+2)=M0
         %REPEAT
         P=P+1
!
         %IF UNSCAL=0 %THEN M0=M0*ELSIZE
         %IF ND=1 %THEN LB=I
         ASIZE=M0
         DV(2)=ASIZE
         DV(1)=12
         DV(0)=5<<27!3*ND;           ! DESPTR FOR DV
         K=3*ND+2
         J=ND;                       ! DIMENSIONALITY FOR DECLN
         HEAD=DVHEADS(ND)
         %WHILE HEAD#0 %CYCLE
            LCELL==ASLIST(HEAD)
            %IF LCELL_S2=ASIZE %AND LCELL_S3=DV(5) %START
               %CYCLE D=0,1,K
                  ->ON %UNLESS DV(D)=CTABLE(D+LCELL_S1)
               %REPEAT
               %RESULT=X'80000000'!4*LCELL_S1
            %FINISH
ON:
            HEAD=LCELL_LINK
         %REPEAT
         %IF CONST PTR&1#0 %THEN CONST HOLE=CONST PTR %AND %C
            CONST PTR=CONST PTR+1
         I=4*CONST PTR!X'80000000'
         PUSH(DVHEADS(ND),CONSTPTR,ASIZE,DV(5))
         %CYCLE D=0,1,K
            CTABLE(CONST PTR)=DV(D)
            CONST PTR=CONST PTR+1
         %REPEAT
         %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> = <CBPAIR>,'('<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                                              *
!***********************************************************************
%ROUTINESPEC CLAIM AS
%INTEGER DVDISP, PP, DVF, ELSIZE, TOTSIZE, D0, D1, PTYPEP,  %C
         ARRP, NN, ND, II, JJ, QQ, R, CDV, UNSCAL, DESC, SC,  %C
         LWB, PTYPEPP
      %IF STACK#0 %AND FLAG(LEVEL)=0=NMDECS(LEVEL)>>14 %START
         PSF1(STSF,1,N)
         NMDECS(LEVEL)=NMDECS(LEVEL)!(N<<14)
         N=N+4
      %FINISH
      %IF STACK=0 %THEN SAVE AUX STACK
      ARRP=2*FORMAT+1;  ARR=ARRP;  PACK(PTYPEP)
      ELSIZE=ACC;  SNDISP=0
      %IF TYPE>2 %OR (TYPE=1 %AND PREC=4)%C
                   %THEN UNSCAL=1 %AND SC=3 %C
                  %ELSE UNSCAL=0 %AND SC=PREC
      DESC=SC<<27!UNSCAL<<25!(1-PARMARR)<<24;! ARRAY DESCRIPTOR SKELETON
         %IF PREC=4 %THEN DESC=X'58000002'
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
      %IF A(P)=1 %THEN ->CONSTDV;       ! P<BPAIR> =<CBPAIR>

! NORMAL CASE - PLANT CODE TO SET UP DOPE-VECTOR AT RUN TIME

      ND=0;  JJ=P;  DVF=0;  TOTSIZE=X'FFFF'
      %UNTIL A(P)=2 %CYCLE;             ! TILL NO MORE BPAIRS
         P=P+1;  ND=ND+1;               ! COUNT NO OF DIMENSIONS
         SKIP EXP;  SKIP EXP
      %REPEAT
      P=JJ;  DVDISP=N;                  ! DVDISP IS D-V POSITION
      N=N+12*ND+12;                     ! CLAIM SPACE FOR THE D-V
      FAULT(37,0) %IF ND>12;            ! TOO MANY DIMENSIONS
      D0=5<<27!3*ND;  D1=12;            ! DESCPTR FOR DV
      STORE CONST(JJ,8,ADDR(D0))
      PF1(LD,0,PC,JJ)
      PSF1(STD,1,DVDISP)
      GRUSE(DR)=0

      %IF UNSCAL=0 %THEN JJ=1 %ELSE JJ=ELSIZE
      PSF1(LSS,0,JJ);                   ! M1 THE FIRST MULTIPLIER
      GRUSE(ACCR)=0
      %CYCLE II=ND,-1,1
         P=P+1
         QQ=DVDISP+12*II;               ! TRIPLE FOR IITH DIMENSION
         PSF1(ST,1,QQ+4);               ! STORE MULTIPLIER
         CSEXP(ACCR,X'51');             ! LOWER BOUND
         %IF ND=1 %AND PTYPEP&7<=2 %AND FORMAT=0 %AND GRUSE(ACCR)=5 %C
            %AND GRINF(ACCR)=0 %THEN PTYPEPP=PTYPEPP+256
         PSF1(ST,1,QQ);                 ! STORED IN DV
         CSEXP(ACCR,X'51');             ! UPPER BOUND
         PSF1(ISB,1,QQ)
         GRUSE(ACCR)=0
         %IF COMPILER=0 %OR PARMARR#0 %START
            PF3(JAF,6,0,3);             ! JUMP UNLESS NEGATIVE
            PSF1(LSS,0,-1);             ! SET UP -1 (ENSURES 0 ELEMENTS
         %FINISH
         PSF1(IAD,0,1);                 ! CONVERTED TO RANGE
         PSF1(IMY,1,QQ+4);              ! RANGE*MULTIPLIER
         PSF1(ST,1,QQ+8);               ! AND STORED IN DV
      %REPEAT
      P=P+1
      %IF UNSCAL=0 %AND ELSIZE#1 %THEN PSF1(IMY,0,ELSIZE)
      PSF1(ST,1,DVDISP+8)
      ->DECL
CONSTDV:                                ! ONE DIMENSION - CONSTANT BOUNDS
      DVF=1;  P=P+1;  CDV=1
      DVDISP=DOPE VECTOR(TYPE,ELSIZE,TOTSIZE,LWB);! AND GENERATE A D-V
      ND=J
      %IF ND=1 %AND LWB=0 %AND TYPE<=2 %C
         %AND FORMAT=0 %THEN PTYPEPP=PTYPEP+256
                                        ! SET ARR=2 IF LWB=ZERO


DECL:                                   ! MAKE DECLN - BOTH WAYS
      J=ND
      ODD ALIGN
      PTYPE=PTYPEPP;  UNPACK
      %IF DVF#0 %THEN %START;           ! ARRAY IS STRING OF LOCALS
         R=TOTSIZE
         %IF UNSCAL=0 %THEN R=R//ELSIZE
         D0=DESC
         D0=D0!R %UNLESS PREC=4
         STORE CONST(D1,4,ADDR(D0))
         PF1(LSS,0,PC,D1)
      %FINISH %ELSE %START
         STORE CONST(D1,4,ADDR(DESC))
         PF1(LSS,0,PC,D1)
         PSF1(OR,1,DVDISP+20) %UNLESS PREC=4
      %FINISH
      %IF DVF#0 %THEN QQ=PC %ELSE QQ=LNB
      PSORLF1(LDRL,0,QQ,DVDISP)
      %CYCLE JJJ=0,1,NN-1;              ! DOWN NAMELIST
         PSF1(ST,1,N+16*JJJ);           ! ARRAY BOUND
         PSF1(STD,1,N+8+16*JJJ);        ! DV POINTER
      %REPEAT
      %CYCLE JJJ=0,1,NN-1;              ! DOWN NAMELIST
         %IF PARMARR=0 %AND ND=1 %AND TYPE<=2 %AND PTYPEPP&X'F00'#2 %C
             %START
                                        ! ADJUST DESC
            %IF DVF#0 %THEN %START
               PSF1(LSS,0,LWB*ELSIZE)
            %FINISH %ELSE %START
               PSF1(LSS,1,DVDISP+12)
               PSF1(IMY,0,ELSIZE) %UNLESS ELSIZE=1
            %FINISH
            %IF STACK#0 %THEN %START
               PF1(STSF,0,TOS,0)
               PF1(IRSB,0,TOS,0)
            %FINISH %ELSE PSF1(IRSB,2,AUXSBASE(LEVEL))
            PSF1(ST,1,N+4)
         %FINISH %ELSE %START;          ! NO ADJUSTMENT OF DESCRPT
            %IF STACK#0 %THEN PSF1(STSF,1,N+4) %ELSE %START
               PSF1(LSS,2,AUXSBASE(LEVEL))
               PSF1(ST,1,N+4)
            %FINISH
         %FINISH

         ACC=ELSIZE;                    ! RESET ACC AFTER DV CMPLD
         KFORM=FINF;                    ! FORMAT INFORMATION
         K=FROM AR2(PP+3*JJJ)
         STORE TAG(K,N)
         N=N+16
         CLAIM AS
      %REPEAT
      P=P+1;                            ! PAST REST OF ARRAYLIST
      %IF A(P-1)=1 %THEN ->START
      GRUSE(ACCR)=0
      GRUSE(DR)=0
      %RETURN
%ROUTINE CLAIM AS
!***********************************************************************
!*       CLAIM THE SPACE FOR AN ARRAY FROM STACK OR AUX STACK          *
!***********************************************************************
%INTEGER T, D
      %IF FORMAT#0 %THEN %RETURN
      %IF STACK=1 %THEN %START;         ! FROM AUTOMATIC STACK
         %IF CDV=1 %THEN %START;        ! CONSTANT BOUNDS
            T=(TOTSIZE+3)//4
            PSF1(ASF+12*PARMCHK,0,T);   ! ASF OR LB
            PPJ(0,4) %IF PARMCHK#0
         %FINISH %ELSE %START;          ! DYNAMIC BOUNDS
            PSF1(LSS,1,DVDISP+8);       ! ARRAY SIZE BYTES
            PSF1(IAD,0,3)
            PSF1(USH,0,-2);             ! ARRAY SIZE WORDS
            PF1(ST,0,BREG,0)
            FORGET(BREG)
            %IF PARMCHK#0 %THEN PPJ(0,4) %ELSE PF1(ASF,0,BREG,0)
         %FINISH
         CHECK STOF
      %FINISH %ELSE %START
         %IF CDV=1 %THEN %START
            TOTSIZE=(TOTSIZE+3)&(-4)
            %IF TOTSIZE<X'1FFFF' %THEN PSF1(LSS,0,TOTSIZE) %C
               %ELSE %START
               STORE CONST(D,4,ADDR(TOTSIZE))
               PF1(LSS,0,PC,D)
            %FINISH
         %FINISH %ELSE %START
            PSF1(LSS,1,DVDISP+8)
            PSF1(IAD,0,3)
            PSF1(AND,0,-4)
         %FINISH
         %IF PARMCHK#0 %THEN %START
            PF1(ST,0,TOS,0)
            PSF1(LB,2,AUXSBASE(LEVEL))
            FORGET(BREG)
            PF1(IAD,0,BREG,0)
         %FINISH %ELSE PSF1(IAD,2,AUXSBASE(LEVEL))
         PF1(ST,2,7,0);                 ! STORE UPDATED POINTER
         %IF PARMOPT#0 %THEN %START
            PF1(ICP,1,0,2)
            PPJ(2,8)
         %FINISH
         %IF PARMCHK#0 %START
            PF1(LDTB,0,PC,PARAM DES(3))
            PF1(LDB,0,TOS,0)
            PF1(LDA,0,BREG,0)
            PF2(MVL,1,1,0,0,UNASSPAT&255)
         %FINISH
      %FINISH
      FORGET(ACCR)
%END
%END
!         %ROUTINE TEST NST
!!***********************************************************************
!!*       SEE IF NAME 'K' HAS BEEN DECLARED BEFORE AT THIS LEVEL        *
!!***********************************************************************
!         FNAME=K
!         FAULT(7,FNAME) %IF FROM1(TAGS(FNAME))>>8&15=LEVEL
!         %END
         %ROUTINE CLT
!***********************************************************************
!*       DEAL WITH PHRASE TYPE AND SET PREC,TYPE & ACC                 *
!*       ONLY PROBLEM IS STRING WHICH HAS OPTIONAL MAX LENGTH ALSO     *
!*       P ON PHRASE TYPE AT ENTRY - TO NEXT PHRASE AT EXIT.           *
!***********************************************************************
%CONSTBYTEINTEGERARRAY TYPEFLAG(1:10)= %C
                                        X'51',X'52',0,X'31',X'35',
                                        X'41',0,X'62',X'61',X'72';
%INTEGER ALT
         ALT=A(P)
         TYPE=TYPEFLAG(ALT)
         %IF TYPE=0 %THEN P=P+1 %AND TYPE=TYPEFLAG(A(P)+7)
         PREC=TYPE>>4
         TYPE=TYPE&7
         PREC=6 %IF TYPE=2 %AND ALL LONG#0 %AND PREC<=5;! DEAL WITH '%REALSLONG'
         ACC=BYTES(PREC)
         %IF TYPE=5 %THEN %START;    ! P<TYPE>='%STRING'
            %IF A(P+1)=1 %THEN %START;! MAX LENGTH GIVEN
               P=P+2
               ACC=A(P)+1
            %FINISH %ELSE ACC=0 %AND P=P+1
         %FINISH
         P=P+1
         %END
         %ROUTINE CQN(%INTEGER P)
!***********************************************************************
!*       SET NAM,ARR & ACC 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 %AND ACC=16;! ARRAYNAMES
         %IF I<=2 %THEN NAM=1;           ! ARRAYNAMES & NAMES
         %IF I=2 %THEN ACC=8;            ! NAMES USE 8-BYTE DESCRIPTOR
         %END
         %ROUTINE     CRSPEC (%INTEGER M)
!***********************************************************************
!*        MODE=0  FOR NORMAL ROUTINE SPEC                              *
!*        MODE=1 FOR EXTERNAL(ETC) ROUTINE SPECS XREF NEEDED           *
!*        MODE=2 FOR %SPEC FOR RT PARAMS                               *
!***********************************************************************
%INTEGER KK,JJ,Q,TYPEP,INC,PPOSN,OPHEAD,OPBOT
%STRING(34) XNAME
         Q=0; LITL=EXTRN&3
         %IF M#2 %THEN %START
!
! WORK OUT TYPEP IE TYPE OF ENTITITY BY INSPECTING AR FOR P<RT>
!
            %IF A(P+1)=1 %THEN %START;  ! P<RT>=%ROUTINE
               TYPEP=LITL<<14!X'1000'; P=P+3
            %FINISH %ELSE %START;       ! P<RT>=<TYPE><FNORMAP>
               ROUT=1; ARR=0; P=P+2
               CLT; NAM=(A(P)-1)<<1
               PACK(TYPEP)
               P=P+2
            %FINISH
            P=P+4;                      ! PAST HOLE FOR DECLINKS 
         %FINISH
         KK=FROM AR2(P); COPYTAG(KK)
!
! IF KK IS A VALID RT TYPE PARAM IT MUST BE DECLARED AT THE CURRENT
! LEVEL AND HAVE 1000 PARAMS. IF KK IS A NEW DECLARATION '%SPEC' CANNOT
! BE USED AND THE NAME MUST NOT BE SET AT THE CURRENT LEVEL.
!
         OPHEAD=K
         %IF SNPT#PTYPE>=X'1000' %THEN FROM12(OPHEAD,JJ,Q)
         %UNLESS OLDI=LEVEL %AND Q=1000 %AND %C
                 (M=2 %OR PTYPE&X'FBFF'=TYPEP) %THEN %START
!
! KK IS NOT A VALID RT TYPE PARAM
!
            %UNLESS OLDI#LEVEL %AND M<=1 %THEN %START;! KK VALID DECLN
               %IF M#0 %THEN FAULT(7-M>>1<<2,KK) %AND %RETURN
                                        ! FAULT 3(SPEC?)OR 7(SET TWICE)
                                        ! STORE TAG GIVES FAULT(7) FOR
                                        ! M=0 WHEN REPLACE TAG ESSENTIAL
            %FINISH
            JJ=0; OPHEAD=NEWCELL;       ! SO MAKE DECLARATION
            J=15-M; PTYPE=TYPEP
            KFORM=0; ACC=0; SNDISP=0
            STORE TAG(KK,OPHEAD)
         %FINISH
         PPOSN=20;                      ! DISPLCMENT OF EACH PARAM
         INC=1
         P=P+2; Q=0;                    ! Q COUNTS NO OF FORMAL PARAMS
         OPBOT=OPHEAD
         %WHILE A(P)=1 %CYCLE;          ! WHILE SOME(MORE) FPS
            P=P+INC;                    ! P<COMMA'> BETWEEN FPDELS
            CFPDEL;                     ! GET TYPE & ACC FOR NEXT GROUP
            %IF KFORM=1 %THEN PPOSN=PPOSN+3
            %UNTIL A(P-1)=2 %CYCLE;     ! DOWN <NAMELIST> FOR EACH DEL
               BINSERT(OPHEAD,OPBOT,PTYPE,ACC<<16!PPOSN,0)
               Q=Q+1; P=P+3
               %IF PTYPE=X'35' %THEN PPOSN=PPOSN+3 %ELSE PPOSN=PPOSN+ACC
            %REPEAT
            INC=2;                      ! TO IGNORE ALT OF P<COMMA'>
         %REPEAT
         %IF M=1 %THEN %START
            XNAME<-STRING(DICTBASE+WORD(KK))
            %IF EXTRN=1 %THEN XNAME<-'S#'.XNAME
            CXREF(XNAME,0,2,JJ)
         %FINISH
         %IF M=0 %AND RLEVEL=0 %THEN CODE DES(JJ)
         REPLACE123(OPHEAD,JJ,Q,0)
         %END
         %ROUTINE CFPDEL
!***********************************************************************
!*       SET UP PTYPE & ACC FOR A LIST OF FORMAL PARAMETERS            *
!*       P<FPDEL>=<RT><%NAME'>,<TYPE><%QNAME'>,'%NAME',                *
!*                '%RECORD'<%ARRAY'>'%NAME'.                           *
!***********************************************************************
%SWITCH FP(1:4)
%INTEGER FPALT
         FPALT=A(P); P=P+1; KFORM=4; LITL=0
         ->FP(FPALT)
FP(1):                                  ! (TYPE)(FMQNAME)
         ROUT=0; CLT
         %IF A(P)=1 %THEN %START;       ! FN OR MAP
            ROUT=1; P=P+1; ARR=0
            NAM=(A(P)-1)<<1+1;         ! 1 FOR FN 3 FOR MAP
            P=P+2; ACC=16
         %FINISH %ELSE %START
            P=P+1; CQN(P)
            FAULT(70,0) %IF TYPE=5 %AND ACC=0
            %IF NAM=0 %AND PREC=3 %AND TYPE=1 %THEN KFORM=1;! BYTE BY VALUE
            P=P+1
         %FINISH
         ->PK
FP(2):                                  ! RECORD(%ARRAY')%NAME
         ARR=2-A(P); ROUT=0
         ACC=8+8*ARR; TYPE=3; PREC=3
         NAM=1; P=P+1; ->PK
FP(3):                                  ! %ROUTINE (%NAME')
         ROUT=1; NAM=1
         ARR=0; TYPE=0; PREC=0
         P=P+1; ACC=16
         ->PK
FP(4):                                  ! %NAME
         ACC=8; NAM=1
         ROUT=0; TYPE=0
         ARR=0; PREC=0
PK:      PACK(PTYPE)
         %END
%ROUTINE DIAG POINTER(%INTEGER LEVEL)
         %IF PARMTRACE#0 %THEN %START
            PUSH(RAL(LEVEL),1,CA,LDB<<24!3<<23)
            PF1(LDB,0,0,0)
            GRUSE(DR)=0
         %FINISH
%END
%ROUTINE RHEAD(%INTEGER KK)
!***********************************************************************
!*       COMPILES CODE FOR BLOCK AND ROUTINE ENTRY                     *
!*       KK IS THE RT/FN/MAP NAME (=-1 FOR %BEGIN BLOCKS)              *
!***********************************************************************
%INTEGER W1, W3, INSRN, AT
         PUSH(LEVELINF, 0, NMAX<<16!N, 0)
         LEVEL=LEVEL+1
         NMDECS(LEVEL)=0; AUXSBASE(LEVEL)=0
         NAMES(LEVEL)=-1
         ONINF(LEVEL)=0; ONWORD(LEVEL)=0
         %IF KK>=0 %THEN %START
            RLEVEL=RLEVEL+1;  RBASE=RLEVEL
         %FINISH
         FAULT(34, 0) %IF LEVEL=MAX LEVELS
         FAULT(105, 0) %IF LEVEL>MAX LEVELS
         %IF KK>=0 %AND RLEVEL>1 %START;! ROUTINE ENTRY
            COPY TAG(KK); JJ=K;         ! LIST OF JUMPS
            J=FROM1(JJ)
            %IF J=0 %AND LEVEL>2 %START;! REPLACE 'NOT USED' BIT
               REPLACE1(TAGS(KK), FROM1(TAGS(KK))&X'FFFF3FFF')
            %FINISH
!
! NOW FILL ANY JUMPS TO THIS ROUTINE PLANTED SINCE
! THE ROUTINESPEC WAS COMPILED. SEE ALSO 'RT JUMP'
!
            %WHILE J#0 %CYCLE
               POP(J, INSRN, AT, W1)
               W3=CA-AT
               W3=W3//2 %IF INSRN>>25=CALL>>1
               INSRN=INSRN+W3
               PLUG(1, AT, INSRN,4)
            %REPEAT
            REPLACE1(JJ, CA);           ! NOTE ADDR FOR FUTURE CALLS
         %FINISH
         %IF KK>=0 %AND RLEVEL=1 %THEN DIAG POINTER(LEVEL) %C
             %AND PSF1(STD,1,12)
         %IF KK<0 %THEN W3=0 %ELSE W3=WORD(KK)
         L(LEVEL)=LINE;  M(LEVEL)=W3
         FLAG(LEVEL)=PTYPE;             ! CURRENT BLOCK TYPE MARKER
%END
%ROUTINE RDISPLAY(%INTEGER KK)
!***********************************************************************
!*       SET UP OR COPY THE DISPLAY (A WORD ARRAY CONTAINING COPIES OF *
!*       LNB FOR THE GLOBAL LEVELS. THE HIGHEST LEVEL ENTRY IS TO THE  *
!*       GLA(PLT) FOR OWNS AND IS ALSO KEPT IN(LNB+4) IN CASE WE WISH  * 
!*       TO MOVE TO READ-ONLY PLTS. ON INTERNAL CALLS THE LNB FOR THE  *
!*       NEXT MOST GLOBAL LEVEL IS STACKED AS AN EXTRA PARAMETER       *
!***********************************************************************
%INTEGER W1,W2,STACK,OP,INC
         %IF KK>=0 %OR LEVEL=2 %START;    ! DISPLAY NEEDED
            STACK=0; DISPLAY(RLEVEL)=N
            %IF LEVEL#2 %THEN %START
!               PF1(LXN,0,TOS,0)
               GRUSE(XNB)=4; GRINF(XNB)=RLEVEL-1; GRAT(XNB)=CA
               GRUSE(CTB)=0; GRUSE(BREG)=0
               PF1(LD,0,XNB,12);         ! COPY PLT DESCRIPTOR
               DIAG POINTER(LEVEL)
               PSF1(STD,1,12)
               W1=RLEVEL-1; W2=DISPLAY(W1)
               %IF W1=1 %THEN PF1(STXN,0,TOS,0) %AND N=N+4 %ELSE %START
                  %WHILE W1>0 %CYCLE
                     OP=LSS; INC=1
                     %IF W1>=2 %THEN OP=LSD %AND INC=2
                     %IF W1>=4 %THEN OP=LSQ %AND INC=4
                     PF1(OP+STACK,0,XNB,W2)
                     STACK=-32; N=N+4*INC
                     W2=W2+4*INC; W1=W1-INC
                  %REPEAT
               %FINISH
            %FINISH
            %IF STACK#0 %THEN PF1(ST,0,TOS,0);    ! ST TOS
            PF1(STLN,0,TOS,0)
            N=N+4
         %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 PARMTRACE#0 %START
            PF1(LSS,0,PC,4*CONST BTM!X'80000000') %IF PARMOPT#0;! M'IDIA'
            %IF KK>=0 %OR LEVEL=2 %START
               %IF PARMOPT#0 %THEN %START
                  PSF1(SLSS,0,LINE)
                  N=N+4
               %FINISH %ELSE PSF1(LSS,0,LINE)
               PF1(ST,0,TOS,0)
            %FINISH %ELSE %START
               %IF PARMOPT#0 %THEN %START
                  PSF1(ST,1,N)
                  N=N+4
               %FINISH
               PSF1(LSS,0,LINE)
               PSF1(ST,1,N)
               PSF1(LD,1,12);           ! UPDATE BND FIELD
               DIAG POINTER(LEVEL)
               PSF1(STD,1,12)
            %FINISH
            DIAGINF(LEVEL)=N
            N=N+4
            GRUSE(ACCR)=0;               ! NEEDED FOR %BEGIN BLOCKS
         %FINISH
         %IF PARMOPT#0 %AND KK>=0 %AND LEVEL=2 %START
            PF1(STSF,0,BREG,0)
            PF1(STLN,0,TOS,0)
            PF1(SBB,0,TOS,0)
            PSF1(CPB,0,N)
            PPJ(7,13)
         %FINISH
!
! CLAIM (THE REST OF) THE STACK FRAME
!
         %IF KK>=0 %OR LEVEL=2 %START
            SET(RLEVEL)=N<<18!CA
            NMAX=N
            PF1(ASF+12*PARMCHK,0,0,0);   ! ASF OR LB
            PPJ(0,4) %IF PARMCHK#0
         %FINISH
!
         %IF KK>=0 %START;              ! ENSURE FNS RETURN RIGHT ACS
            CHECK STOF;                   ! CHECK FOR STACK O'FLOW
         %FINISH
%END
%ROUTINE CHECK STOF
!***********************************************************************
!*       CHECK THE STACK FOR OVERFLOW (LEAVING 4K MARGIN FOR MDIAG     *
!***********************************************************************
         %IF PARMOPT#0 %THEN %START
!
!         STSF  TOS                    GET STACK POINTER
!         LSS   TOS
!         USH   +14
!         USH   -15                    LOSE SEGMENT NO
!         ICP   X'1F800'               CHECK WITHIN SEG ADDRESS
!                                      SHIFTED DOWN 1 PLACE
!         JCC   2,EXCESS BLKS
!
            PF1(STSF,0,TOS,0)
            PF1(LSS,0,TOS,0)
            PSF1(USH,0,14)
            PSF1(USH,0,-15)
            PF1(ICP,0,0,ST LIMIT>>1)
            PPJ(2,8)
          %FINISH
%END;                                   ! OF ROUTINE RHEAD
%ROUTINE CIOCP(%INTEGER N,REG)
!***********************************************************************
!*       COMPILES A CALL ON IOCP ENTRY POINT NO 'N'                    *
!*       2ND PARAMETER IS ALREAD IN THE ACC WHICH IS 32 BITS           *
!***********************************************************************
%INTEGER XYNB,OP1,OP2
         %IF IOCPDISP=0 %THEN CXREF(IOCPEP,0,2,IOCPDISP)
         %IF REGISTER(BREG)#0 %THEN BOOT OUT(BREG)
         %IF REG=ACCR %THEN OP1=LUH %AND OP2=ST %C
                      %ELSE OP1=LDTB %AND OP2=STD
         PSF1(OP1,0,N)
         PSF1(PRCL,0,4)
         PF1(OP2,0,TOS,0)
         XYNB=SET XORYNB(-1,-1);        ! TO PLT
         PSF1(RALN,0,7)
         PF1(CALL,2,XYNB,IOCPDISP)
         FORGET(-1)
%END
%ROUTINE CUI(%INTEGER CODE)
!***********************************************************************
!*       COMPILE AN UNCONDITIONAL INSTRN WHEREEVER IT OCCURS           *
!*       CODE=0 UNCONDITIOALLY,=1 AFTER %THEN, =2 AFTER %ELSE          *
!***********************************************************************
%INTEGER MARKER,J,LNAME,TYPEP,PRECP,GWRDD,LWB,XYNB,ARRP
%SWITCH SW(1:8)
          REPORTUI=0; ->SW(A(P))
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,0)
            P=P+1
         %FINISH
AUI:     J=A(P); P=P+1
         %IF J=1 %THEN CUI(CODE)
         %RETURN
SW(2):                                  ! -> (NAME)(APP)
         NMDECS(LEVEL)=NMDECS(LEVEL)!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(MASK,LNAME,0)
            REPORTUI=1 %IF MASK=15
         %FINISH %ELSE %START;          ! SWITCH LABELS
            COPY TAG(LNAME)
            ARRP=ARR
            GWRDD=SNDISP<<2;            ! BYTE DISP OF DESCRIPTOR IN PLT
            %UNLESS OLDI=LEVEL %AND TYPE=6 %START
               FAULT(4,LNAME); P=P-1; SKIP APP
               %RETURN
            %FINISH
            LWB=FROM2(K);                ! GET LOWER BOUND
            CSEXP(BREG,X'51')
            %IF ARRP=1 %THEN %START
               PSF1(SBB,0,LWB) %UNLESS LWB=0
            %FINISH %ELSE PSF1(MYB,0,2)
            XYNB=SET XORYNB(-1,-1);     ! TO PLT
            PF1(LB,3,XYNB,GWRDD);       ! RELATIVE DISP TO B
            PF1(ADB,0,XYNB,GWRDD+4);    ! MAKE ABSOLUTE
            PF1(JUNC,0,BREG,0);         ! AND JUMP TO IT
            REPORTUI=1; FORGET(-1)
         %FINISH
         %RETURN
SW(3):                                  ! RETURN
         FAULT(30,0) %UNLESS FLAG(LEVEL)&X'3FFF'=X'1000'
         P=P+1
RET:     RT EXIT
         REPORT UI=1
         CURR INST=1 %IF CODE=0
         %RETURN
SW(4):                                 ! %RESULT(ASSOP)(EXPR)
         PTYPE=FLAG(LEVEL)&X'3FFF'; UNPACK
         %IF PTYPE>X'1000' %AND A(P+1)#3 %THEN %START;! ASSOP #'->'
            %IF A(P+1)=1 %AND NAM#0 %AND A(P+5)=4 %AND A(P+6)=1 %START
               P=P+7; TYPEP=TYPE; PRECP=PREC
               CNAME(4,ACCR)
               FAULT(81,0) %UNLESS A(P)=2; P=P+1
               FAULT(83,0) %UNLESS TYPEP=TYPE %AND PRECP=PREC
               ->RET
            %FINISH
            %IF A(P+1)=2 %THEN %START;    ! ASSOP='='
               P=P+2
               %IF NAM#0 %THEN TYPE=1;    ! MAPS HAVE INTEGER RESULTS
               %IF TYPE=5 %THEN %START
                  CSTREXP(0,ACCR)
                  PSF1(LD,1,DISPLAY(RBASE)-8); ! RESULT DESCRPT
                  PF1(IAD,0,PC,SPECIAL CONSTS(2))
                  PF2(MV,1,1,0,0,UNASSPAT&255)
                  PSF1(LD,1,DISPLAY(RBASE)-8)
                  PF1(LDB,2,7,0)
                  COPY DR
               %FINISH %ELSE %START
                  %IF PREC<5 %THEN PREC=5
                  %IF NAM=0 %THEN KK=PREC<<4!TYPE %ELSE KK=X'51'
                  CSEXP(ACCR,KK)
               %FINISH; ->RET
            %FINISH
         %FINISH
         FAULT(31,0)
         P=P+2; SKIP EXP;                 ! IGNORE SPURIOUS RESULT
         %RETURN
SW(5):                                  ! %MONITOR (AUI)
         PSF1(LSS,0,0);                 ! ERR=0
         PF1(ST,0,TOS,0);               ! EXTRA=0
         PPJ(0,2);                      ! TO ERROR ROUTINE
         P=P+1; ->AUI
SW(6):                                 ! %STOP
         PPJ(0,21)
         P=P+1
         CURR INST=1 %IF CODE=0
         REPORTUI=1
         %RETURN
SW(7):                                  !'%SIGNAL'(EVENT')(N)(OPEXPR)
         PSF1(PRCL,0,4)
         PSF1(JLK,0,1);                 ! STACK DUMMY PC
         %IF NMDECS(LEVEL)&16 #0 %START;! IN AN 'ON' GROUP
            %IF FLAG(LEVEL)<=2 %START;  ! IN A BEGIN BLOCK
               PSF1(LD,1,12);           ! SO RESET DIAG POINTER
               DIAGPOINTER(LEVEL-1);    ! TO NEXT OUTER BLOCK
               PSF1(STD,1,12)
               PF1(STLN,0,TOS,0)
            %FINISH %ELSE %START;       ! 'ON IN A RT/FN/MAP
               PSF1(LSS,1,0);           ! GET PREVIOUS LNB
               PF1(ST,0,TOS,0);         ! AND STACK THAT
            %FINISH
         %FINISH %ELSE PF1(STLN,0,TOS,0)
         GRUSE(ACCR)=0
         J=A(P+2);                      ! EVENT NO
         FAULT(26,0) %UNLESS 1<=J<=14
         %IF A(P+3)=1 %START;           ! SUBEVENT SPECIFIED
            P=P+4; CSEXP(ACCR,X'51')
            PF1(AND,0,0,255)
            PF1(OR,0,0,256*J)
         %FINISH %ELSE PF1(LSS,0,0,256*J)
         PSF1(SLSS,0,0)
         PF1(ST,0,TOS,0)
         XYNB=SET XORYNB(-1,-1);        ! TO PLT
         PSF1(RALN,0,9)
         PF1(CALL,2,XYNB,40)
         CURR INST=1 %IF CODE=0
         REPORTUI=1; %RETURN
SW(8):                                  ! %EXIT
         KK=FROM2(CYCLE(LEVEL))
         %IF KK=-1 %THEN FAULT(54,0) %AND %RETURN
         REPLACE2(CYCLE(LEVEL),KK!X'80000000')
         ENTER JUMP(MASK,KK>>16&X'7FFF',B'10')
         REPORTUI=1 %IF MASK=15
         CURR INST=1 %IF CODE=0
%END
%ROUTINE CSTART(%INTEGER CODE)
!***********************************************************************
!*       NOTE A START FOR APPROPIATE ACTION AT THE FINISH              *
!***********************************************************************
         SFLABEL=SFLABEL-1
         PUSH(SBR(LEVEL),CODE,SFLABEL,CYCLE(LEVEL))
%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)                     *
!*       >4 IS FOR STORE ACC BY 'ASSOP&3' INTO NAME                    *
!*                                                                     *
!*       P POINTS TO THE EXPRESSION. P1 TO THE NAME ON LHS             *
!***********************************************************************
%INTEGER Q,QQ,KK,TYPEP,PRECP,PTYPEP,JJJ,P2,JJ, %C
         RHTYPE,ACCP,II,HEAD1,NOPS,TPCELL,LVL,BOT1
%RECORD R(RD)
%SWITCH SW(0:3);                       ! TO SWITCH ON ASSOP
         P2=P
         %IF ASSOP>4 %THEN RHTYPE=TYPE
         P=P1; REDUCE TAG;             ! LOOK AT LH SIDE
         PTYPEP=PTYPE; JJ=J
         KK=K; II=I; LVL=OLDI
         TPCELL=TCELL; ACCP=ACC
         P=P2; TYPEP=TYPE; PRECP=PREC; ! SAVE USEFUL INFO FOR LATER
         -> SW(ASSOP&3)
!
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;                      ! CLEAR TEMPORAYRY LIST HEADS
         TYPE=1 %UNLESS TYPE=2;        ! DEAL WITH UNSET NAMES
         TYPEP=TYPE
         NOPS=1<<18+1; P=P2+3
         PUSH(HEAD1,ASSOP&3+33,PRECP,0); ! ASSIGNMENT OPERATOR
         BOT1=HEAD1
         PUSH(HEAD1,PTYPEP<<16!2,P1,0);  ! LHS
         %IF ASSOP>4 %THEN %START
            FAULT(24,0) %UNLESS TYPE=RHTYPE
            PUSH(HEAD1,RHTYPE<<16!9,0,0)
            OLINK(ACCR)=HEAD1
         %FINISH %ELSE TORP(HEAD1,BOT1,NOPS); ! RHS TO REVERSE POLISH
         Q=P; EXPOP(HEAD1,-1,NOPS,256+PRECP<<4+TYPEP); ! PLANT CODE
         P=Q
!        CLEAR LIST(HEAD1)
         ASLIST(BOT1)_LINK=ASL
         ASL=HEAD1
         %RETURN
!NA:      NOTE ASSMENT(-1,ASSOP&3,A(P1))
ST:                                    ! STRINGS
!
! PICK OFF NULL STRINGS AND SUBSTITUTE A CRAFTY MVL FOR S='' OR S=""
!
         %IF A(P+3)=4 %AND A(P+4)=2 %AND((A(P+5)=X'51' %AND %C
            FROMAR4(P+6)=0 %AND A(P+10)=2) %OR %C
            (A(P+5)=5 %AND A(P+10)=0 %AND A(P+11)=2)) %THEN %START
            Q=P+12-A(P+10)>>1
            P=P1; CNAME(1,DR)
            PF2(MVL,0,1,0,0,0)
            P=Q; %RETURN
         %FINISH
         %IF ASSOP<=3 %THEN CSTREXP(0,ACCR)
         ASSOP=ASSOP&3
         QQ=STRINGL; Q=P
         REGISTER(ACCR)=1
         OLINK(ACCR)=ADDR(R)
         R_PTYPE=X'51'; R_FLAG=9; R_UPTYPE=0
         R_XB=ACCR
         P=P1; CNAME(1,DR)
         %IF R_FLAG#9 %THEN PF1(LSD,0,TOS,0)
         PF1(IAD,0,PC,SPECIAL CONSTS(2))
         %IF (ROUT#0 %OR NAM#0=ARR) %AND QQ=0 %START; ! LHS=MAP : DR BOUND NOT VALID
            %IF PARMOPT#0 %THEN PPJ(0,18) %ELSE %START
               PF1(STUH,0,BREG,0)
               PF1(LUH,0,BREG,0)
               PF1(LDB,0,BREG,0)
            %FINISH
            GRUSE(BREG)=0
         %FINISH
         GRUSE(ACCR)=0
         REGISTER(ACCR)=0
         %IF QQ>0 %AND ASSOP#3 %THEN PF2(MV,0,0,QQ,0,0) %ELSESTART
            %IF ASSOP=3 %THEN PF1(STD,0,TOS,0)
            PF2(MV,1,1,0,0,UNASSPAT&255)
            %IF PARMARR#0 %OR ASSOP=3 %THEN PSF1(USH,0,8) %ANDC
               PSF1(USH,0,-40)
            %IF PARMARR#0 %AND ASSOP=2 %THEN PPJ(36,9)
            %IF ASSOP=3 %THEN %START
               PF1(IRSB,2,TOS,0)
               PF1(ST,2,7,0);           ! STORE AMENDED CURRENT LENGTH
            %FINISH
         %FINISH
         P=Q; %RETURN
!
! THIS SECTION DEALS WITH OPERATIONS ON COMPLETE RECORDS
!
RECOP:                                   ! LHS IS RECORD WITHOUT SUBNAME
         Q=TSEXP(JJJ)
         %IF Q=1 %AND JJJ=0 %START;     ! CLEAR A RECORD TO ZERO
            P=P1; CNAME(3,DR)
            %IF ACC<=128 %THEN JJ=0 %AND KK=ACC-1 %ELSE %START
               JJ=1; KK=0
               %IF NAM#0 %THEN PSF1(LDB,0,ACC)
            %FINISH
            PF2(MVL,JJ,1,KK,0,0)
         %FINISH %ELSE %START
            ->BACK %UNLESS TYPE=3 %AND A(P2+3)=4 %AND A(P2+4)=1
            P=P2+5; CNAME(3,ACCR)
            ACCP=ACC
            ->F66 %UNLESS A(P)=2
            R_PTYPE=X'61'; R_FLAG=9
            R_XB=ACCR<<5; R_D=0
            OLINK(ACCR)=ADDR(R)
            REGISTER(ACCR)=1
            P=P1; CNAME(3,DR)
            REGISTER(ACCR)=0
            %IF R_FLAG#9 %THEN PF1(LSD,0,TOS,0)
            ->F66 %IF ASSOP=2 %AND ACCP#ACC
            %IF ACCP>ACC %THEN ACCP=ACC
            %UNTIL ACCP=0 %CYCLE
               %IF ACCP>128 %THEN KK=128 %ELSE KK=ACCP
               PF2(MV,0,0,KK-1,0,0)
               ACCP=ACCP-KK
            %REPEAT
            GRUSE(ACCR)=0
         %FINISH
         P=P2; SKIP EXP
         GRUSE(DR)=0
         %RETURN
SW(0):                                 ! RESOLUTION
         P=P1; CNAME(2,DR)
         P=P2; CRES(0); %RETURN
SW(1):                                 ! '==' AND %NAME PARAMETERS
         ->F2 %UNLESS A(P2+3)=4 %AND A(P2+4)=1
         Q=82 %AND ->F00 %UNLESS NAM=1; ! ONLY POINTERS ON LHS OF==
         P=P2+5; ->ARRNAME %IF ARR=1
         CNAME(3,ACCR);                 ! DESCRPTR TO ACC
         R_PTYPE=X'61'; R_FLAG=9
         R_XB=ACCR
         OLINK(ACCR)=ADDR(R)
         REGISTER(ACCR)=1
         ->F2 %UNLESS A(P)=2;           ! NO REST OF EXP ON LHS
         Q=P+1; P=P1
         Q=83 %AND ->F00 %UNLESS TYPE=TYPEP %AND PREC=PRECP
         CNAME(6,0)
         %IF R_FLAG#9 %THEN PF1(LSD,0,TOS,0) %AND GRUSE(ACCR)=0
         REGISTER(ACCR)=0
COM:     PSORLF1(ST,ACCESS,AREA CODE,DISP)
         NOTE ASSMENT(ACCR,1,A(P1)<<8!A(P1+1))
         P=Q; %RETURN
ARRNAME: CNAME(12,ACCR)
         %IF ACCESS>=8 %THEN ACCESS=ACCESS-4 %ELSE ACCESS=0
         Q=83 %AND ->F00 %UNLESS TYPE=TYPEP %AND PREC=PRECP %C
            %AND ARR>0 %AND OLDI<=LVL
         TYPE=0
         NAMEOP(2,ACCR,16,-1)
         R_PTYPE=X'72'; R_UPTYPE=0
         R_FLAG=9; R_XB=ACCR
         R_D=-1
         REGISTER(ACCR)=1
         OLINK(ACCR)=ADDR(R)
         ->F2 %UNLESS A(P)=2
         Q=P+1; P=P1
         CNAME(6,0)
         PF1(LSQ,0,TOS,0) %UNLESS R_FLAG=9
         REGISTER(ACCR)=0
         ->COM
F66:     Q=66; ->F00
F2:      Q=81;                         ! RHS AN EXPRSSN
F00:
         REGISTER(ACCR)=0
         %IF Q=82 %THEN JJ=FROM AR2(P1) %ELSE JJ=0
         FAULT(Q,JJ)
         P=P2; SKIP EXP
         %END
         %ROUTINE     CSEXP(%INTEGER REG,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,PP,BDISP,EXPBOT
         EXPHEAD=0; EXPBOT=0
         NOPS=0
         P=P+3
         TORP(EXPHEAD,EXPBOT,NOPS)
         %IF EXPHEAD=0 %THEN NEST=0 %AND %RETURN;! EXPR  CONSTANT ONLY
!
         BDISP=ADISP
         PP=P
         EXPOP(EXPHEAD,REG,NOPS,MODE)
         P=PP
         ADISP=BDISP
!         CLEAR LIST(EXPHEAD)
         ASLIST(EXPBOT)_LINK=ASL
         ASL=EXPHEAD
         %END
         %ROUTINE TORP(%INTEGERNAME HEAD,BOT,NOPS)
!***********************************************************************
!*       CONVERT THE SIGNED EXPRESSION INDEXED BY P INTO REVERSE       *
!*      POLISH NOTATION. THE REVERSE POLISH LIST IS ADDED TO 'HEAD'    *
!*      WHICH MAY CONTAIN ANOTHER EXPRESSION. THE NUMBER OF OPERATORS  *
!*      IS ADDED TO NOPS.                                              *
!*      N.B. AN INTEGER EXPRESSION IS A SPECIAL CASE OF A REAL EXPRSN  *
!***********************************************************************
%SWITCH OPERAND(1:3)
%CONSTBYTEINTEGERARRAY PRECEDENCE(1:15)=3,3,4,5,5,4,3,3,4,4,5,5,3,5,5;
%CONSTBYTEINTEGERARRAY OPVAL(1:15)=20,21,27,37,30,24,22,23,25,26,
                                   28,29,20,37,30;
%INTEGER RPHEAD,PASSHEAD,SAVEHEAD,REAL,REALOP,COMPLEX,%C
         OPERATOR,OPPREC,OPND,C,D,E,RPTYPE,RPINF,BDISP,%C
         OPNAME,OPMASK,XTRA,RPBOT,OPSTK,OPPSTK,PASSBOT
%RECORDNAME LCELL(LISTF)
!
         PASSHEAD=0; RPHEAD=0; SAVEHEAD=0
         REAL=0; REALOP=0; BDISP=0
         RPBOT=0; OPSTK=0; OPPSTK=0
!
         C=A(P)
         %IF 2<=C<=3 %THEN %START;     ! INITIAL '-' OR '\'
            NOPS=NOPS+1
                                       ! '-' =(11,3)   '\' =(10,5)
            OPSTK=4-C
            OPPSTK=C<<1-1
            OPMASK=1<<(19+C);          ! - %OR !!
         %FINISH %ELSE OPMASK=0
NEXTOPND:OPND=A(P+1); P=P+2
         COMPLEX=0; XTRA=0
         -> OPERAND(OPND);             ! SWITCH ON OPERAND
OPERAND(1):                            ! NAME
         OPNAME=A(P)<<8+A(P+1)
         LCELL==ASLIST(TAGS(OPNAME))
         PTYPE=LCELL_S1>>16
         %IF PTYPE=0 %THEN PTYPE=7;     ! NAME NOT SET
         TYPE=PTYPE&7; PREC=PTYPE>>4&15
         %IF PTYPE=SNPT %THEN %START
            K=LCELL_S3>>16
             %IF K=38 %AND A(P+2)=2 %THEN %START;    ! PICK OFF NL
                RPTYPE=0; RPINF=10; PTYPE=X'51'; P=P+2; ->SKNAM
             %FINISH
            %IF K=52 %AND A(P+2)=2 %START;! PICK OFF PI
               RPTYPE=1; PTYPE=X'62'; RPINF=X'413243F6'
               XTRA=X'A8885A31'
               P=P+2; REAL=1; ->SKNAM
            %FINISH
            COMPLEX=1
             PTYPE=TSNAME(K); UNPACK
         %FINISH
         %IF PTYPE&X'FF00'=X'4000' %AND A(P+2)=2 %C
            %AND 1<=TYPE<=2 %THEN %START; ! CONST VAR
            LCELL_S1=LCELL_S1!X'8000';  ! SET USED BIT
            RPINF=LCELL_S2; XTRA=LCELL_S3
            RPTYPE=1; PTYPE=PTYPE&255
            %IF TYPE=1 %AND PREC<=5 %AND X'FFFE0000'<=RPINF<=X'1FFFF'%C
               %THEN RPTYPE=0
            %IF PREC=7 %THEN RPTYPE=3
            REAL=1 %IF TYPE=2
            P=P+2; ->SKNAM
         %FINISH
         XTRA=OPNAME
         %IF PTYPE&X'3F00'#0 %OR PARMCHK=1 %OR PREC<5 %C
            %THEN COMPLEX=1
         OPMASK=OPMASK!(COMPLEX<<19)
         %IF TYPE=3 %THEN %START
            D=P; KFORM=LCELL_S3&X'FFFF'
            C=COPY RECORD TAG(E); P=D;
            COMPLEX=1 %UNLESS E=1 %AND 1<=TYPE<=2 %AND NAM=ARR=0 %C
               %AND PREC#3
         %FINISH
         %IF TYPE=5 %THEN FAULT(42,OPNAME)
         %IF TYPE=2 %THEN REAL=1
         RPTYPE=2; RPINF=P; PTYPE=1 %IF PTYPE=7
         RPTYPE=0 %AND PTYPE=1 %IF TYPE=5;   ! CHANGE TO SHORT CONST
         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:     BINSERT(RPHEAD,RPBOT,PTYPE<<16!COMPLEX<<8!RPTYPE,RPINF,XTRA)
         -> OP
OPERAND(2):                            ! CONSTANT
         PTYPE=A(P); D=PTYPE>>4
         C=PTYPE&7; RPINF=FROM AR4(P+1)
         REAL=1 %IF C=2; RPTYPE=1
         %IF D=6 %THEN XTRA=FROM AR4(P+5)
         %IF C=5 %THEN %START;      ! STRING CONSTANT
            FAULT(42,0); RPINF=1; RPTYPE=0
            P=P+A(P+5)+7
         %FINISH %ELSE %START
            %IF D=7 %THEN XTRA=ADDR(A(P+1)) %AND RPTYPE=3
            %IF PTYPE=X'51' %AND RPINF>>17=0 %THEN RPTYPE=0
            P=P+2+BYTES(D)
         %FINISH; -> INS
OPERAND(3):                            ! SUB EXPRESSION
         PASSHEAD=0; PASSBOT=0
         P=P+3
         TORP(PASSHEAD,PASSBOT,NOPS)
         REAL=1 %IF TYPE=2
!         CONCAT(RPHEAD,PASSHEAD)
         %IF RPBOT=0 %THEN RPHEAD=PASSHEAD %ELSE %C
            ASLIST(RPBOT)_LINK=PASSHEAD
         RPBOT=PASSBOT
         P=P+1
OP:                                     ! DEAL WITH OPERATOR
         -> EOE %IF A(P-1)=2;           ! EXPR FINISHED
         OPERATOR=A(P)
!
! THE STRING OPERATOR '.' CAUSES CHAOS IN AN ARITHMETIC EXPRSN
! SO FAULT IT AND CHANGE IT TO THE INNOCUOUS '+'
!
         %IF OPERATOR=CONCOP %THEN FAULT(42,0)
         OPPREC=PRECEDENCE(OPERATOR)
         OPERATOR=OPVAL(OPERATOR)
         %IF OPERATOR=26 %OR OPERATOR=30 %THEN REAL=1
         OPMASK=OPMASK!(1<<OPERATOR)
         NOPS=NOPS+1
!
! UNLOAD THE OPERATOR STACK OF ALL OPERATORS WHOSE PRECEDENCE IS
! NOT LOWER THAN THE CURRENT OPERATOR. AN EMPTY STACK GIVES'-1'
! AS PRECEDENCE.
!
         %WHILE OPPREC<=OPPSTK&31 %CYCLE
            BINSERT(RPHEAD,RPBOT,OPSTK&31+9,0,0)
            OPSTK=OPSTK>>5; OPPSTK=OPPSTK>>5
         %REPEAT
!
! THE CURRENT OPERATOR CAN NOW BE STORED
!
         OPSTK=OPSTK<<5!(OPERATOR-9)
         OPPSTK=OPPSTK<<5!OPPREC
         -> NEXTOPND
EOE:                                   ! END OF EXPRESSION
                                       ! EMPTY REMAINING OPERATORS
         %WHILE OPSTK#0 %CYCLE
            BINSERT(RPHEAD,RPBOT,OPSTK&31+9,0,0)
            OPSTK=OPSTK>>5
         %REPEAT
         PTYPE=REAL+1
         TYPE=PTYPE
!         CONCAT(RPHEAD,HEAD)
         %IF HEAD=0 %THEN BOT=RPBOT %ELSE %C
            ASLIST(RPBOT)_LINK=HEAD
         HEAD=RPHEAD;                ! HEAD BACK TO TOP OF LIST
         NOPS=NOPS!OPMASK
         %END
         %ROUTINE EXPOP(%INTEGER INHEAD,REG,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                                       *
!*                                                                     *
!*    ARRAY MCINST HOLD THE OPCODES CORRESPONDING TO THE OPERATORS:-   *
!*       TOP BYTE = REAL FORWARD FORM                                  *
!*       2ND BYTE = REAL REVERSE FORM                                  *
!*       3RD BYTE = INTEGER FORWARD FORM                               *
!*       BTM BYTE = INTEGER REVERSE FORM                               *
!*       MODE HAS TYPE & PREC REQD +256 BIT IF NO RESULT REQD          *
!***********************************************************************
%ROUTINESPEC CTOP(%INTEGERNAME A)
%ROUTINESPEC CHOOSE(%INTEGERNAME I)
%ROUTINESPEC PUT
%ROUTINESPEC STARSTAR
%ROUTINESPEC REXP
%ROUTINESPEC LOAD(%RECORDNAME OP,%INTEGER REG,MODE)
%ROUTINESPEC FLOAT(%RECORDNAME OPND,%INTEGER OTHERPTYPE)
%ROUTINESPEC COERCET(%RECORDNAME OP1,OP2,%INTEGER MODE)
%ROUTINESPEC COERCEP(%RECORDNAME OP1,OP2)
%ROUTINESPEC LENGTHEN(%RECORDNAME OP)
%ROUTINESPEC SHORTEN (%RECORDNAME OP)
!
%INTEGERARRAY OPERAND(1:2),STK(0:99)
%RECORDNAME LIST(LISTF)
%RECORDNAME OPND1,OPND2,OPND (RD)
!
%INTEGER C,D,KK,JJ,OPCODE,COMM,XTRA,NEWCC,PP,PT,JJJ,LOADREG,EVALREG,%C
         STPTR,RDFORM
%CONSTINTEGERARRAY MCINST(10:37)=X'8E8E',X'F4F4E4E4',X'A8A8',
                                 X'F4F4E4E4',0(6),
                                 X'F0F0E0E0',X'F2F4E2E4',
                                 X'8E8E',X'8C8C',X'FAFAEAEA',
                                 X'AAAC',X'BABC0000',
                                 X'8A8A',X'C800'(2),X'FA000000',
                                 X'F6F6E6E6',X'00F600E6',
                                 X'2C002C00',X'02000200',
                                 X'48004800'(2),X'EA00';
%CONSTBYTEINTEGERARRAY CORULES(20:37)=X'1F'(2),X'11'(2),X'1F',X'11',
                                       X'12',X'11',1,1,0,X'1F'(2),
                                      0(4),1;
%CONSTBYTEINTEGERARRAY FCOMP(1:28)=%C
                                        8,10,2,7,12,4,7,
                                        8,12,4,7,10,2,7,
                                        16,34,17,32,33,18,32,
                                        16,33,18,32,34,17,32;
%SWITCH SW(10:37)
!
         STPTR=0; RDFORM= MODE&256
         NEWCC=0
         EVALREG=ACCR;                  ! EVALUATE IN ACC UNLESS
         %IF REG=BREG %AND NOPS&X'7EC00000'=0 %C
            %THEN EVALREG=BREG;         ! ONLY '+' %AND '*' PRESENT
!         %IF REG<0 %AND NOPS&X'7EC400FF'<=2 %AND MODE&255=X'51' %C
           %AND REGISTER(BREG)=0 %AND GRUSE(BREG)<3 %AND GRUSE(ACCR)>3%C
            %THEN EVALREG=BREG
NEXT:    LIST==ASLIST(INHEAD)
         C=LIST_S1; XTRA=LIST_S2
         JJ=C&255; D=INHEAD
         INHEAD=LIST_LINK
         -> OPERATOR %IF JJ>=10
!
! ANY OPERAND WHICH MAY NEED DR OR B OR ACC IN THEIR EVALUATION
! EG FUNCTIONS,ARRAY ELEMENTS ETC ARE FETCHED AND STACKKED FIRST
!
         OPERAND(1)=ADDR(ASLIST(D))
         OPND1==ASLIST(D)
         %IF OPND1_FLAG=2 %AND OPND1_XB#0 %THEN LOAD(OPND1,EVALREG,0)
         STK(STPTR)=OPERAND(1)
         STPTR=STPTR+1
         ABORT %IF STPTR>99
ANYMORE:
         ->NEXT %UNLESS INHEAD=0 %OR MODE=100
         -> FINISH
OPERATOR:
         %IF JJ<19 %THEN KK=1 %ELSE KK=2; ! UNARY OR BINARY
         %CYCLE KK=KK,-1,1
            STPTR=STPTR-1
            C=STK(STPTR)
            OPERAND(KK)=C
         %REPEAT
         OPCODE=MCINST(JJ)
         COMM=1
         OPND1 == RECORD(OPERAND(1))
         OPND2 == OPND1
         %IF JJ>=19 %THEN %START
            OPND2==RECORD(OPERAND(2))
            C=CORULES(JJ)
            %IF C&15#0 %THEN COERCET(OPND1,OPND2,C&15)
            %IF C>>4#0 %THEN COERCEP(OPND1,OPND2)
         %FINISH
         %IF JJ>19 %START
            CHOOSE(COMM)
            OPND1==RECORD(OPERAND(COMM))
            OPND2==RECORD(OPERAND(3-COMM))
         %FINISH
         PTYPE=OPND1_PTYPE; TYPE=PTYPE&7
         %IF TYPE=1 %THEN OPCODE=OPCODE&X'FFFF' %C
                    %ELSE OPCODE=OPCODE>>16;! INTEGER OR REAL FORMS
         %IF OPND1_FLAG<2 %AND OPND2_FLAG<2 %THEN CTOP(JJ)
         -> STRES %IF JJ=0;            ! CTOP CARRIED OUT
         -> SW(JJ)
SW(10):                                !  \
         LOAD(OPND1,EVALREG,2)
         FAULT(24,0) %UNLESS TYPE=1
         PSF1(OPCODE&255,0,-1);         ! NEQ -1
         GRUSE(EVALREG)=0
SUSE:    OLINK(EVALREG)=OPERAND(COMM)
STRES:   STK(STPTR)=OPERAND(COMM)
         STPTR=STPTR+1
         ->ANYMORE
SW(11):                                ! NEGATE
         LOAD(OPND1,EVALREG,2)
         %IF EVALREG=BREG %THEN PSF1(SLB,0,0) %AND PF1(SBB,0,TOS,0) %C
            %ELSE PSF1(OPCODE&255,0,0); ! IRSB 0 OR RRSB 0
         GRUSE(EVALREG)=0
         -> SUSE
SW(12):                                ! FLOAT
         ABORT
SW(13):                                 ! ABS
         LOAD(OPND1,EVALREG,2);             ! OPERAND TO ACC
         %IF TYPE=2 %THEN C=2 %ELSE C=6
         PF3(JAF,C,0,3);                ! JAF *+3 ON ACC<0
         PSF1(OPCODE&255,0,0);          ! IRSB 0 OR RRSB 0
         GRUSE(EVALREG)=0
         ->SUSE
SW(14):                                 ! STRETCH
         ABORT
SW(20):                                 ! ADD
         %IF TYPE=1 %AND GRUSE(EVALREG)=10 %AND OPND1_FLAG=2 %C
            %AND OPND2_FLAG=0 %AND REGISTER(EVALREG)=0 %START
            P=OPND1_D; D=GRINF(EVALREG)
            %IF FROMAR2(P)=D&X'FFFF' %AND A(P+2)=2=A(P+3) %START
               %IF EVALREG=ACCR %THEN C=IAD %ELSE C=ADB
               PSF1(C,0,OPND2_D-D>>16)
               GRINF(EVALREG)=D&X'FFFF'!OPND2_D<<16
               REGISTER(EVALREG)=1
               OPND1_FLAG=9; OPND1_XB=EVALREG<<4
               OPND1_D=0; ->SUSE
            %FINISH
         %FINISH
BINOP:   LOAD(OPND1,EVALREG,2);
         LOAD(OPND2,EVALREG,1)
         PUT; -> SUSE
SW(21):                                 ! SUBTRACT
         ->BINOP
SW(22):                                 ! EXCLUSIVE OR
SW(23):                                 ! OR
SW(27):                                 ! AND
         ->BINOP %IF TYPE=1
F24:     FAULT(24,0) %UNLESS TYPE=7
         JJ=20; OPCODE=MCINST(20)
         ->BINOP;                       ! CHANGE OPN TO +
SW(28):                                 ! SRL
         %IF OPND2_FLAG=0 %THEN OPND2_D=-OPND2_D %ELSE %START
            LOAD(OPND2,EVALREG,2);          ! OPND TO ACC
            PSF1(IRSB,0,0);             ! AND NEGATE IT
            GRUSE(EVALREG)=0
         %FINISH
SW(29):                                 ! SLL
         ->F24 %IF OPND2_PTYPE>>4>=6;! NO SHIFT BY LONG INT
         -> BINOP
SW(24):                                ! MULT
         -> BINOP
SW(25):                                 ! INTEGER DIVISION
         ->F24 %UNLESS TYPE=1
         -> BINOP
SW(26):                                 ! NORMAL DIVISION
         -> BINOP
SW(30):                                 ! EXP IN REAL EXPRSN
         %IF OPND1_PTYPE&7=1 %THEN FLOAT(OPND1,0)
         %IF OPND2_PTYPE&7=1 %THEN STARSTAR %AND ->SUSE
                                        ! REAL**REAL BY SUBROUTINE
         REXP; COMM=2; ->SUSE
SW(37):                                 ! EXP IN INTEGER CONTEXT
         STARSTAR; -> SUSE
SW(31):                                 ! COMPARISONS
SW(32):                                 ! DSIDED COMPARISONS 
         PTYPE=OPND1_PTYPE
         ->Z1 %IF OPND1_FLAG<=1 %AND 0=OPND1_D %AND JJ=31 %AND %C
            (OPND1_XTRA=0 %OR PTYPE>>4=5)
         -> Z2 %IF OPND2_FLAG<=1 %AND 0=OPND2_D %AND %C
            (OPND2_XTRA=0 %OR OPND2_PTYPE>>4=5)
         LOAD(OPND1,EVALREG,2)
         LOAD(OPND2,EVALREG,1)
         PUT
         REGISTER(EVALREG)=0
         BFFLAG=COMM-1;                ! NOTE BACKWARDS OR FORWARDS
         MASK=FCOMP(XTRA+7*BFFLAG)
         COMM=2; ->STRES;              ! 2ND OPERAND MAY BE NEEDED IN
                                       ! DOUBLE SIDED AND IS THEREFORE
                                       ! TAKEN AS THE 'RESULT'
Z1:      COMM=3-COMM
Z2:      OPND==RECORD(OPERAND(COMM))
         C=EVALREG; D=EVALREG!!7
         %IF OPND_FLAG=2 %AND GRUSE(D)=9 %AND %C
            (GRINF(D)&X'FFFF'=OPND_XTRA %OR GRINF(D)>>16=OPND_XTRA) %C
            %THEN C=D
         LOAD(OPND,C,2)
         REGISTER(C)=0
         MASK=FCOMP(XTRA+7*COMM+7)
         %IF TYPE=1 %THEN MASK=MASK+4
         %IF C=BREG %THEN MASK=MASK+8
         COMM=2; ->STRES
SW(33):                                 ! SPECIAL MH FOR ARRAY ACCESS
         C=OPND2_D>>16;                 ! CURRENT DIMENSION
         D=OPND2_D&31;                  ! TOTAL NO OF DIMENSIONS
         %IF OPND1_FLAG=9 %AND OPND1_XB>>4=ACCR %THEN %START
            PF1(ST,0,TOS,0);            ! ACC CANNOT BE USED IN DVM
            CHANGE RD(ACCR)
            REGISTER(ACCR)=0
         %FINISH
!
         %IF C=D %THEN %START;          ! TOP DIMENSION LOAD DV DES
            BASE=OPND2_XTRA>>18; AREA=-1
            GET IN ACC(DR,2,0,AREA CODE,OPND2_XTRA&X'1FFFF'+8)
         %FINISH
!
         LOAD(OPND1,EVALREG,0)
         %IF OPND1_PTYPE>>4>=6 %THEN FAULT(24,0)
         %IF C=D %AND REGISTER(BREG)>=1 %AND %C
            (OPND1_FLAG#9 %OR OPND1_XB>>4#BREG) %THEN %START
            OPND==RECORD(OLINK(BREG))
            OPND_D=0
            REGISTER(BREG)=2
            BOOT OUT(BREG)
         %FINISH
         AREA=OPND1_XB>>4; ACCESS=OPND1_XB&15
         PSORLF1(OPCODE>>8,ACCESS,AREA,OPND1_D)
         GRUSE(BREG)=0
!
         %IF C=1=D %THEN LOADREG=BREG %ELSE %START
            LOADREG=ACCR
            %IF C=D %THEN GET IN ACC(ACCR,1,0,7,0) %ELSE %C
                    PF1(IAD,0,BREG,0) %AND GRUSE(BREG)=0
            %IF C=1 %THEN %START
               PF1(ST,0,BREG,0)
               GRUSE(BREG)=0
               REGISTER(ACCR)=0
               LOADREG=BREG
            %FINISH
         %FINISH
         REGISTER(LOADREG)=1
         OPND1_FLAG=9; OPND1_XB=LOADREG<<4
         OLINK(LOADREG)=OPERAND(COMM)
         %IF C=1 %THEN ->STRES
         ->ANYMORE
SW(34):                                   ! ->LAB MASKS AND LAB AS OPND2
                                          ! OPND1 MIDDLE OF D-SIDED
         LOAD(OPND1,EVALREG,2) %IF INHEAD#0;  ! PROTECT MIDDLE OPND IN DSIDED
         %IF XTRA=1 %THEN MASK=REVERSE(MASK)
         ENTER JUMP(MASK,OPND2_D,B'11')
         ->STRES;                         ! RETURN MIDDLE OPND AS RESULT
SW(35):                                   ! ASSIGN(=)
SW(36):                                 ! ASSIGN(<-)
         PT=OPND2_PTYPE; PP=OPND2_D
         %IF PT&7=1 %AND OPND1_PTYPE&7=2 %THEN  FAULT(24,0)
         %IF PT&7=2 %AND OPND1_PTYPE&7=1 %THEN FLOAT(OPND1,OPND2_PTYPE)
         LOAD(OPND1,EVALREG,2);             ! RHS TO ACC
         REGISTER(EVALREG)=2
         C=PT>>4; D=OPND1_PTYPE>>4
         %IF C<5 %THEN C=5
         %IF D<5 %THEN D=5
         %WHILE D<C %THEN LENGTHEN(OPND1) %AND D=OPND1_PTYPE>>4
         %WHILE (C<D %AND TYPE=1 %AND JJ#36) %OR C<D-1 %THEN %C
            SHORTEN(OPND1) %AND D=OPND1_PTYPE>>4
         P=PP; CNAME(1,0);              ! STORE CALL
         D=DISP; C=ACCESS; JJJ=AREA;    ! SAVE INFO FOR STORE
         KK=PREC
         LOAD(OPND1,EVALREG,2);             ! IN CASE STACKED
         %IF JJ=36 %AND TYPE=1 %START
            %IF 3<=XTRA<=4 %THEN PF1(AND,0,0,(-1)>>(8*(6-XTRA)))%C
                %AND GRUSE(ACCR)=0
            %IF KK<=5 %AND PREC=6 %THEN %C
               PSF1(MPSR,0,17) %AND GRUSE(ACCR)=0
         %FINISH
         %IF TYPE=2 %AND KK<PREC %THEN KK=STUH %ELSE KK=ST
         %IF EVALREG=BREG %THEN KK=STB
         PSORLF1(KK,C,JJJ,D)
         %IF A(PP+2)=2=A(PP+3) %THEN NOTE ASSMENT(EVALREG,JJ-33,STNAME)
         %IF C>=2 %START
            %IF STNAME>=0 %THEN GRUSE(DR)=7 %AND GRINF(DR)=STNAME %C
                          %ELSE GRUSE(DR)=0
         %FINISH
         %IF KK=STUH %THEN GRUSE(ACCR)=0
         COMM=1; ->STRES
FINISH:  C=STK(STPTR-1)
         OPERAND(1)=C
         OPND1==RECORD(C)
         %IF OPND1_PTYPE>>4&15<5 %THEN %C
            OPND1_PTYPE=OPND1_PTYPE&X'F'!X'50';! BITS&BYTES->INTEGERS
         %IF RDFORM =0 %START
            D=MODE>>4&7; D=5 %IF D<5
            %IF MODE&7=2 %AND OPND1_PTYPE&7=1 %THEN FLOAT(OPND1,D<<4)
            %WHILE D<OPND1_PTYPE>>4 %THEN SHORTEN(OPND1)
            %WHILE D>OPND1_PTYPE>>4 %THEN LENGTHEN(OPND1)
            LOAD(OPND1,REG,2)
         %FINISH
         PTYPE=OPND1_PTYPE
         TYPE=PTYPE&7; PREC=PTYPE>>4
         %IF TYPE=2 %AND MODE&7=1 %THEN FAULT(24,0)
         NEST=-1
         %IF OPND1_FLAG=9 %THEN %START
            NEST=OPND1_XB>>4
            REGISTER(NEST)=0
         %FINISH
         %RETURN
!
%ROUTINE CHOOSE(%INTEGERNAME CHOICE)
%RECORDNAME OPND1,OPND2(RD)
         OPND1==RECORD(OPERAND(1))
         OPND2==RECORD(OPERAND(2))
         CHOICE=1
         %RETURN %IF JJ=21 %AND EVALREG=BREG;! NO REVERSE SUBTRACT B
         CHOICE=2 %IF OPCODE&X'FF00FF00'=0 %OR %C
            (OPCODE&X'FF00FF'#0 %AND (OPND2_FLAG=9 %C
            %OR(OPND2_FLAG=2 %AND GRUSE(EVALREG)=9 %AND %C
            GRINF(EVALREG)=OPND2_XTRA>0)))
         %END
%ROUTINE LOAD(%RECORDNAME OPND,%INTEGER REG,MODE)
!***********************************************************************
!*       LOAD OPERAND OPND AS DIRECTED BY MODE TO REGISTER REG         *
!*       MODE=0   LEAVE IN STORE IF POSSIBLE                           *
!*       MODE=1 LEAVE IN STORE IF SUITABLE FOR RX INSTRUCTIONS         *
!*       MODE=2 LOAD TO REGISTER REGARDLESS                            *
!***********************************************************************
%INTEGER K,KK
%RECORDSPEC OPND(RD)
%SWITCH SW(0:9)
         K=OPND_FLAG
        %RETURN %UNLESS MODE=2 %OR K=2 %OR(K<=3 %AND MODE=1)
         PTYPE=OPND_PTYPE
         TYPE=PTYPE&15
         PREC=PTYPE>>4
         %IF K<0 %OR K>9 %THEN ABORT
         ->SW(K)
SW(0):LITCONST:                        ! CONSTANT < 18 BITS
         AREA=0; ACCESS=0
         DISP=OPND_D
         %IF MODE=2 %THEN %START;       ! FETCH TO REG
            %IF GRUSE(REG)=5 %AND GRINF(REG)=DISP %AND PREC=5 %START
               %IF REGISTER(REG)#0 %THEN BOOT OUT(REG)
            %FINISHELSE GET IN ACC(REG,BYTES(PREC)>>2,ACCESS,AREA,DISP)
            %IF PREC<=5 %THEN GRUSE(REG)=5 %AND GRINF(REG)=DISP
            ->LDED
         %FINISH
         %IF PREC=3 %THEN OPND_PTYPE=X'51';  ! CONSTBYTEINTEGERS AGAIN
         OPND_FLAG=7; OPND_XB=AREA<<4!ACCESS
         OPND_D=DISP
         %RETURN
SW(1):                                  ! LONG CONSTANT
         %IF OPND_D=0=OPND_XTRA %AND PREC<=6 %THEN ->LITCONST
SW(3):                                  ! 128 BIT CONSTANT
         %IF PREC=7 %THEN KK=OPND_XTRA %ELSE KK=ADDR(OPND_D)
         STORE CONST(DISP,BYTES(PREC),KK)
         %IF MODE#2 %THEN %START
            OPND_FLAG=7; OPND_XB=PC<<4
            OPND_D=DISP; %RETURN
         %FINISH
         %IF GRUSE(REG)=6 %AND GRINF(REG)=DISP %THEN %START
            %IF REGISTER(REG)#0 %THEN BOOT OUT (REG)
         %FINISH %ELSE GET IN ACC(REG,BYTES(PREC)>>2,0,PC,DISP)
         GRUSE(REG)=6; GRINF(REG)=DISP
         ->LDED
SW(2):                                  ! NAME
         P=OPND_D
         -> LOAD %IF MODE=2 %OR OPND_XB#0;! COMPLEX NAMES MUST BE LOADED
         CNAME(5,REG)
         ->LDED %IF NEST>=0
         AREA=-1
         AREA=AREA CODE
         OPND_PTYPE<-PTYPE
         OPND_FLAG=7
         OPND_XB=AREA<<4!ACCESS
         OPND_D=DISP; %RETURN
LOAD:    CNAME(2,REG)
LDED:    REGISTER(REG)=1;          ! CLAIM THE REGISTER
         OLINK(REG)=ADDR(OPND)
         %IF PREC<5 %THEN OPND_PTYPE=OPND_PTYPE&15!X'50'
         OPND_FLAG=9; OPND_D=0; OPND_XB=REG<<4
         %IF REG=BREG %AND REGISTER(ACCR)&1#0 %THEN %C
            REGISTER(BREG)=2
         %RETURN
SW(4):                                  ! CONDITIONAL EXPRESSION
SW(5):                                  ! UNASSIGNED
SW(6):                                  ! UNASSIGNED
         ABORT
SW(7):                                  ! I-R IN A STACK FRAME
         AREA=OPND_XB>>4
         ACCESS=OPND_XB&15
         DISP=OPND_D
PICKUP:  GET IN ACC(REG,BYTES(PREC)>>2,ACCESS,AREA,DISP)
         ->LDED
SW(8):                                  ! I-R THAT HAS BEEN STACKED
         AREA=TOS; ACCESS=0; DISP=0; ->PICK UP
SW(9):                                  ! I-R IN A REGISTER
         %IF OPND_XB>>4=REG %THEN -> LDED
         %IF REG#ACCR %THEN PF1(ST,0,BREG,0) %ELSE %C
            GETINACC(ACCR,1,0,BREG,0)
         REGISTER(OPND_XB>>4)=0
         OPND_XB=REG<<4; GRUSE(REG)=0
         REGISTER(REG)=1; OLINK(REG)=ADDR(OPND)
         %END
%ROUTINE PUT
!***********************************************************************
!*       THIS ROUTINE PLANTS CODE TO PERFORM THE BASIC                 *
!*       OPERATION DEFINED BY OPND1,OPND2 & OPCODE                     *
!***********************************************************************
%INTEGER CODE,OCODE
         CODE=OPCODE
         %IF COMM=1 %THEN CODE=CODE>>8
         CODE=CODE&255; OCODE=CODE
         %IF EVALREG=BREG %THEN CODE=CODE-X'C0'
         ABORT %UNLESS OPND1_FLAG=9
         PSORLF1(CODE,OPND2_XB&15,OPND2_XB>>4,OPND2_D)
         %IF OCODE=IAD %AND GRUSE(EVALREG)=9 %AND OPND2_XB=0 %C
            %AND OPND2_D<4095 %THEN %START
            GRUSE(EVALREG)=10
            GRINF(EVALREG)=GRINF(EVALREG)&X'FFFF'!OPND2_D<<16
         %FINISH %ELSE %START
            GRUSE(EVALREG)=0 %UNLESS 31<=JJ<=32
         %FINISH
         OLINK(EVALREG)=OPERAND(COMM)
         %END
%ROUTINE FLOAT(%RECORDNAME OPND,%INTEGER OTHERPTYPE)
!***********************************************************************
!*       PLANT CODE TO CONERT OPERAND FROM FIXED TO FLOATING           *
!***********************************************************************
%RECORDSPEC OPND(RD)
         %IF OPND_FLAG<=1 %THEN %START
            CVALUE=OPND_D
            OPND_D=INTEGER(ADDR(CVALUE))
            OPND_XTRA=INTEGER(ADDR(CVALUE)+4)
            OPND_FLAG=1
         %FINISH %ELSE %START
            LOAD(OPND,ACCR,2)
            %IF OTHERPTYPE&X'F0'=X'70' %AND OPND_PTYPE&X'F0'<=X'50' %C
               %THEN PSF1(IMYD,0,1) %AND OPND_PTYPE=OPND_PTYPE&15!X'60'
            PSF1(FLT,0,0)
            GRUSE(ACCR)=0
         %FINISH
         OPND_PTYPE=OPND_PTYPE+X'11'
         TYPE=2
%END
%ROUTINE COERCET(%RECORDNAME OPND1,OPND2,%INTEGER MODE)
!***********************************************************************
!*         MODE=1 BOTH OPERANDS INTEGER ELSE ERROR                     *
!*         MODE=2 FORCE BOTH OPERAND TO BE OF TYPE REAL                *
!*         MODE=15  BOTH OPERANDS TO BE OF LAGEST TYPE                 *
!***********************************************************************
%RECORDSPEC OPND1(RD)
%RECORDSPEC OPND2(RD)
%INTEGER PT1,PT2
         PT1=OPND1_PTYPE&7
         PT2=OPND2_PTYPE&7
         %IF (MODE=1 %OR MODE=15) %AND PT1=1=PT2 %THEN %RETURN
         %IF MODE=1 %THEN FAULT(24,0) %AND %RETURN
         %IF PT1=1 %THEN FLOAT(OPND1,OPND2_PTYPE)
         %IF PT2=1 %THEN FLOAT(OPND2,OPND1_PTYPE)
%END
%ROUTINE COERCEP(%RECORDNAME OPND1,OPND2)
!***********************************************************************
!*       FORCE BOTH OPERAND TO THE SAME PRECISION BEFORE OPRNTN        *
!***********************************************************************
%RECORDSPEC OPND1(RD)
%RECORDSPEC OPND2(RD)
%INTEGER PREC1,PREC2
         PREC1=OPND1_PTYPE>>4
         PREC2=OPND2_PTYPE>>4
         %WHILE PREC1<PREC2 %CYCLE
            LENGTHEN(OPND1)
            PREC1=OPND1_PTYPE>>4
         %REPEAT
!
         %WHILE PREC2<PREC1 %CYCLE
            LENGTHEN(OPND2)
            PREC2=OPND2_PTYPE>>4
         %REPEAT
%END
%ROUTINE LENGTHEN(%RECORDNAME OPND)
!***********************************************************************
!*       INCREASE OPND PRECISION BY ONE SIZE AT COMPILE TIME IF POSS   *
!***********************************************************************
%RECORDSPEC OPND(RD)
%INTEGER TP,PR
         TP=OPND_PTYPE&7
         PR=OPND_PTYPE>>4
         %IF OPND_FLAG<=1 %AND PR<=5 %START;  ! LENGTHEN CONSTANT
            %IF TP=1 %AND OPND_FLAG=1 %START;! INTEGER CONSTANT
               OPND_XTRA=OPND_D
               %IF OPND_XTRA<0 %THEN OPND_D=-1 %ELSE OPND_D=0
            %FINISH %ELSE OPND_XTRA=0
         %FINISH %ELSE %START;          ! CODE PLANTING REQRD
            LOAD(OPND,ACCR,2)
           %IF TP=1 %THEN PSF1(IMYD,0,1) %ELSE %C
               PF1(RMYD,0,PC,SPECIAL CONSTS(1));!  REAL ONE=X'41000000'
            GRUSE(ACCR)=0
         %FINISH
         OPND_PTYPE=(PR+1)<<4+TP
%END
%ROUTINE SHORTEN(%RECORDNAME OPND)
!***********************************************************************
!*       PLANT CODE TO REDUCE ACC SIZE. NO COMPILETIME OPTION          *
!*       SINCE ONLY AN IDIOT WILL GIVE OVERLENGTH CONSTANTS.           *
!***********************************************************************
%RECORDSPEC OPND(RD)
%INTEGER TY,PR
         TY=OPND_PTYPE&7
         PR=OPND_PTYPE>>4
         LOAD(OPND,ACCR,2)
         %IF PR=7 %THEN %START;          ! SHORTEN QUAD
            PF1(RDDV,0,PC,SPECIAL CONSTS(1))
         %FINISH %ELSE %START
            %IF TYPE=1=PARMARR %THEN PSF1(ISH,0,32)
            PSF1(USH,0,-32) %IF PARMARR=1 %OR TYPE#1
            %IF REGISTER(BREG)=0 %THEN PF1(STUH,0,BREG,0) %AND %C
               GRUSE(BREG)=0 %ELSE PSF1(MPSR,0,17);! ACS TO 1 WORD
         %FINISH
         GRUSE(ACCR)=0
         OPND_PTYPE=(PR-1)<<4+TY
%END
%ROUTINE CTOP(%INTEGERNAME FLAG)
!***********************************************************************
!*       AN OPERATION HAS BEEN FOUND WHERE BOTH OPERANDS ARE CONSTANTS *
!*       THIS ROUTINE ATTEMPTS TO INTERPRET THIS OPERATION IF IT       *
!*       CAN BE DONE SAFELY                                            *
!*       ON EXIT FLAG=0 %IF OPERATION CARRIED OUT                      *
!***********************************************************************
%INTEGER K,VAL1,VAL2,TYPEP,PRECP,OP,TYPEPP
%LONGREAL RVAL1,RVAL2
%SWITCH ISW,RSW(10:30)
!         NEWCC=0;                       !COMPILE TIME OPS CAN NOT SET CC
         TYPEP=TYPE; PRECP=PTYPE>>4&15; OP=FLAG
         K=OPND2_PTYPE; TYPEPP=K&7; K=K>>4
         %IF TYPEP=2 %THEN %START;   ! BOTH OPERANDS ARE REAL
            INTEGER(ADDR(RVAL1))=OPND1_D
            INTEGER(ADDR(RVAL1)+4)=OPND1_XTRA
         %FINISH %ELSE %START
            VAL1=OPND1_D; RVAL1=VAL1 %IF TYPEPP=2
         %FINISH
         %IF TYPEPP=2 %THEN %START
            INTEGER(ADDR(RVAL2))=OPND2_D
            INTEGER(ADDR(RVAL2)+4)=OPND2_XTRA
         %FINISH %ELSE %START
            VAL2=OPND2_D
         %FINISH
         %IF TYPEP<TYPEPP %THEN TYPEP=TYPEPP
         %IF PRECP<K %THEN PRECP=K
         %RETURN %IF OP>30 %OR PRECP=7 %OR(PRECP=6 %AND TYPEP=1)
         %IF TYPEP=2 %THEN ->RSW(OP) %ELSE ->ISW(OP)
ISW(10):                                ! \
         VAL1=\VAL1
INTEND:  FLAG=0; OPND1_PTYPE=X'51'
         %IF X'FFFE0000'<=VAL1<=X'1FFFF' %THEN OPND1_FLAG=0 %ELSE %C
            OPND1_FLAG=1; OPND1_D=VAL1;
         %RETURN
ISW(11):                                ! INTEGER NEGATE
         VAL1=-VAL1; -> INT END
ISW(13):                                ! INTEGER ABS
         VAL1=IMOD(VAL1); -> INT END
ISW(12):                                ! INTEGER FLOAT
         RVAL1=VAL1; PRECP=5+XTRA
         ->REAL END
RSW(14):                                ! STRETCH REAL
         PRECP=6
REAL END:OPND1_FLAG=1
         OPND1_D=INTEGER(ADDR(RVAL1))
         OPND1_XTRA=INTEGER(ADDR(RVAL1)+4)
         FLAG=0; OPND1_PTYPE=16*PRECP+2
         %RETURN
ISW(14):                                ! STRETCH INTEGER
RSW(12):                                ! FLOAT REAL
         ABORT
ISW(20):                                ! ADD
         VAL1=VAL1+VAL2; -> INT END
ISW(21):                                ! MINUS
         VAL1=VAL1-VAL2; -> INT END
ISW(22):                                ! EXCLUSIVE OR
         VAL1=VAL1!!VAL2; -> INT END
ISW(23):                                ! OR
         VAL1=VAL1!VAL2; -> INT END
ISW(24):                                ! MULT
         VAL1=VAL1*VAL2; -> INT END
ISW(26): %RETURN;                       ! / DIVISION
ISW(25): %RETURN %IF VAL2=0;            ! // DIVISION
         VAL1=VAL1//VAL2; -> INT END
ISW(27):                                ! AND
         VAL1=VAL1&VAL2; -> INT END
ISW(29):                                ! SLL
         VAL1=VAL1<<VAL2; -> INT END
ISW(28):                                ! SRL
         VAL1=VAL1>>VAL2; -> INT END
RSW(11):                                ! NEGATE
         RVAL1=-RVAL1; -> REAL END
RSW(13):                                ! ABS
         RVAL1=MOD(RVAL1); -> REAL END
RSW(20):                                ! ADD
         RVAL1=RVAL1+RVAL2; -> REAL END
RSW(21):                                ! SUBTRACT
         RVAL1=RVAL1-RVAL2; -> REAL END
RSW(24):                                ! MULT
         RVAL1=RVAL1*RVAL2; -> REAL END
RSW(26):                                ! DIVISION
         %RETURN %IF RVAL2=0;           ! AVOID DIV BY ZERO
         RVAL1=RVAL1/RVAL2; -> REAL END
ISW(30):                               ! '**' WITH 2 INTEGER OPERANDS
         RVAL1=VAL1
RSW(30):                                ! EXP
         %IF OPND2_FLAG#0 %THEN  %RETURN
         RVAL1=RVAL1**OPND2_D; -> REAL END
RSW(22):RSW(23):
RSW(25):RSW(27):RSW(28):RSW(29):
         %END
%ROUTINE REXP
!***********************************************************************
!*       CALLS A PERM ROUTINE TO PERFORM REAL**REAL                    *
!***********************************************************************
%INTEGER I,PR
%RECORDNAME OPND(RD)
         %IF REGISTER(BREG)>0 %THEN BOOT OUT(BREG)
         %CYCLE I=1,1,2
            OPND==RECORD(OPERAND(I))
            LOAD(OPND,ACCR,2) %UNLESS I=1 %AND OPND_FLAG=8
            PR=OPND_PTYPE>>4
            %IF PR<6 %THEN LENGTHEN(OPND)
            %IF PR>6 %THEN SHORTEN(OPND)
         %REPEAT
         PPJ(0,17)
%END
%ROUTINE STARSTAR
!***********************************************************************
!*       PLANT IN-LINE CODE FOR EXPONENTIATION                         *
!*       IMP ALLOWS EXPONENTS IN INTEGER EXPRESSIONS FROM 0-63 AND     *
!*       IN REAL EXPRESSIONS FROM-255 TO +255                          *
!***********************************************************************
%INTEGER TYPEP,PRECP,WORK,C,EXPWORK,VALUE
         PTYPE=OPND1_PTYPE;            ! INSPECT THE OPERAND
         UNPACK
         TYPEP=TYPE; PRECP=PREC
         %IF TYPEP=2 %THEN OPCODE=X'FA' %ELSE OPCODE=X'EA'
         VALUE=0
         %IF OPND2_FLAG=0 %AND 1<=OPND2_D<=63*TYPE %THEN %C
            VALUE=OPND2_D;             ! EXPONENT IS #0 AND CONSTANT
         LOAD(OPND1,ACCR,2);               ! FETCH OPERAND TO ACC
         %IF TYPEP=2 %AND PRECP=5 %THEN LENGTHEN(OPND1)%AND PRECP=6
!
! OPTIMISE **2 **3 AND **4
!
         %IF 2<=VALUE<=4 %THEN %START
            PF1(ST,0,TOS,0)
            %IF VALUE=3 %THEN PF1(ST,0,TOS,0)
            PF1(OPCODE,0,TOS,0)
            %IF VALUE=4 %THEN PF1(ST,0,TOS,0)
            %IF VALUE>2 %THEN PF1(OPCODE,0,TOS,0)
            %RETURN
         %FINISH
!
! OTHERWISE STORE OPERAND IN 'WORK' AND GET HOLD OF EXPONENT
!
         GET WSP(WORK,BYTES(PRECP)>>2)
         %IF TYPEP=2 %THEN GET WSP(EXPWORK,1)
         PSF1(ST,1,WORK)
         REGISTER(ACCR)=0
         PLABEL=PLABEL-1;              ! LABEL FOR JUMPING OUT
         LOAD(OPND2,BREG,2);               ! EXPONENT TO ANY REGISTER
         %IF TYPE=2 %OR PREC>5 %START;! EXPONENT IS REAL OR LONG INT
            FAULT(39,0)
         %FINISH
         %IF TYPEP=2 %THEN PSF1(STB,1,EXPWORK)
!
! GET '1' INTO ACC IN APPROPIATE FORM
!
         GET IN ACC(ACCR,BYTES(PRECP+1-TYPEP)>>2,0,0,1)
         %IF TYPEP=2 %THEN PSF1(FLT,0,0)
!
! IF EXPONENT NOT KNOWN AT COMPILE TIME TO BE +VE CONSTANT MUST
! ALLOW FOR ZERO  :- XX**0=1 FOR ALL XX
! ALSO ALLOW FOR X**(-N) WHICH IS 1/(X**N) FOR ALL X & N
!
         %IF VALUE=0 %THEN %START;       ! NOT +VE CONSTANT
            ENTER JUMP(28,PLABEL,B'11');    ! J(B=0) END OF EXP ROUTINE
            %IF TYPEP=2 %THEN %START
               PF3(JAT,13,0,4);              ! J*+4 IF B>0
               PSF1(SLB,0,0)
               PF1(SBB,0,TOS,0)
            %FINISH
!
! IN CHECKING MODE PLANT CODE TO CHECK RANGE OF EXPONENT
!
            %IF PARMOPT=1 %THEN %START
               %IF TYPEP=1 %THEN PPJ(30,7);  ! JUMP B<0
               PSF1(CPB,0,64*TYPEP*TYPEP-1)
               PPJ(2,7)
            %FINISH
         %FINISH
         C=CA
         PSF1(OPCODE,1,WORK)
         PSF1(DEBJ,0,(C-CA)//2)
!
! FOR REAL EXPONENTS CHECK IF NEGATIVE AND EVALUATE INVERSE
!
         %IF VALUE=0 %AND TYPEP=2 %THEN %START
            PSF1(LB,1,EXPWORK);        ! LB ON ORIGINAL EXPONENT
            ENTER JUMP(46,PLABEL,B'11');! BP END OF EXP ROUTINE
            %IF PRECP<7 %THEN PF1(RRDV,0,PC,SPECIAL CONSTS(1))%ELSESTART
               PSF1(SLSD,0,1); PSF1(FLT,0,0)
               PF1(RDV,0,TOS,0)
            %FINISH
         %FINISH
!
! ALL OVER. REAL RESULTS ARE IN FR WORK. INT RESULTS IN GR WORK+1
! FREE AND FORGET ANY OTHER REGISTERS
!
         TYPE=TYPEP; PREC=PRECP
         REGISTER(BREG)=0
         GRUSE(BREG)=0
         REGISTER(ACCR)=1
         OPND1_PTYPE=16*PREC+TYPE
         OPND1_XB=0; OPND1_D=ACCR
         ENTER LAB(PLABEL,B'11');      ! LABEL AT END OF EXP ROUTINE
         %END
         %END;                          ! OF ROUTINE EXPOP
         %ROUTINE REDUCE ENV(%INTEGERNAME HEAD)
!***********************************************************************
!*       HEAD HAS AN ENVIRONMENT  - THIS ROUTINE REMOVES ANYTHING      *
!*       INCOMPATIBLE WITH THE CURRENT REGISTER STATE                  *
!***********************************************************************
         %INTEGER NEWHEAD,I,J,K,REG,USE
         NEWHEAD=0
         %WHILE HEAD#0 %CYCLE
            POP(HEAD,I,J,K)
            REG=K>>8; USE=K&255
            %IF USE=GRUSE(REG) %AND I=GRINF(REG) %THEN %C
               PUSH(NEWHEAD,I,J,K)
         %REPEAT
         HEAD=NEWHEAD
         %END
         %ROUTINE CCOND(%INTEGER IU,FARLAB)
!***********************************************************************
!*       COMPILES <IU><SC><RESTOFCOND>%THEN<UI1>%ELSE<UI2>             *
!*       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>            *
!***********************************************************************
!%ROUTINESPEC WRITE CONDLIST
%ROUTINESPEC SKIP SC
%ROUTINESPEC SKIP COND
%ROUTINESPEC CCOMP
!
! 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
!
         %CONSTINTEGERARRAY FCOMP(1:21)=8,13,5,7,10,2,7,
                                        8,10,2,7,13,5,7,
                                        27,0,0,43,0,0,43;
!
%INTEGER PIN,PP,II,L,CPTR,CMAX,LL
%RECORDFORMAT CF(%BYTEINTEGER TF,CMP1,CMP2,LABU,LVL,JMP, %C
                 %INTEGER LABNO,SP1,SP2)
%RECORDARRAY CLIST(1:30)(CF)
%RECORDNAME C1,C2(CF)
!
! PASS 1.   ANALYSES THE CONDITION
!
         PIN=P;                        ! SAVE INITIAL AR POINTER
         CPTR=1; L=3;                  ! LEVEL=3 TO ALLOW 2 LOWER
         C1==CLIST(CPTR);              ! SET UP RECORD FOR FIRST CMPARSN
         C1=0
         SKIP SC;                      ! SKIP THE 1ST CMPARSN
         SKIP COND;                    ! AND ANY %AND/%OR CLAUSES
         C1_LVL=2;                     ! LEVEL =-1 FOR %IF/%THEN ENTRY
         C1_TF=IU
         CMAX=CPTR+1
         C1==CLIST(CMAX); C1=0
         C1_LVL=1;                     ! LEVEL =-2 FOR ELSE ENTRY
         C1_TF=3-IU; C1_LABNO=FARLAB
         PP=P;                         ! SAVE FINAL AR POINTER
         FAULT(209,0) %IF CMAX>29;     ! TOO COMPLICATED
!
! PASS 2 WORKS OUT WHERE TO JUMP TO
! THE JUMP IS FORWARD TO THE START OF THE CLAUSE WITH A DIFFERENT
! CONNECTOR (AND/OR) PROVIDED THIS IS AT A LOWER LEVEL THAN THE BRANCH
! AND ALSO AT A LOWER LEVEL THAN THE LOWEST POINT REACHED ENROUTE
!
! ALSO CONTAINS PASS 3 (TRIVIAL)
! ASSIGN LABELS WHERE LABU SHOWS THEY ARE REQUIRED
!
         %CYCLE CPTR=1,1,CMAX-1
            C1==CLIST(CPTR)
            L=C1_LVL; LL=L;            ! LL FOR LOWEST LEVEL ENROUTE
            %CYCLE II=CPTR+1,1,CMAX+1
              C2==CLIST(II)
              %EXIT %IF C1_TF#C2_TF %AND C2_LVL<LL
              %IF C2_LVL<LL %THEN LL=C2_LVL
            %REPEAT
            C1_JMP=II;                 ! CLAUSE TO JUMP TO
            C2_LABU=C2_LABU+1
             %IF C1_CMP2#0 %OR C1_CMP1=8 %START; ! D-SIDED OR RESLN
                                       ! REQIUIRES A LABEL ON THE
               C1_LABU=C1_LABU+1;      ! THE NEXT SIMPLE CONDITION
            %FINISH
            %IF C1_LABU#0 %AND C1_LABNO<=0 %THEN PLABEL=PLABEL-1 %C
                                           %AND C1_LABNO=PLABEL
         %REPEAT
!
! PASS 4 GENERATE THE CODE
!
!         WRITE CONDLIST %IF DCOMP=1
         %CYCLE CPTR=1,1,CMAX-1
            C1==CLIST(CPTR)
            CCOMP
            %IF C1_LABNO>0 %THEN ENTER LAB(C1_LABNO,B'11')
         %REPEAT
!
         P=PP; %RETURN
         %ROUTINE SKIP SC
!***********************************************************************
!*       SKIPS OVER A SIMPLE CONDITION. P ON ALT OF<SC>                *
!***********************************************************************
%INTEGER ALT
         ALT=A(P); P=P+1
         %IF ALT=1 %THEN %START;      ! <EXP><COMP><EXP><SECONDSIDE>
            C1_SP1=P-PIN
            SKIP EXP
            C1_CMP1=A(P)
            P=P+1; C1_SP2=P-PIN
            SKIP EXP
            %IF A(P)=2 %THEN P=P+1 %ELSE %START
               C1_CMP2=A(P+1);        ! DEAL WITH 2ND HALF OF D-SIDED
               P=P+2; SKIP EXP
            %FINISH
         %FINISH %ELSE %START;        ! '('<SC><RESTOFCOND>')'
             L=L+1
             SKIP SC
             SKIP COND
             L=L-1
         %FINISH
         %END;                        ! OF ROUTINE SKIP SC
         %ROUTINE SKIP COND
!***********************************************************************
!*       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
               CPTR=CPTR+1
               C1==CLIST(CPTR); C1=0
               SKIP SC
               ALTP=A(P); P=P+1
            %REPEAT
         %FINISH
         %END
!         %ROUTINE WRITE CONDLIST
!         %CONSTSTRING(5) %ARRAY CM(0:8)='     ','    =','   >=','    >',
!                                '    #','   <=','    <','   \=','   ->'
!         PRINTSTRING('
! NO   TF   C1   C2   LABU   LVL  JMP  LABNO
!')
!         %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_LABNO,7)
!            NEWLINE
!         %REPEAT
!         %END
         %ROUTINE CCOMP
!***********************************************************************
!*       COMPILES A COMPARISION: THREE DIFFERENT CASES                 *
!*       1) ARITHMETIC EXPRESSIONS EXPOP IS USED                       *
!*       2) STRING EXPRESSION AD-HOC CODE PLANTED BY THIS ROUTINE      *
!*       3) RESOLUTIONS - CRES CAN BE USED                             *
!***********************************************************************
%ROUTINESPEC ACOMP(%INTEGER TF,LAB,DS)
%ROUTINESPEC SCOMP(%INTEGER DS,TF,LAB,%INTEGERNAME WA)
%INTEGER HEAD1,HEAD2,NOPS,TE1,TE2,TEX1,TEX2,MASK,P1,P2,FEXIT,IEXIT, %C
         CMP,WA1,WA2,WA3,BOT1,BOT2
!
         HEAD1=0; HEAD2=0; NOPS=0
         BOT1=0; BOT2=0
         FEXIT=CLIST(C1_JMP)_LABNO;    ! FINAL EXIT
         IEXIT=FEXIT;                  ! INTERMEDIATE EXIT (D-SIDED ETC)
         %IF C1_TF=2 %AND (C1_CMP1=8 %OR C1_CMP2#0) %THEN %C
                      IEXIT=C1_LABNO
!
         P=PIN+C1_SP2
         P2=P; P1=PIN+C1_SP1
         %IF C1_CMP1=8 %OR C1_CMP2=8 %THEN %START
                                       ! CONDITIONAL RESOLUTION
                                       ! NB CRES BRANCHES ON FALSE!!
            P=P1
            %IF C1_CMP2=0 %AND A(P+3)=4 %AND A(P+4)=1 %START
               P=P+5; CNAME(2,DR);     ! LH STRING TO DR
               %IF A(P)=2 %AND TYPE=5 %THEN %START
                  P=P2
                  CRES(IEXIT);         ! FAILURES -> IEXIT
                  %IF C1_TF=2 %THEN ENTER JUMP(15,FEXIT,B'11')
                  %RETURN
               %FINISH
            %FINISH
            FAULT(73,0)
            %RETURN
         %FINISH
         MASK=FCOMP(C1_CMP1)
         TE2=TSEXP(TEX2)
         ->STR %IF TYPE=5
         ->ARITH %UNLESS TE2=1
         P=P1; TE1=TSEXP(TEX1)
         ->STR %IF TYPE=5
ARITH:                                 ! ARITHMETIC COMPARISIONS
         P=P1+3
         TORP(HEAD1,BOT1,NOPS);      ! FIRST EXPRESSION TO REVERSE POL
         CMP=C1_CMP1
         P=P2+3
         %IF C1_CMP2#0 %THEN %START;   ! IF D-SIDED DEAL WITH MIDDLE
            ACOMP(1,IEXIT,1);          ! BRANCH IEXIT %IF FALSE
            P=P+5;                     ! TO THE THIRD EXPRSN
            CMP=C1_CMP2;               ! COMPARATOR NO 2
         %FINISH
!
         ACOMP(C1_TF,FEXIT,0);         ! SECOND OR ONLY COMPARISION
!
         EXPOP(HEAD1,-1,NOPS,256+16*PREC+TYPE);      ! PLANT THE CODE
!         CLEAR LIST(HEAD1)
         ASLIST(BOT1)_LINK=ASL
         ASL=HEAD1
         %RETURN
STR:                                   ! STRING COMPARISIONS
                                       ! SOME CARE IS NEEDED IN FREEING
                                       ! STRING WK-AREAS SET BY CSTREXP
         P=P1
         WA1=0; WA2=0; WA3=0
         %IF C1_CMP2=0 %AND 7<=FCOMP(C1_CMP1)<=8 %AND A(P2+3)=4 %AND %C
            A(P2+4)=2 %AND ((A(P2+5)=X'51' %AND FROM AR4(P2+6)=0 %ANDC
            A(P2+10)=2)%OR(A(P2+5)=5 %AND A(P2+10)=0 %AND A(P2+11)=2))%C
            %THEN %START
            CSTREXP(0,DR)
            MASK=FCOMP(C1_CMP1+14)
            %IF C1_TF=1 %THEN MASK=REVERSE(MASK)
            ENTER JUMP(MASK,FEXIT,B'11')
            %RETURN
         %FINISH
         CSTREXP(17,ACCR);            ! DO NOT FREE WK-AREA
         WA1=VALUE;                   ! SAVE ADDRESS OF WK-AREA
         CMP=C1_CMP1
         P=P2
!
         %IF C1_CMP2#0 %THEN %START;  ! D-SIDED DEAL WITH MIDDLE
            SCOMP(1,1,IEXIT,WA2)
            P=P+2; CMP=C1_CMP2
            %IF WA1#0 %THEN RETURN WSP(WA1,256) %AND WA1=0
         %FINISH
!
         SCOMP(0,C1_TF,FEXIT,WA3)
         %CYCLE CMP=ADDR(WA1),4,ADDR(WA3)
            %IF INTEGER(CMP)#0 %THEN RETURN WSP(INTEGER(CMP),256)
         %REPEAT
         %RETURN
         %ROUTINE ACOMP(%INTEGER TF,LAB,DS)
!***********************************************************************
!*       TYPE & PREC DEFINE THE EXPRSN IN REVERSE POLISH IN HEAD1      *
!*       THIS ROUTINE CONVERTS THE NEXT EXPRSN TO REVERSE POLISH AND   *
!*       ADDS OPERATORS FOR TYPE CHANGING(IF REQ) CMPRSN AND JUMP      *
!***********************************************************************
%INTEGER PRECP,TYPEP,COP
         PRECP=PREC; TYPEP=TYPE
!
! ADD OPERATORS IN THE REVERSE ORDER. IE JUMP(34) THEN COMPARE(31)
!
         PUSH(HEAD2,34,TF,0)
         BOT2=HEAD2
         PUSH(HEAD2,1<<16,LAB,0)
         PUSH(HEAD2,31+DS,CMP,0)
         NOPS=(NOPS+2)!1<<31;           ! FLAG COMPARE 
!
! CONVERT NEXT EXPRSN TO REVERSE POLISH AND TO THE SAME TYPE AS THE
! FIRST IF POSSIBLE. MODE=0 INTEGER IF POSSIBLE,=2 REAL, =3 LONGREAL
!
         TORP(HEAD2,BOT2,NOPS)
         %IF TYPEP>TYPE %THEN TYPE=TYPEP
!         CONCAT(HEAD1,HEAD2)
         ASLIST(BOT1)_LINK=HEAD2
         BOT1=BOT2; BOT2=0; HEAD2=0
         %END
         %ROUTINE SCOMP(%INTEGER DS,TF,LAB,%INTEGERNAME WA)
!***********************************************************************
!*       1ST STRING IS DEFINED BY (ACCR)                               *
!*       THIS ROUTINE EVALUATES THE NEXT STRING EXPRS AND PERFORMS     *
!*       THE COMPARISON & BRANCH.                                      *
!*       DS=0 UNLESS THIS COMPARISON IS THE FIRST HALF OF A DBLE-SIDED *
!***********************************************************************
%INTEGER MASK
%RECORD R(RD)
!
         REGISTER(ACCR)=1
         OLINK(ACCR)=ADDR(R)
         R_PTYPE=1; R_XB=ACCR<<4; R_FLAG=9
         MASK=FCOMP(CMP)
         %IF TF=1 %THEN MASK=REVERSE(MASK); ! REVERSE MASK TO JMP IF FALS
!
         CSTREXP(16+DS,DR);                ! SAVE WK-AREA
         WA=VALUE
         REGISTER(ACCR)=0
         %IF R_FLAG#9 %THEN PF1(LSD,0,TOS,0)
         %IF DS#0 %THEN PF1(STD,0,TOS,0)
         PSF1(INCA,0,1); PSF1(IAD,0,1)
         PF2(CPS,1,1,0,0,0)
         GRUSE(ACCR)=0; GRUSE(DR)=0
!
! IF CC=8 MUST CHECK THAT ACC STRING IS EXHAUSTED OTHERWISE CHANGE CC
! TO GIVE RESULT ACC>DR. THIS IS BEST FIDDLED USING ISH.
! CAN SKIP THIS CHECK IF MASK IS SUCH THAT 2**3 &2**2 BITS SET THE SAME
!
         %IF 0#MASK&X'C'#X'C' %THEN %START
            PF3(JCC,7,0,4)
            PSF1(USH,0,-32)
            PSF1(ISH,0,-24)
         %FINISH
         %IF DS#0 %THEN PF1(LSD,0,TOS,0);    ! DOES NOT CHANGE CC
         ENTER JUMP(MASK,LAB,B'11')
         %END
         %END
         %END
         %INTEGERFN REVERSE(%INTEGER MASK)
!***********************************************************************
!*       REVERSE THE MASK FOR A JCC(MASK<=15),JAT(>15) OR JAF(>31     *
!***********************************************************************
         %IF MASK>15 %THEN MASK=MASK!!X'30' %ELSE MASK=MASK!!15
         %RESULT=MASK
%END
         %ROUTINE ENTER LAB(%INTEGER LAB,FLAGS)
!***********************************************************************
!*       ENTER A NEW LABEL ON THE LABEL LIST FOR THE CURRENT LEVEL     *
!*       2**0  OF FLAGS  = 1  CONDITIONAL ENTRY                        *
!*       2**1  OF FLAGS  = 1  UPDATE ENVIRONMENT                       *
!*       2**2  OF FLAGS  = 1  REPLACE ENV     =0  MERGE ENV            *
!*       THE LABEL LIST                                                *
!*       S1 =   USE BITS<<8 ! LABEL ADDR                               *
!*       S2 =   ENVIRONMENT LIST << 16 ! UNFILLED JUMPS LIST           *
!*       S3 = LAB NO - RESET TO FFFF WHEN USED FOR INTERNAL LABELS     *
!***********************************************************************
%INTEGER CELL,AT,ENVHEAD,JUMPHEAD,INSTRN,OLDCELL,WORK
%RECORDNAME LCELL(LISTF)
%INTEGERNAME LHEAD
         CELL=LABEL(LEVEL); OLDCELL=0
         %WHILE CELL>0 %CYCLE
            LCELL==ASLIST(CELL)
            %EXIT %IF LCELL_S3=LAB
            OLDCELL=CELL; CELL=LCELL_LINK
         %REPEAT
!
         %IF CELL<=0 %THEN %START;      ! LABEL NOT KNOWN
            %IF FLAGS&1=0 %THEN %START;! UNCONDITIONAL ENTRY
               PUSH(LABEL(LEVEL),CA,0,LAB)
               FORGET(-1)
            %FINISH
            %RETURN
         %FINISH
!
! LABEL HAS BEEN REFERENCED - FILL IN ITS ADDRESS
!
         %IF LCELL_S1&X'FFFFFF'# 0 %THEN %START
            FAULT(2,LAB);             ! LABEL SET TWICE
         %FINISH %ELSE %START
            LCELL_S1=X'1000000'!CA
         %FINISH
!
! SORT OUT ENVIRONMENTS  -  AS DIRECTED BY FLAGS
!
         JUMPHEAD=LCELL_S2
         ENVHEAD=JUMPHEAD>>16
         JUMPHEAD=JUMPHEAD&X'FFFF'
         %IF FLAGS&2=0 %THEN %START
            FORGET(-1)
            CLEAR LIST(ENVHEAD)
         %FINISH %ELSE %START
            REMEMBER %IF FLAGS&4=0
            RESTORE (ENVHEAD)
            ENVHEAD=0
            MERGE INFO %IF FLAGS&4=0
         %FINISH
!
! NOW FILL JUMPS TO THIS LABEL - JUMP LIST FORMAT GIVEN IN 'ENTER JMP'
!
         %WHILE  JUMPHEAD#0  %CYCLE
            POP(JUMPHEAD,AT,INSTRN,WORK)
            PLUG(1,AT,INSTRN!(CA-AT)//2,4)
         %REPEAT
         LCELL_S2=0
         %IF LAB> MAX ULAB  %THEN %START
            %IF OLDCELL=0 %THEN LHEAD==LABEL(LEVEL)  %ELSE %C
               LHEAD==ASLIST(OLDCELL)_LINK
            POP(LHEAD,AT,AT,AT)
         %FINISH
         %END
         %ROUTINE ENTER JUMP(%INTEGER MASK,LAB,FLAGS)
!***********************************************************************
!*       IF LAB HAS BEEN ENCOUNTERED THEN PLANT A JCC OTHERWISE ENTER  *
!*       THE LABEL IN THE LABEL LIST AND ATTACH THE JUMP TO IT SO IT   *
!*       CAN BE PLANTED WHEN THE LABEL IS FOUND                        *
!*       THE LABEL LIST IS DESCRIBED UNDER 'ENTER LAB'                 *
!*       THE JUMP SUB-LIST HAS THE FORM                                *
!*       S1= ADDR OF JUMP                                              *
!*       S2=INSTRN                                                     *
!*                                                                     *
!*       FLAGS BITS SIGNIFY AS FOLLOWS                                 *
!*       2**0 =1  JUMP IS KNOWN TO BE SHORT                            *
!*       2**1 =1  ENVIRONMENT MERGEING REQUIRED                        *
!***********************************************************************
%INTEGER AT,CELL,J,JJ,LABADDR,I,ENVHEAD,OLDENV,JCODE,INSTRN
%RECORDNAME LCELL(LISTF)
         ENVHEAD=0; AT=CA
         %IF LAB<MAX ULAB %THEN FLAGS=FLAGS&X'FD';! NO MERGE
         %IF LAB<21000 %THEN FLAGS=FLAGS&X'FE'; ! SF OR USER LAB=LONG
         CELL=LABEL(LEVEL)
         %WHILE CELL>0 %CYCLE
            LCELL==ASLIST(CELL)
            %IF LAB=LCELL_S3 %THEN %EXIT
            CELL=LCELL_LINK
         %REPEAT
         INSTRN=MASK
         %IF INSTRN>>8=0 %THEN %START
            JCODE=JCC
            %IF MASK>=16 %THEN JCODE=JAT
            %IF MASK>=32 %THEN JCODE=JAF
            INSTRN=JCODE<<24!(MASK&15)<<21
            %IF MASK=15 %THEN INSTRN=JUNC<<24!3<<23
         %FINISH
         -> FIRSTREF %IF CELL<=0
         LABADDR=LCELL_S1&X'FFFFFF'
         -> NOT YET SET %IF LABADDR=0
         LCELL_S1=LABADDR!X'1000000';! FLAG LABEL AS USED
         I=(LABADDR-CA)//2
         %IF MASK=15 %THEN PSF1(JUNC,0,I) %ELSE %C
                           PCONST(INSTRN!(I&X'3FFFF'))
         %RETURN
FIRSTREF:                              ! FIRST REFERENCE TO A NEW LABEL
         %IF LAB>MAX ULAB %AND FLAGS&2#0 %THEN GET ENV(ENV HEAD)
         PUSH(LABEL(LEVEL),X'1000000',ENVHEAD<<16,LAB)
         CELL=LABEL(LEVEL)
         LCELL==ASLIST(CELL)
         -> CODE
NOT YET SET:                           ! LABEL REFERENCED BEFORE
         %IF LAB>MAX ULAB %AND FLAGS&2#0 %THEN %START
            I=LCELL_S2
            OLDENV=I>>16
            REDUCE ENV(OLD ENV)
            LCELL_S2=OLDENV<<16!I&X'FFFF'
         %FINISH
CODE:                                  ! ACTUALLY PLANT THE JUMP
         J=LCELL_S2
         JJ=J&X'FFFF'
         PUSH(JJ,CA,INSTRN,0)
         LCELL_S2=J&X'FFFF0000'!JJ
         PCONST(INSTRN)
         %END
%ROUTINE REMOVE LAB(%INTEGER LAB)
!***********************************************************************
!*    REMOVES A ALBEL FROM THE CURRENT LABEL LIST WHEN KNOWN TO        *
!*    BE REDUNDANT. MAINLY USED FOR CYCLE LABELS                       *
!***********************************************************************
%RECORDNAME LCELL(LISTF)
%INTEGERNAME LHEAD
%INTEGER CELL,AT
      LHEAD==LABEL(LEVEL); CELL=LHEAD
      %WHILE CELL>0 %CYCLE
         LCELL==ASLIST(CELL)
         %EXIT %IF LCELL_S3=LAB
         LHEAD==LCELL_LINK
         CELL=LHEAD
      %REPEAT
      %IF CELL>0 %THEN POP(LHEAD,AT,AT,AT)
%END
         %ROUTINE MERGE INFO
!***********************************************************************
!*       MERGE THE CURRENT STATUS OF THE REGISTERS WITH THE VALUES     *
!*      AT THE START OF THE CONDITIONAL CLAUSE. THIS PERMITS THE       *
!*       THE COMPILER TO REMEMBER UNCHANGED REGISTERS BUT NOT THOSE    *
!*      WHICH DEPEND ON A PARTICULAR RUN TIME ROUTE BEING TAKEN        *
!***********************************************************************
         %INTEGER I
         %CYCLE I=0,1,7
           GRUSE(I)=0 %UNLESS SGRUSE(I)=GRUSE(I) %AND SGRINF(I)=GRINF(I)
         %REPEAT
         %END
         %ROUTINE     REMEMBER
%INTEGER I
         %CYCLE I=0,1,7
            SGRUSE(I)=GRUSE(I)
            SGRINF(I)=GRINF(I)
         %REPEAT
         %END
%ROUTINE CREATE AH(%INTEGER MODE)
!***********************************************************************
!*       CREATE AN ARRAY HEAD IN TEMPORARY SPACE BY MODIFYING THE HEAD *
!*       THE HEAD AT AREA,ACCESS & DISP AS FOLOWS:-                    *
!*       MODE=0 (ARRAY MAPPING) ACC HAS ADDR(1ST ELEMENT)              *
!*       MODE=1 (ARRAYS IN RECORDS) ACC HAS RELOCATION FACTOR          *
!***********************************************************************
%INTEGER WK
         GET WSP(WK,4)
         AREA=AREA CODE
         %IF MODE=0 %THEN %START
            %IF COMPILER=1=J %AND TYPE<=2 %START
               PF1(SLSS,2,AREA,DISP+8); ! LWB TO ACC
               PSF1(IMY,0,-BYTES(PREC)) %UNLESS PREC=3
               PF1(IAD,0,TOS,0)
               GRUSE(DR)=0
            %FINISH
            PSORLF1(LUH,ACCESS,AREA,DISP)
         %FINISH %ELSE %START
            PSF1(LUH,0,0)
            PSORLF1(IAD,ACCESS,AREA,DISP)
         %FINISH
!
         PSF1(ST,1,WK);                 ! 1ST PART OF HEAD =DESC TO ARRAY
         PSORLF1(LSD,ACCESS,AREA,DISP+8)
         PSF1(ST,1,WK+8);               ! 2ND PART = DESCPTR TO DV
         GRUSE(ACCR)=0
         ACCESS=0; AREA=LNB; DISP=WK
%END
         %ROUTINE CSNAME(%INTEGER Z,REG)
!***********************************************************************
!*       COMPILE A SPECIAL NAME - PTYPE=10006 (=%ROUTINE %LABEL)       *
!*       THEIR TRUE PTYPE IS IN GLOBAL ARRAY TSNAME.                   *
!*       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 STRINWG(%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 FROMSTRING(%STRING(255)S,%INTEGER BEG,END) *
!*       48=%RECORDMAP RECORD(%INTEGER REC ADDR)                       *
!*       49=%ARRAYMAP ARRAY(%INTEGER A1ADDR,%ARRAYNAME FORMAT)         *
!*       50=%ROUTINE SETMARGINS(%INTEGER INOUT,LHM,RHM)                *
!*       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)                 *
!***********************************************************************
%INTEGERFNSPEC OPTMAP
         %SWITCH ADHOC(1:14)
         %CONSTINTEGERARRAY SNINFO(0:61)=%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'801B0014',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'110A8018',X'120B1000',X'80170013',X'11060024',
                    X'100C0024',X'100D0024',X'2100003E'(2),
                    X'110E0024'(4),
                    X'10020024',X'2100003E';
%CONSTSTRING(11)%ARRAY SNXREFS(0:20)=%C
                  'READSTRING', 'S#READ',   'S#IARCSIN', 'S#INT',
                  'S#INTPT' , 'S#FRACPT', 'S#PRINT' , 'S#PRINTFL',
                  'S#IARCCOS','S#ISQRT' , 'S#ILOG'  , 'S#ISIN',
                  'S#ICOS'  , 'S#ITAN'  , 'S#IEXP'  , 'CLOSESTREAM',
                  'S#IRADIUS','S#IARCTAN','FROMSTRING','SETMARGINS',
                  '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.
!
         %CONSTINTEGERARRAY SNPARAMS(0:29)=0,
               1,X'62',       2,X'62',X'62',  2,X'62',X'51',
               3,X'62',X'51',X'51',   1,X'435',   3,X'35',X'51',X'51',
               1,X'400',     1,X'51',      3,X'51',X'51',X'51',
               2,X'51',X'51';
!
         %ROUTINESPEC RTOS(%INTEGER REG)
         %RECORD R(RD)
         %INTEGER ERRNO,FLAG,POINTER
         %INTEGER PIN,SNNO,SNNAME,NAPS,SNPTYPE,JJ,%C
                  XTRA,IOCPEP,B,D,SNINF,P0,OPHEAD
!
         SNNAME=FROM AR2(P)
         SNNO=K;                       ! INDEX INTO SNINFO
         TESTAPP(NAPS);                ! COUNT ACTUAL PARAMETERS
         PIN=P; P=P+2
         SNPTYPE=TSNAME(SNNO)
         SNINF=SNINFO(SNNO)
         XTRA=SNINF&X'FFFF'
         POINTER=(SNINF>>16)&255
         FLAG=SNINF>>24
!
! THE IMPLICITLY SPECIFIED ROUTINE ARE THE EASIEST OF ALL TO DEAL WITH.
! JUST SET UP THE EXTERNAL SPEC & PARAMETERS. THEN A RECURSIVE CALL
! OF CNAME THEN FINDS THE ROUTINE UNDER ITS TRUE COLOURS AND COMPILES
! THE CALL. ALL CALLS EXCEPT THE FIRST ARE DEALT WITH DIRECTLY BY CNAME.
! ALL NONTRIVIAL ROUTINES SHOULD BE DEALT WITH IN THIS MANNER
! XTRA HAS INDEX INTO ARRAY OF EXTERNAL NAMES SO THAT THESE
! CAN EASILY BE CHANGED.
!
         %IF FLAG&X'80'#0 %THEN %START
            CXREF(SNXREFS(XTRA),0,2,JJ);! JJ SET WITH REF DISPLACEMENT
            %IF SNNO=26 %THEN LOGEPDISP=JJ
            %IF SNNO=31 %THEN EXPEPDISP=JJ
            OPHEAD=0; P0=SNPARAMS(POINTER)
            PUSH(OPHEAD,JJ,P0,0)
            K=OPHEAD; JJ=1; D=64
            %WHILE JJ<=P0 %CYCLE
               PTYPE=SNPARAMS(POINTER+JJ)
               UNPACK
               %IF NAM=0 %THEN ACC=BYTES(PREC) %ELSE ACC=8
               %IF PTYPE=X'35' %THEN ACC=256;!STRING BY VALUE
               INSERTAT END(OPHEAD,PTYPE,ACC<<16!D,0)
               D=D+ACC
               JJ=JJ+1
            %REPEAT
            I=1; J=14
            OLDI=0; PTYPE=SNPTYPE
            REPLACETAG(SNNAME)
            P=PIN; CNAME(Z,REG);        ! RECURSIVE CALL
            NEST=REG
            P=P-2; %RETURN;             ! DUPLICATES CHECK OF <ENAME>
         %FINISH
!
! ALL ROUTINES EXCEPT THE IMPLICITS REQUIRE A CHECK THAT THE USE OF THE
! NAME IS LEGAL AND THAT THE CORRECT NO OF PARAMETERS(BOTTOM 2 BITS OF
! FLAG) HAS BEEN SUPPLIED. THE CHECK IS TRIVIAL - THE PROBLEM
! IS TO GET THE RIGHT ERROR NUMBER.
! XTRA HAS A BITMASK OF ALLOWED USES(IE ALLOWED Z VALUES)
!
         %IF NAPS#FLAG&3 %THEN ERRNO=19 %AND ->ERREXIT
         JJ=1<<Z
         %IF JJ&XTRA=0 %THEN %START;    ! ILLEGAL USE
            ERRNO=23
            %IF Z=0 %THEN ERRNO=17
            %IF Z=1 %OR 3<=Z<=4 %THEN ERRNO=29
            %IF XTRA&X'F000'#0 %THEN ERRNO=84
            ->ERR EXIT
         %FINISH
!
! A NUMBER OF INPUT-OUTPUT ROUTINES ARE MAPPED ONTO CALLS OF IOCP.
! THIS ARRANGEMENT HAS THE ADVANTAGE OF REQUIRING ONL 1 EXTERNAL REF
! IN THE GLA BUT HAS THE DISADVANTAGE THAT THE I-O ROUTINES CAN NOT
! BE PASSED AS RT-TYPE PARAMETERS AS WELL AS REQUIRING MESSY CODE
! HEREABOUTS.  SNINF_PTR HOLD EITHER:-
!       1) THE IOCP ENTRY POINT NO
!   OR  2) THE SYMBOL TO BE OUTPUT WITH 2**7 BIT SET
!
! THIS SECTION DEALS WITH SELECT INPUT,SELECT OUTPUT,NEWLINE,NEWPAGE
!                         SPACE,SKIP SYMBOL,PRINT SYMBOL,PRINT STRING
!                         AND PRINT CH
!
         %IF FLAG&X'40'#0 %THEN %START
            IOCPEP=POINTER; B=ACCR
            %IF FLAG&3#0 %THEN %START;  ! RT HAS PARAMS
               P=P+1
               %IF SNNO=37 %THEN CSTREXP(0,DR) %AND B=DR %C
                           %ELSE CSEXP(ACCR,X'51')
            %FINISH
            %IF IOCPEP>127 %THEN PSF1(LSS,0,IOCPEP&127) %AND IOCPEP=5
            %IF SNNO=4 %THEN PSF1(LSS,0,0);! SKIP SYMBOL FORCE ACS=1
            CIOCP(IOCPEP,B);           ! PLANT CALL OF IOCP
            ->OKEXIT
         %FINISH
!
! THE BUILT-IN MAPS (INTEGER ETC BUT NOT RECORD OR ARRAY)
!
         %IF FLAG&X'20'#0 %THEN %START
            SNPTYPE=X'1400'+SNPTYPE;      ! ADD MAP BITS
            %IF PARMOPT=0 %AND OPTMAP#0 %THEN ->OKEXIT
            %IF Z=1 %THEN  BIMSTR=1;   ! SPECIAL FLAG FOR STORE VIA MAP
            P=P+1
            CSEXP(BREG,X'51'); P=P+1
            %IF Z=1 %THEN BIMSTR=0
            JJ=SNPTYPE>>4&15
            DISP=MAPDES(JJ)
            AREA=PC; ACCESS=3
            ->OKEXIT
         %FINISH
!
! ADHOC CODING IS REQUIRED FOR THE REMAINING ROUTINES APART FROM
! A CHECK FOR NAMETYPE PARAMETERS. THE SWITCH NO IS KEPT IN POINTER
!
         P=P+1
         %IF FLAG&8#0 %AND(A(P+3)#4 %OR A(P+4)#1 %OR %C
            A(P+FROM AR2(P+1)+1)#2) %THEN ERRNO=22 %AND ->ERREXIT
         ->ADHOC(POINTER)
ADHOC(1):                               ! NEWLINES(=6) & SPACES(=7)
         CSEXP(ACCR,X'51');                 ! REPITITION NO TO ACC
         %IF SNNO=6 %THEN JJ=10 %ELSE JJ=32
         PSF1(USH,0,8);                 ! SHIFT UP 8 PLACES
         PSF1(OR,0,JJ);                ! OR SYMBOL
         CIOCP(17,ACCR)
         ->OKEXIT
ADHOC(2):                               ! NEXTSYMBOL(=8) & NEXTITEM(=44)
                                        ! ALSO NEXTCH(=60)
         GET IN ACC(ACCR,1,0,0,0);      ! PRESERVE ANY INTERMEDIATES
         %IF SNNO=60 %THEN JJ=18 %ELSE JJ=2
         CIOCP(JJ,ACCR);                ! LEAVES THE SYMBOL IN ACC
         %IF SNNO=44 %THEN %START
            RTOS(BREG)
            SNPTYPE=X'1435'
            AREA=PC; ACCESS=3
            DISP=MAPDES(3)
         %FINISH
         NEST=ACCR;                     ! CONVERT R1 TO STRING
         ->OKEXIT
ADHOC(3):                               ! READSYMBOL(=10),CH(=41)&ITEM(=43)
         %IF SNNO=41 %THEN JJ=4 %ELSE JJ=1
         PSF1(LSS,0,0)
         CIOCP(JJ,ACCR);                ! SYMBOL OR CH TO GR1
         P=P+5
         %IF SNNO=43 %THEN %START
            TYPE=5; RTOS(ACCR)
            PF1(LUH,0,PC,PARAM DES(3))
         %FINISH  %ELSE %START
            REGISTER(ACCR)=1; TYPE=1
         %FINISH
         JJ=TYPE
         ASSIGN(6,P);                   ! BY '=' TO PARAMETER
         P=PIN+5+FROM AR2(PIN+4)
         ->OKEXIT
ADHOC(4):                               ! INT(=16) AND INTPT (=17)
         CSEXP(ACCR,X'62')
         %IF SNNO=16 %THEN PF1(RAD,0,PC,SPECIAL CONSTS(0));! RAD 0.5
         %IF PARMOPT=0 %THEN PSF1(RSC,0,55) %AND PSF1(RSC,0,-55)
         %IF REGISTER(BREG)#0 %THEN BOOT OUT(BREG)
         PF1(FIX,0,BREG,0)
         PSF1(MYB,0,4)
         PSF1(CPB,0,-64)
         PF3(JCC,10,0,3)
         PSF1(LB,0,-64)
         PF1(ISH,0,BREG,0)
         PF1(STUH,0,BREG,0)
         GRUSE(ACCR)=0; GRUSE(BREG)=0
         NEST=ACCR
         ->OKEXIT
ADHOC(5):                               ! ADDR(=14)
         P=P+5; CNAME(4,REG);           ! FETCH ADDRESS MODE
         NEST=REG
         P=P+1; ->OKEXIT
ADHOC(6):                               ! MOD(=23), IMOD(=51)
         %IF SNNO=51 %THEN %START
            JJ=X'51'; B=5; D=IRSB
         %FINISH %ELSE %START
            JJ=X'62'; B=1; D=RRSB
         %FINISH
         CSEXP(ACCR,JJ);                 ! INTEGER OR LONGREAL MODE
         PF3(JAT,B,0,3);             ! JUMP ACC >0
         PSF1(D,0,0)
         GRUSE(ACCR)=0
         NEST=ACCR
         ->OKEXIT
ADHOC(7):                               ! CHARNO(=45) & LENGTH(=36)
         P=P+5
         CNAME(4,BREG)
         ERRNO=22
         ->ERREXIT %UNLESS TYPE=5
         P=P+2
         %IF SNNO#36 %THEN %START
            PF1(STB,0,TOS,0)
            CSEXP(BREG,X'51')
            P=P+1
            PF1(ADB,0,TOS,0)
         GRUSE(BREG)=0
         %FINISH
         DISP=MAPDES(3)
         AREA=PC; ACCESS=3
         SNPTYPE=SNPTYPE+X'1400'
         ->OKEXIT
ADHOC(12):                              ! PI(=52)
ADHOC(8):                               ! NL(=38). THIS FN IS PICKED OFF
         NEST=0;                        ! IN CSEXP.ONLY COMES HERE IN
         ->OKEXIT;                      ! ERROR EG NL=A+B
ADHOC(9):                               ! TOSTRING(=46)
         CSEXP(ACCR,X'51');                ! RET EXPSN
         P=P+1
         RTOS(BREG)
         DISP=MAPDES(3)
         AREA=PC; ACCESS=3
         SNPTYPE=SNPTYPE+X'1400'
         ->OKEXIT
ADHOC(10):                              ! RECORD(=48)
         %IF RECTB=0 %THEN JJ=X'1800FFFF' %AND %C
            STORECONST(RECTB,4,ADDR(JJ))
         %IF REG=ACCR %THEN %START
            CSEXP(ACCR,X'51')
            PF1(LUH,0,PC,RECTB)
         %FINISH %ELSE %START
            CSEXP(BREG,X'51')
            PF1(LDTB,0,PC,RECTB)
            PF1(LDA,0,BREG,0)
         %FINISH
         P=P+1
         GRUSE(REG)=0
         OLDI=0; ACC=X'FFFF'
         SNPTYPE=SNPTYPE+X'1400';       ! ADD MAP BITS
         ->OKEXIT
ADHOC(11):                              ! ARRAY(=49)
         CSEXP(ACCR,X'51');                 ! ADDR(A(0)) TO ACCR
         ERRNO=22
         ->ERREXIT %UNLESS A(P+4)=4 %AND A(P+5)=1
         REGISTER(ACCR)=1; OLINK(ACCR)=ADDR(R)
         R=0; R_PTYPE=X'51'
         R_FLAG=9; R_XB=ACCR
         P=P+6; CNAME(12,0)
         %IF R_FLAG#9 %THEN PF1(LSS,0,TOS,0)
         REGISTER(ACCR)=0
         ->ERREXIT %UNLESS A(P)=2 %AND ARR>0
         P=P+2
         CREATE AH(0)
         %RETURN
ADHOC(13):                              ! EVENTINF(=33) & EVENTLINE
         D=ONINF(LEVEL)
         FAULT(16,SNNAME) %IF D=0
         D=D+4 %IF SNNO#33
         PSF1(LSS,1,D)
         GRUSE(ACCR)=0
         NEST=ACCR
         ->OKEXIT
ADHOC(14):                              ! LENGTHEN AND SHORTEN
         D=(SNNO&3)*8
         CSEXP(ACCR,X'62517261'>>D&255)
         P=P+1; NEST=ACCR
OKEXIT:                                 ! NORMAL EXIT
         PTYPE=SNPTYPE; UNPACK
         %RETURN
ERREXIT:                                ! ERROR EXIT
         FAULT(ERRNO,SNNAME)
         BASE=0; DISP=0; ACCESS=0; AREA=0
         P=PIN+2; SKIP APP
         P=P-1; %RETURN
%INTEGERFN OPTMAP
!***********************************************************************
!*       LOOK FOR EXPRESSION LIKE INTEGER(ADDR(X)) AND AVOID USING DR  *
!***********************************************************************
%INTEGER VARNAME,REXP,PP,CVAL,OP
         %IF 3<=Z<=4 %OR SNNO=42 %OR SNNO=32 %OR SNNO=61 %THEN %RESULT=0
         PP=P+2; REXP=FROM AR2(PP)+PP;  ! TO REST OF EXP
         VARNAME=FROM AR2(PP+4);             ! SHOULD BE ADDR
         %RESULT=0 %UNLESS A(PP+2)=4 %AND A(PP+3)=1 %AND A(PP+6)=1
         COPY TAG(VARNAME);             ! CHECK IT WAS ADDR
         %RESULT=0 %UNLESS PTYPE=SNPT %AND K=14
         PP=PP+10
         %RESULT=0 %UNLESS A(PP)=4 %AND A(PP+1)=1 %AND %C
            A(PP+4)=2=A(PP+5) %AND A(PP+6)=2=A(PP+7) %AND A(PP+8)=2
         VARNAME=FROM AR2(PP+2); COPY TAG(VARNAME)
         %RESULT=0 %UNLESS PTYPE&X'FF0C'=0
         %IF A(REXP)=2 %THEN P=REXP+2 %ELSE %START
            OP=A(REXP+1)
            %RESULT=0 %UNLESS 1<=OP<=2 %AND A(REXP+2)=2 %AND %C
               A(REXP+3)=X'51' %AND A(REXP+8)=2
            CVAL=FROM AR4(REXP+4)
            %IF OP=1 %THEN K=K+CVAL %ELSE K=K-CVAL
            %RESULT=0 %IF K<0
            P=REXP+10
         %FINISH
         BASE=I
         DISP=K; AREA=-1; ACCESS=0
         AREA=AREA CODE
         %RESULT=1
%END
         %ROUTINE RTOS(%INTEGER REG)
!***********************************************************************
!*       PLANTS CODE TO CONVERT A SYMBOL IN ACC TO A ONE               *
!*       CHARACTER STRING IN A TEMPORARARY VARIABLE.                   *
!***********************************************************************
         %INTEGER KK
         GET WSP(KK,1);               ! GET 1 WORD WK AREA
         STRINGL=1; DISP=KK+2
         PF1(OR,0,0,256)
         PSF1(ST,1,KK)
         GET IN ACC(REG,1,0,LNB,PTR OFFSET(RBASE))
         %IF REG=BREG %THEN KK=ADB %ELSE KK=IAD
         PSF1(KK,0,DISP)
         GRUSE(BREG)=0
         %END
         %END;                        ! OF ROUTINE CSNAME
         %ROUTINE     CANAME(%INTEGER ARRP,BS,DP)
!***********************************************************************
!*       BS & DP DEFINE THE POSITION OF THE ARRAY HEAD                 * 
!*       ARRP=1 FOR ARRAYS,2 FOR VECTORS,3 FOR ARRAYS IN RECORDS       *
!*       BASIC DISP = DISPMNT OF A(0) FOR VECTORS OR ARRAYS IN RECORDS *
!***********************************************************************
%INTEGER HEAD1,HEAD2,HEAD3,NOPS,PTYPEP,KK,PP,JJ, %C
         TYPEP,ARRNAME,Q,PRECP,ELSIZE,NAMINF,BOT1,BOT2,BOT3
         PP=P; TYPEP=TYPE
         JJ=J; PTYPEP=PTYPE; PRECP=PREC
         %IF TYPE<=2 %THEN ELSIZE=BYTES(PRECP) %C
                                %ELSE ELSIZE=ACC
         ARRNAME=FROM AR2(P);            ! NAME OF ENTITY
         NAMINF=TAGS(ARRNAME)
         FAULT(29,ARRNAME) %IF ARR=3;    ! ARRAYFORMAT USED AS ARRAY
         NAMINF=-2 %IF ARRP>2;           ! SWITCHES&ARRAYS IN RECORDS 
         ARRP=ARRP&X'F';                 ! NOT OPTIMISED
         TEST APP(Q);                    ! COUNT NO OF SUBSCRIPTS
!
! CHECK CORRECT NO OF SUBSCRIPTS PROVIDED. HOWEVER ENTITIES DECLARED
! AS %<TYPE>ARRAYNAME HAVE NO DIMENSION . THIS SECTION SETS THE
! DIMENSION FROM THE FIRST USE OF THE NAME.
!
         %IF JJ=0 %THEN %START;        ! 0 DIMENSIONS = NOT KNOWN
            REPLACE1(TCELL,FROM1(TCELL)!Q);! DIMSN IS BOTTOM 4 BITS OF TAG
            JJ=Q
         %FINISH
         %IF JJ=Q#0 %THEN %START;        ! IN LINE CODE
!
! FOR IN-LINE CODE WE SET UP A CHAIN OF REVERSE POLISH OPERATIONS TO
! EVALUATE THE VARIOUS SUBSCRIPTS,MULTIPLY BY THE MULTIPLIERS AND
! ADD THEM TOGETHER.
!
         NOPS=0;HEAD1=0;HEAD2=0;HEAD3=0;! CLEAR LISTHEADS
         BOT1=0; BOT3=0
!
! NOW PROCESS THE SUBSCRIPTS CALLINR TORP TO CONVERT THE EXPRESSIONS
! TO REVERSE POLISH AND ADDING THE EXTRA OPERATIONS.
!
         P=PP+3
         %IF ARRP=2 %OR (JJ=1 %AND TYPE<=2 %AND PARMARR=0 %AND %C
                 (NAM=0 %OR COMPILER#0)) %START
            CSEXP(BREG,X'51'); P=P+1
            %IF PRECP=4 %THEN PF1(ADB,0,BREG,0) %AND GRUSE(BREG)=0
         %FINISH %ELSE %START
            %CYCLE KK=1,1,JJ;             ! THROUGH THE SUBSCRIPTS
               P=P+3; BOT2=0
               TORP(HEAD2,BOT2,NOPS);   ! SUBSCRIPT TO REVERSE POLISH
               P=P+1
!
! MULTIPLIERS ARE DOPE VECTOR ITEMS (OPTYPE=3)
!
! N SUBSCRIPTS WILL REQUIRE (N-1) MULTIPLICATIONS AND ADDITIONS
!
               NOPS=(NOPS+1)!1<<24;       ! DVM AS '*'
               PUSH(HEAD3,33,0,0);          ! DOPE VECTOR MULTIPLY
               BOT3=HEAD3 %IF BOT3=0
               PUSH(HEAD3,1<<16,KK<<16!JJ,BS<<18!DP);! MULTIPLIER
!               CONCAT (HEAD1,HEAD2);      ! OPERANDS TO MAIN LIST
               %IF HEAD1=0 %THEN HEAD1=HEAD2 %ELSE %C
                  ASLIST(BOT1)_LINK=HEAD2
               BOT1=BOT2; HEAD2=0
            %REPEAT
!
! ADD OPERATORS TO THE BACK OF OPERANDS AND EVALUATE
!
!            CONCAT(HEAD1,HEAD3);          ! OPERATORS  LINKED ON
            ASLIST(BOT1)_LINK=HEAD3
            BOT1=BOT3
            PP=P
            EXPOP(HEAD1,BREG,NOPS,X'51');     ! EVALUATE THE REVERSE POLISH LIST
            P=PP
!
!            CLEAR LIST(HEAD1);            ! RETURN SPACE
            ASLIST(BOT1)_LINK=ASL
            ASL=HEAD1
         %FINISH
         BASE=BS; DISP=DP; ACCESS=3; AREA=-1
         %FINISH %ELSE %START
            FAULT(19,ARRNAME)
            P=P+1; SKIP APP
            BASE=BS; DISP=0; ACCESS=3; AREA=-1
         %FINISH
         ACC=ELSIZE
         PTYPE=PTYPEP; UNPACK; J=JJ
         %END;                         ! OF ROUTINE CANAME
%ROUTINE CNAME(%INTEGER Z, REG)
!***********************************************************************
!*       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 SET ACCESS,AREA AND DISP FOR A 'STORE' OPERATION          *
!*       Z=2 FETCH NAME TO 'REG'                                       *
!*       Z=3 SET DESCRIPTOR IN REG FOR PASSING BY NAME                 *
!*       Z=4 SET 32 BIT ADDRESS OF NAME IN REG                         *
!*       Z=5 DELAYED FETCH IF NAME SIMPLE ELSE AS Z=2                  *
!*       Z=6 STORE 'REG' (CONTAINS POINTER) INTO POINTER VARIABLE      *
!*       Z=7->11  NOT NOW USED                                         *
!*       Z=12 SET BASE AND DISP TO POINT TO ARRAYHEAD                  *
!*       Z=13 SET REG TO POINT TO 4 WORD ROUTINE DISCRIPTOR            *
!*              (INTERNAL ROUTINES FIRST CREATE THE DISCRIPTOR)        *
!*       Z=14 STORE 'REG' INTO A RECORD NAME VARIABLE                  *
!*       Z=15 SET 'REG' TO POINT TO A RECORD                           *
!*       Z=16 SET BASE AND DISP  FOR RECORD                            *
!*                                                                     *
!*       REG (WHERE APPROPRIATE) IS SET AS FOLLOWS:-                   *
!*       >=0  A REGISTER                                               *
!*       -1   MEANS CHOOSE ANY REGISTER                                *
!*       IF A REGISTER IS CHOSEN THEN NEST IS SET WITH CHOICE          *
!***********************************************************************
%INTEGER JJ, JJJ, KK, RR, LEVELP, DISPP, NAMEP, PP, SAVESL, FNAME
%SWITCH S, FUNNY(12:13), SW(0:8), MAP(0:3)
         PP=P
         FNAME=A(P)<<8+A(P+1)
         %IF Z=1 %OR Z=6 %THEN STNAME=FNAME
         COPYTAG(FNAME)
         %IF I=-1 %THEN %START
            FAULT(16, FNAME)
            I=RLEVEL;  J=0;  K=FNAME
            KFORM=0; SNDISP=0; ACC=4
            PTYPE=7;  STORE TAG(K, N)
            K=N;  N=N+4;  COPYTAG(FNAME);! SET USE BITS!
         %FINISH
         SAVESL=ACC
         JJ=J;  JJ=0 %IF JJ=15
         NAMEP=FNAME
         LEVELP=I;  DISPP=K
         FAULT(29, FNAME) %IF LITL=1 %AND ROUT=0 %AND %C
            (Z=1 %OR Z=3 %OR (Z=4 %AND TYPE<5 %AND ARR=0))
         ->NOT SET %IF TYPE=7
         %IF (Z=0 %AND (ROUT#1 %OR 0#TYPE#6)) %OR (Z=13 %AND ROUT=0) %C
             %THEN FAULT(17,FNAME) %AND ->NOT SET
         ->FUNNY(Z) %IF Z>=10
         ->RTCALL %IF ROUT=1
         ->SW(TYPE)
SW(6):
SW(4):                                  !RECORD FORMAT NAME
         FAULT(20, FNAME)
SW(7):
NOT SET:                                ! NAME NOT SET
         NEST=0;  BASE=I;  DISP=K;  ACCESS=0
         AREA=LNB; PTYPE=1;  UNPACK
         P=P+2; SKIP APP;  ->CHKEN
FUNNY(12):                              ! SET BASE & DISP FOR ARRAYHEAD
         ->SW(3) %IF TYPE=3 %AND (ARR=0 %OR A(P+2)=1)
         %IF PTYPE=SNPT %THEN CSNAME(12,REG) %ELSE %START
            ACCESS=0; BASE=I; DISP=K; AREA=-1
            %IF ARR=1=J %AND PARMARR=0=NAM %AND TYPE<=2 %START;! ADJUST DESR TO 1ST ELMNT
               GET WSP(JJ,4)
               GET IN ACC(ACCR,4,0,AREA CODE,DISP)
               PSF1(ST,1,JJ)
               GET IN ACC(BREG,1,2,LNB,JJ+8);                          
               KK=MODD
               %IF PREC=4 %THEN PF1(ADB,0,BREG,0) %AND KK=INCA
               PSF1(LD,1,JJ)
               PF1(KK,0,BREG,0);      ! ADJUST DESCRPTR
               PSF1(STD,1,JJ)
               GRUSE(DR)=0; GRUSE(ACCR)=0
               GRUSE(BREG)=0; AREA=LNB; DISP=JJ
            %FINISH
            %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
         %FINISH
S(12):                                  ! ARRAYS IN RECORDS BY NAME
         ->CHKEN
FUNNY(13):                              ! LOAD ADDR FOR RT-TYPE
         %IF PTYPE=SNPT %THEN CSNAME(Z,REG) %AND P=P+1 %AND->CHKEN
         DISP=FROM1(K); BASE=I
         %IF NAM&1#0 %THEN %START
            AREA=-1
            GET IN ACC(REG,4,0,AREA CODE,DISP)
         %FINISH %ELSE %START
            %IF J=14 %THEN %START;      ! EXTERNAL ROUTINE PASSED
               GET IN ACC(REG,2,0,0,0); ! ZERO ENVIRONMENT
               GET IN ACC(DR,2,0,SET XORYNB(-1,-1),DISP)
!               PSF1(MODD,0,0);          ! PROVOKE ESCAPE IF DYNAMIC
            %FINISH %ELSE %START
               %IF BASE=0 %AND CPRMODE=2 %START;! IN FILE OF RTS
                  PSF1(LD,1,12)
                  PSF1(INCA,0,DISP) %UNLESS DISP=0
                  GET IN ACC(ACCR,2,0,0,0)
               %FINISH %ELSE %START
                  PSF1(JLK,0,1);           ! GET PC TO TOS
                  RTJUMP(LDA,ASLIST(K)_S1);     ! ADD N TO POINT @ ENTRY
                  PF1(INCA,0,TOS,0);       ! AND TO DES REG
                  JJ=X'E0000001'
                  STORE CONST(JJJ,4,ADDR(JJ))
                  PF1(LDTB,0,PC,JJJ)
                  GET IN ACC(ACCR,1,0,LNB,PTR OFFSET(BASE))
                  PSF1(LUH,0,0);           ! SPARE FIELD IN RT HDDR
               %FINISH
            %FINISH
            PF1(STD,0,TOS,0);           ! DR TO TOP OF STACK
            PF1(LUH,0,TOS,0);           ! AND TO TOP 64 BITS OF ACC
            GRUSE(DR)=0
         %FINISH
         %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP; ->CHKEN
SW(3):                                 ! RECORD
         CRNAME(Z, REG, 2*NAM, I, -1, K, NAMEP)
         ->S(Z) %IF Z>=10
         STNAME=-1 %IF Z=1 %OR Z=6
         ->STRINREC %IF TYPE=5 %AND Z#6
         ->NOT SET %IF TYPE=7
         NAMEOP(Z,REG,BYTES(PREC),NAMEP)
         ->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; AREA=-1; DISP=K
SNINREC:         %IF Z=1 %THEN Z=3;     ! STRINGNAMES IN RECORDS
         %IF Z=3 %OR Z=4 %THEN NAMEOP(Z,REG,8,-1) %AND ->CHKEN
         %IF ACCESS=2 %AND PARMCHK=0 %AND REGISTER(DR)=0 %START
            PSORLF1(LDB,2,AREA CODE,DISP);! LOAD BND & DR IN 1 INSTRN
            GRUSE(DR)=0
            %IF REG=ACCR %THEN COPY DR
            ->CHKEN
         %FINISH
         NAMEOP(3,DR,8,-1)
MBND:    %IF PARMCHK=1 %THEN TEST ASS(DR,5,8)
         PF1(LDB,2,7,0);                ! LBOUND FIRST BYTE=CURRENT L
         %IF REG=ACCR %THEN COPY DR
         ->CHKEN
STRARR:                                 ! STRINGARRAYS &  ARRAYNAMES
         CANAME(ARR, I, K)
SAINREC:                                ! STRING ARRAYS IN RECORDS
         %IF Z=1 %OR Z=3 %THEN %START
            %IF NAM=1 %THEN %START
               PSF1(INCA,0,-8);         ! DR TO SIZE ITEM IN DV
               PF1(SLB,2,7,0);          ! STACK MODIFIER FETCH SIZE
!               PSF1(SBB,0,1);           ! REMOVE CURR LENGTH BYTE
            %FINISH
            GET IN ACC(DR,2,0,AREA CODE,DISP)%IF AREA#7;! ALREADY IN DR
            %IF NAM=1 %THEN %START
               PF1(MODD,0,TOS,0)
               PF1(LDB,0,BREG,0)
            %FINISH %ELSE %START
               PF1(MODD,0,BREG,0)
               PSF1(LDB,0,ACC)
            %FINISH
            %IF REG=ACCR %THEN COPY DR
            ->CHKEN
         %FINISH
         %IF Z=4 %THEN ACCESS=3 %AND NAMEOP(Z,REG,4,-1) %AND ->CHKEN
                                        ! SPECIAL FOR Z=4 IN CRNAME !
         GET IN ACC(DR,2,0,AREA CODE,DISP) %UNLESS AREA=7
         PF1(MODD,0,BREG,0)
         ->MBND
STRINREC:                               ! STRINGS IN RECORDS
         ->SAINREC %IF ARR#0
         ->SNINREC %IF NAM#0 %OR Z=4
!
! STRINGS IN RECORDS HAVE NO HEADER AND ARE SPECIAL
!
         NAMEOP(4,BREG,4,-1)
         PF1(LDTB,0,PC,PARAM DES(3))
         PF1(LDA,0,BREG,0)
         PSF1(LDB,0,ACC) %UNLESS Z=2 %AND PARMCHK=0
         GRUSE(DR)=0
         ->MBND %IF Z=2
         COPY DR %IF REG=ACCR
         ->CHKEN
!
! SECTION TO DEAL WITH ALL NAMES INVOLVING ROUTINE CALL
!
RTCALL:                                 ! FIRST CHECK
         %IF TYPE=0 %AND Z#0 %THEN FAULT(23, FNAME) %AND ->NOT SET
                                        ! RT NAME IN EXPRSN
         %IF PTYPE=SNPT %THEN %START
            CSNAME(Z, REG);             ! SPECIAL NAME
            ->BIM %IF ROUT=1 %AND NAM>=1 %AND Z#0
            %IF TYPE#0 %AND NEST=ACCR %THEN ->MVFNRES
            P=P+1; ->CHKEN
         %FINISH
         %IF FROM2(K)=1000 %THEN FAULT(21, FNAME) %AND ->NOT SET
                                        ! USE BEFORE %SPEC GIVEN
         CRCALL(FNAME);  P=P+1;         ! DEAL WITH PARAMS
         ->CHKEN %IF PTYPE&15=0
         ->UDM %IF NAM>1;               ! MAPS
         %UNLESS Z=2 %OR Z=5 %THEN %START;   ! FUNCTIONS
            FAULT(29, FNAME);  BASE=0
            ACCESS=0;  DISP=0
         %FINISH
MVFNRES: %IF TYPE=5 %THEN %START;       ! STRING FNS
            %IF REG=DR %THEN PF1(ST,0,TOS,0) %AND PF1(LD,0,TOS,0)
         %FINISH %ELSE %START
            %IF REG=BREG %THEN PF1(ST,0,BREG,0)
         %FINISH
         NEST=REG; ->CHKEN
UDM:                                    ! USER DEFINED MAPS
         PF1(ST,0,BREG,0);              ! RETURN 32 BIT ADDR IN ACC
         DISP=MAPDES(PREC)
         ACCESS=3; AREA=PC
         NAMEP=-1
BIM:                                    ! BUILT IN MAPS
         NAMEP=-1 %UNLESS AREA=PC %AND ACCESS=3
         ->CHKEN %IF TYPE=3;            ! MAP RECORD USE VERY LIMITED
         %IF Z=3 %OR (TYPE=5 %AND Z#4) %START
            PF1(LDTB,0,PC,DISP)
            %IF TYPE=5 %AND (PARMCHK#0 %OR Z#2) %THEN PSF1(LDB,0,255)
            PF1(LDA,0,BREG,0)
            GRUSE(DR)=0
         %FINISH %ELSE %START
            %IF GRUSE(DR)=7 %AND GRINF(DR)=NAMEP>0 %AND 1<=Z<=2 %C
               %THEN AREA=7;            ! CHANGE TO(%DR+%B) FORM
         %FINISH
         NAM=0
         KK=Z; KK=2 %IF Z=5
         ->MAP(KK&3)
MAP(0):                                 ! FETCH ADDRESS
         %IF REG#BREG %THEN GETINACC(ACCR,1,0,BREG,0)
         ->CHKEN
MAP(1):                                 ! STORE
         ->CHKEN %UNLESS TYPE=5; ->MAP(3)
MAP(2):                                 ! FETCH
         %IF TYPE=5 %THEN ->MBND
         GET IN ACC(REG,BYTES(PREC)>>2,ACCESS,AREA,DISP)
         %IF NAMEP>0 %THEN GRUSE(DR)=7 %AND GRINF(DR)=NAMEP
         %IF PARMCHK=1 %AND PREC>=5 %THEN TEST ASS(REG,1,BYTES(PREC))
         ->CHKEN
MAP(3):                                 ! SET DESCRIPTOR
         %IF TYPE=5 %THEN PF1(LDB,0,0,256)
         COPY DR %UNLESS REG=DR
         ->CHKEN
SW(0):                                  ! %NAME PARAMETERS NO TYPE
                                        ! ALLOW FETCH ADDR OPERATIONS
                                        ! AND SPECIAL FOR BUILTIN MAPS
         %UNLESS 3<=Z<=4 %THEN %START
            FAULT(12, 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; AREA=-1
            %IF A(P+2)=2 %THEN P=P+3 %ELSE NO APP
         %FINISH %ELSE %START
            CANAME(ARR, I, K)
            NAM=0
         %FINISH
         NAMEOP(Z,REG,BYTES(PREC),NAMEP)
         ->CHKEN
!
                                        ! GENERAL FETCHING & STORING 
                                        !SECTION
!
CHKEN:   %WHILE A(P)=1 %CYCLE
            FAULT(69,FNAME)
            P=P+3; SKIP APP
         %REPEAT
         P=P+1
%END
%ROUTINE NAMEOP(%INTEGER Z,REG,SIZE,NAMEP)
!***********************************************************************
!*    FETCH OR STORE REG FROM OR TO VARIABLE DEFINED BY AREA ACCESS    *
!*    BASE AND DISP.                                                   *
!***********************************************************************
%SWITCH MOD(0:47)
%INTEGER KK,JJJ,TOTHER,XYNB,JJ,OP1,OP2
         KK=Z; KK=2 %IF Z=5
         %IF Z=6 %THEN %START
            FAULT(17,0) %UNLESS NAM=1 %AND ROUT=0 %AND %C
                        (ACCESS>=8 %OR ACCESS=2)
            KK=1; SIZE=8
            %IF ACCESS>=8 %THEN ACCESS=ACCESS-4 %ELSE ACCESS=0
         %FINISH
         KK=KK&3
         ->MOD(ACCESS<<2!KK)
!
! AREA AND ACCESS
! **** *** ******
! THESE VARIABLES DEFINE HOW TO ACCESS ANY IMP VARIABLE. AREA HAS THE
! THREE BIT AREA CODE FROM THE PRIMARY FORMAT INSTRN.(EG 6=TOS ETC)
! THE SPECIAL CASE AREA=-1 IS USED FOR ENTITIES IN STACK FRAME 'BASE'
! THE FN AREA CODE CONVERTS THIS CASE TO AREA=LNB OR AREA=XNB ARRANGING
! TO LOAD XNB IF NECESSARY.
!
! ACCESS HAS TWO VERSIONS OF THE 2-BIT INDIRECTION CODE FROM PRIMARY
! FORMAT INSTRNS:-
! =0 VARIABLE DIRECTLY ADDRESSED IN 'AREA' BY 'DISP'
! =1 VARIABLE ADDRESSED BY DR MODIFIED BY 'AREA' & 'DISP'
! =2 DESCRIPTOR TO VARIABLE DIRECTLY ADDRESS BY 'AREA' & 'DISP'
! =3 DESCRIPTOR AS IN =2 IS TO BE MODIFIED BY 'B'
! =4 VARIABLE 'XDISP' INTO RECORD DIRECTLY ADDRESSED BY 'AREA' & 'DISP'
! =5 VARIABLE 'XDISP' INTO RECORD ADDRESSED BY DR MODIFIED AS =1
! =6 VAR 'XDISP' INTO RECORD ADDRESSED BY DESCRIPTOR AT 'AREA' & 'DISP'
! =7 AS =6 BUT DESCRIPTOR MODIFIED BY B
! =8-11 AS 4-7 BUT THERE IS A DESCRIPTOR TO ITEM AT 'XDISP' INTO RECORD
!
! THESE COVER ALL THE COMMON CASES. ITEMS LIKE ARRAYS IN RECORD ARRAYS
! NEED AN INTERMEDIATE DESCRIPTOR TO BE CALCULATED AND(USUALLY) STACKED
!
MOD(0):                                 ! ACCESS=0 FETCH ADDRESS
         %IF TYPE=3 %THEN GETINACC(REG,1,0,AREA CODE,DISP-4) %ANDRETURN
         GET IN ACC(REG,1,0,LNB,PTR OFFSET(BASE))
         %IF REG=BREG %THEN JJJ=ADB %ELSE JJJ=IAD
         PSF1(JJJ,0,DISP)
         %IF BIMSTR=1 %THEN NOTE ASSMENT(REG,3,NAMEP)
         %RETURN
MOD(1):                                 ! ACCESS=0 STORE
         %IF 1<=SIZE<=2 %THEN %START;   ! BYTES & HALFS REQUIRE DESCRIPTOR
            PF1(LDTB,0,PC,MAP DES(SIZE+2)) %UNLESS GRUSE(DR)=SIZE+11
            PSF1(LDA,1,PTR OFFSET(BASE)) %C
               %UNLESS 12<=GRUSE(DR)<=13 %AND GRINF(DR)=BASE
            GRUSE(DR)=SIZE+11; GRINF(DR)=BASE
            ACCESS=1; AREA=0
         %FINISH %ELSE AREA=AREA CODE
         %RETURN
MOD(2):                                 ! ACCESS=0 FETCH
         %IF SIZE>2 %AND Z=5 %AND PARMCHK=0 %THEN NEST=-1 %AND %RETURN
MOD(10):                                ! ACCESS=2 FETCH
         %IF GRUSE(REG)=9 %AND NAMEP>0 %THEN %START
            %IF GRINF(REG)&X'FFFF'=NAMEP %OR GRINF(REG)>>16=NAMEP %START
               %IF REGISTER(REG)#0 %THEN BOOT OUT(REG)
               NEST=REG; %RETURN
            %FINISH
         %FINISH
         TOTHER=REG!!7
         %IF GRUSE(TOTHER)=9 %AND NAMEP>0 %START
            KK=GRINF(TOTHER)
            %IF KK&X'FFFF'=NAMEP %OR KK>>16=NAMEP %START
               %IF REG=BREG %AND REGISTER(BREG)=0 %START
                  PF1(ST,0,BREG,0);        ! ACC TO BRGE
                  GRUSE(REG)=9; GRINF(REG)=KK
                  NEST=REG
                  %RETURN
               %FINISH
               %IF REG=ACCR %AND Z=2 %THEN %START
                  ACCESS=0; AREA=7
                  SIZE=4; DISP=0
               %FINISH
            %FINISH
         %FINISH
         %IF 1<=SIZE<=2 %AND ACCESS=0 %THEN %START;       ! BYTES
            PF1(LDTB,0,PC,MAP DES(SIZE+2)) %UNLESS GRUSE(DR)=SIZE+11
            PSF1(LDA,1,PTR OFFSET(BASE)) %C
               %UNLESS 12<=GRUSE(DR)<=13 %AND GRINF(DR)=BASE
            GRUSE(DR)=SIZE+11; GRINF(DR)=BASE
            %IF Z=5 %AND PARMCHK=0 %START
               ACCESS=1; AREA=0; NEST=-1; %RETURN
            %FINISH
            GET IN ACC(REG,1,1,0,DISP)
            %IF PARMCHK#0 %AND SIZE=2 %THEN TEST ASS(REG,TYPE,SIZE)
            NEST=REG; %RETURN
         %FINISH
MOD(6):                                 ! ACCESS=1 FETCH
MOD(14):                                ! ACCESS=3 FETCH
         %IF ACCESS>=2 %AND GRUSE(DR)=7 %AND GRINF(DR)=NAMEP>0 %THEN %C
            AREA=7 %AND DISP=0 %ELSE AREA=AREA CODE
         GET IN ACC(REG,SIZE>>2,ACCESS,AREA,DISP)
         %IF PARMCHK=1 %AND SIZE#1 %THEN TEST ASS(REG,TYPE,SIZE)
          %IF (ACCESS=0 %OR ACCESS=2) %AND NAMEP>0 %THEN %C
            GRUSE(REG)=9; GRINF(REG)=NAMEP
         %IF ACCESS>=2 %AND NAMEP>0 %THEN %C
            GRUSE(DR)=7 %AND GRINF(DR)=NAMEP
         NEST=REG; %RETURN
MOD(3):                                 ! ACCESS=0 SET DESCRIPTOR
         ABORT %UNLESS REG=ACCR %OR REG=DR
         %IF TYPE=3 %THEN %START
!            JJ=X'18000000'+ACC
!            STORE CONST(JJJ,4,ADDR(JJ))
            GET IN ACC(REG,2,0,AREA CODE,DISP-8);! PTR BEFORE START
            %RETURN
         %FINISH %ELSE JJJ=PARAM DES(PREC)
!
         %IF REG=ACCR %THEN %START
            GET IN ACC(REG,1,0,LNB,PTR OFFSET(BASE))
            OP1=IAD; OP2=LUH
         %FINISH %ELSE %START
            PSF1(LDA,1,PTR OFFSET(BASE))
            OP1=INCA; OP2=LDTB
         %FINISH
         PSF1(OP1,0,DISP)
         PF1(OP2,0,PC,JJJ)
         GRUSE(REG)=0
         %RETURN
MOD(4):                                 ! ACCESS=1 FETCH ADDRESS
MOD(7):                                 ! ACCESS=1 SET DESCRIPTOR
         PSORLF1(INCA,0,AREA CODE,DISP) %UNLESS AREA=0=DISP
         COPY DR
         PSF1(MPSR,0,X'11') %IF KK=4;   ! HALVE ACC SIZE
         %RETURN
MOD(5):                                 ! ACCESS=1 STORE
         AREA=AREA CODE; %RETURN
MOD(12):                                ! ACCESS=3 FETCH ADDRESS
         JJJ=BYTES(PREC)
         PSF1(MYB,0,JJJ) %AND GRUSE(BREG)=0 %UNLESS JJJ=1
MD12:    %IF REG=BREG %THEN %START
            PF1(ADB,0,AREA CODE,DISP+4)
            GRUSE(BREG)=0
            %RETURN
         %FINISH
MOD(8):                                 ! ACCESS=2 FETCH ADDRESS
         GET IN ACC(REG,1,0,AREA CODE,DISP+4)
         %IF ACCESS&3=3 %THEN PF1(IAD,0,BREG,0)
         %RETURN
MOD(9):                                 ! ACCESS=2 STORE
MOD(13):                                ! ACCESS=3 STORE
         %IF GRUSE(DR)=7 %AND GRINF(DR)=NAMEP>0 %THEN %C
            AREA=7 %AND DISP=0 %ELSE AREA=AREA CODE
         %RETURN
MOD(11):                                ! ACCESS=2 SET DESCRIPTOR
         %IF AREA=7 %THEN %START
            COPY DR %UNLESS REG=DR
            %RETURN
         %FINISH
         GET IN ACC(REG,2,0,AREA CODE,DISP)
         %RETURN
MOD(15):                                ! ACCESS=3 SET DESCRIPTOR
         GET IN ACC(DR,2,0,AREA CODE,DISP) %UNLESS AREA=7
         %IF PREC=4 %THEN JJ=INCA %ELSE JJ=MODD
         PF1(JJ,0,BREG,0)
         %IF REG#DR %THEN COPY DR
         GRUSE(DR)=0
         %RETURN
MOD(17):                                ! ACCESS=4 STORE
MOD(18):                                ! ACCESS=4 FETCH
         %IF SIZE=1 %THEN DISP=DISP-8 %AND ->MD2526
         DISP=DISP+XDISP
         ACCESS=0; NAMEP=0
         ->MOD(KK);                   ! REDUCES TO ACCESS=0
MOD(20):                                ! ACCESS=5 FETCH ADDRESS
MOD(21):                                ! ACCESS=5 STORE
MOD(22):                                ! ACCESS=5 FETCH
MOD(23):                                ! ACCESS=5 SET DESCRIPTOR
MOD(36):                                ! ACCESS=9 FETCH ADDRESS
MOD(37):                                ! ACCESS=9 STORE
MOD(38):                                ! ACCESS=9 FETCH
MOD(39):                                ! ACCESS=9 SET DESCRIPTOR
         ABORT
MOD(16):                                ! ACCESS=4 FETCH ADDRESS
         DISP=DISP-8
MOD(24):                                ! ACCESS=6 FETCH ADDRESS
         GET IN ACC(REG,1,0,AREA CODE,DISP+4)
         %IF REG=BREG %THEN KK=ADB %ELSE KK=IAD
         PSF1(KK,0,XDISP) %UNLESS XDISP=0
         %RETURN
MD2526:
MOD(25):                                ! ACCESS=6 STORE
MOD(26):                                ! ACCESS=6 FETCH
         %IF SIZE>2 %START
            XYNB=XORYNB(8,NAMEP)
            PSORLF1(LDCODE(XYNB),0,AREA CODE,DISP+4) %UNLESS %C
               GRUSE(XYNB)=8 %AND GRINF(XYNB)=NAMEP>0
            GRUSE(XYNB)=0
            %IF NAMEP>0 %THEN %C
               GRUSE(XYNB)=8 %AND GRINF(XYNB)=NAMEP %AND GRAT(XYNB)=CA
            AREA=XYNB; ACCESS=0
         %FINISH %ELSE %START
            PSORLF1(LD,0,AREA CODE,DISP) %UNLESS %C
               GRUSE(DR)=7 %AND GRINF(DR)=NAMEP>0
            GRUSE(DR)=0
            %IF SIZE=2 %THEN PF1(LDTB,0,PC,MAP DES(4)) %ELSE %START
               %IF NAMEP>0 %THEN GRUSE(DR)=7 %AND GRINF(DR)=NAMEP
            %FINISH
            ACCESS=1; AREA=0
         %FINISH
         DISP=XDISP; NAMEP=0
         ->MOD(ACCESS<<2!KK)
MOD(19):                                ! ACCESS=4 SET DESCRIPTOR
         DISP=DISP-8
MOD(27):                                ! ACCESS=6 SET DESCRIPTOR
MOD(31):                                ! ACCESS=7 SET DESRCPTOR
         GET IN ACC(DR,2,0,AREA CODE,DISP)
         PSF1(INCA,0,XDISP) %UNLESS XDISP=0
         PF1(INCA,0,BREG,0) %IF ACCESS=7
         %IF TYPE=3 %OR TYPE=5 %THEN JJJ=3 %ELSE JJJ=PREC
         PF1(LDTB,0,PC,PARAM DES(JJJ))
         %IF TYPE=3 %OR TYPE=5 %THEN PSORLF1(LDB,0,0,ACC)
         %IF REG#DR %THEN COPY DR
         %RETURN
MOD(28):                                ! ACCESS=7 FETCH ADDRESS
         PSF1(ADB,0,XDISP) %AND GRUSE(BREG)=0 %UNLESS XDISP=0
         ACCESS=3; ->MD12
MOD(29):                                ! ACCESS=7 STORE
MOD(30):                                ! ACCESS=7 FETCH
         %IF 1<=SIZE<=2 %THEN %START
            PSORLF1(LD,0,AREA CODE,DISP)
            GRUSE(DR)=0
            %IF SIZE=2 %THEN PF1(LDTB,0,PC,MAPDES(4))
            PF1(INCA,0,BREG,0)
            ACCESS=1; AREA=0
         %FINISH %ELSE %START
            PSORLF1(ADB,0,AREA CODE,DISP+4)
            GRUSE(BREG)=0
            XYNB=XORYNB(0,0)
            PF1(LDCODE(XYNB),0,BREG,0)
            GRUSE(XYNB)=0
            AREA=XYNB; ACCESS=0
         %FINISH
         NAMEP=0
         DISP=XDISP; ->MOD(ACCESS<<2!KK)
MOD(32):                                ! ACCESS=8 FETCH ADDRESS
MOD(33):                                ! ACCESS=8 STORE
MOD(34):                                ! ACCESS=8 FETCH
MOD(35):                                ! ACCESS=8 SET DESCRIPTOR
         DISP=DISP+XDISP
         NAMEP=0
         ACCESS=2; ->MOD(KK+8)
MOD(40):                                ! ACCESS=10 FETCH ADDRESS
MOD(41):                                ! ACCESS=10 STORE
MOD(42):                                ! ACCESS=10 FETCH
MOD(43):                                ! ACCESS=10 SET DESCRIPTOR
         %IF NAMEP>0 %THEN XYNB=XORYNB(8,NAMEP) %ELSE XYNB=XORYNB(0,0)
         PSORLF1(LDCODE(XYNB),0,AREA CODE,DISP+4) %UNLESS %C
            GRUSE(XYNB)=8 %AND GRINF(XYNB)=NAMEP>0
         GRUSE(XYNB)=0
         %IF NAMEP>0 %THEN GRUSE(XYNB)=8 %AND GRINF(XYNB)=NAMEP
         AREA=XYNB; ACCESS=2; DISP=XDISP
         NAMEP=0
         ->MOD(KK+8)
MOD(44):                                ! ACCESS=11 FETCH ADDRESS
MOD(45):                                ! ACCESS=11 STORE
MOD(46):                                ! ACCESS=11 FETCH
MOD(47):                                ! ACCESS=11 SET DESCRIPTOR
         PSORLF1(ADB,0,AREA CODE,DISP+4)
         XYNB=XORYNB(0,0)
         PF1(LDCODE(XYNB),0,BREG,0)
         GRUSE(XYNB)=0
         NAMEP=0; AREA=XYNB
         ACCESS=2; DISP=XDISP; ->MOD(KK+8)
%END
         %ROUTINE CRCALL(%INTEGER RTNAME)
!***********************************************************************
!*       COMPILE A ROUTINE OR FN CALL                                  *
!*       THE PROCEDURE CONSIST OF THREE PARTS:-                        *
!*       A) PLANT THE PARAMETER (IF ANY)                               *
!*       B) ENTER THE ROUTINE OR FN                                    *
!*       C) FORGET ANY REGISTERS WHICH HOLD ENTITIES THAT CAN BE       *
!*          ALTERED BY THE CALLED PROCEDURE.                           *
!***********************************************************************
%SWITCH FPD(0:3)
%INTEGER II,III,QQQ,DLINK,JJ,JJJ,NPARMS,PT,LP,PSIZE, %C
         FPTR,TYPEP,PRECP,NAMP,TL,MOVEPTR,CLINK,RDISP
%RECORDNAME LCELL(LISTF)
         PT=PTYPE; JJJ=J; TL=OLDI
         LP=I; CLINK=K; DLINK=CLINK
         TYPEP=TYPE; PRECP=PREC; NAMP=NAM
         LCELL==ASLIST(CLINK)
         RDISP=LCELL_S1
!
! NOW CHECK THAT THE RIGHT NUMBER OF PARAMETERS HAVE BEEN PROVIDED
!
         TEST APP(NPARMS)
         P=P+2
         %IF LCELL_S2#NPARMS %THEN %START
            FAULT(19,RTNAME);          ! WRONG NO OF PARAMETERS GIVEN
            SKIP APP; P=P-1
            %RETURN
         %FINISH
!
         SAVE IRS;                      ! STACK ANY IRS BEFORS ASF
         PSF1(PRCL,0,4)
         FPTR=20
         -> ENTRY SEQ %IF NPARMS=0;    ! NO PARAMETERS TO BE PLANTED
!
NEXT PARM:CLINK=LCELL_LINK
         ->ENTRY SEQ %IF CLINK=0
         LCELL==ASLIST(CLINK)
         PSIZE=LCELL_S2>>16
         P=P+1
         PTYPE=LCELL_S1
         UNPACK
         II=TYPE;III=PREC
         JJ=(NAM<<1!ARR)&3
         %UNLESS (JJ=0 %AND ROUT=0) %OR %C
           (A(P+3)=4 %AND A(P+4)=1 %AND A(P+FROMAR2(P+1)+1)=2) %START
            FAULT(22,0); SKIP EXP
            ->NEXT PARM
         %FINISH
!
! RT TYPE PARAMS, PASS 4 WORDS SET UP AS CODE DESC,DUMMY & ENVIRONMENT
!
         %IF ROUT=1 %THEN %START
            II=PTYPE; P=P+5
            CNAME(13,ACCR);            ! SET UP 4 WDS IN ACC
            FAULT(22,0) %IF II&255#PTYPE&255;! PREC&TYPE SIMILAR
            P=P+1; MOVEPTR=16
            ->STUFF
         %FINISH
         ->FPD(JJ)
FPD(0):                                ! VALUE PARAMETERS
         %IF TYPE=5 %THEN %START
            CSTREXP(17,DR);             ! TO WK AREA & KEEP WK AREA
            PSF1(LDB,0,PSIZE)
            %IF REGISTER(ACCR)=3 %THEN PF1(ST,0,TOS,0) %C
                  %AND REGISTER(ACCR)=0
            PF1(STD,0,TOS,0)
            PUSH(TWSPHEAD,VALUE,268,0);   ! RETURN WK AREA AT STMNT END
            FPTR=FPTR+8; ->NEXT PARM
         %FINISH %ELSE %START
            %IF PREC=6 %THEN JJ=3 %ELSE JJ=TYPE
            CSEXP(ACCR,III<<4!II)
            MOVEPTR=((BYTES(III)+3)&(-4))
         %FINISH
         ->STUFF
!
FPD(2):                                ! NAME PARAMETERS
         P=P+5
         FNAME=FROM AR2(P)
         COPY TAG(FNAME)
         %IF II#0 %OR TYPE=0 %START
            CNAME(3,ACCR)
            FAULT(22,FNAME) %UNLESS II=TYPE %AND III=PREC
         %FINISH %ELSE %START
            CNAME(4,ACCR)
            %IF TYPE<=2 %THEN JJ=PREC<<27!TYPE %ELSE JJ=X'1A'<<24+ACC
            STORE CONST(III,4,ADDR(JJ))
            PF1(LUH,0,PC,III)
         %FINISH
         P=P+1; MOVEPTR=8
         ->STUFF
!
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
         CNAME(12,ACCR)
         GET IN ACC(ACCR,4,0,AREA CODE,DISP)
         P=P+1; MOVEPTR=16
         FAULT(22,0) %AND ->STUFF %UNLESS 1<=ARR<=2 %AND %C
                  II=TYPE %AND III=PREC
         QQQ=FROM1(TCELL)&15;       ! DIMENSION OF ACTUAL(IF KNOWN)
         JJ=LCELL_S3;               ! DIMENSION OF FORMAL
         %IF JJ=0 %THEN JJ=QQQ %AND LCELL_S3=JJ
         %IF QQQ=0 %THEN QQQ=JJ %AND REPLACE1(TCELL,FROM1(TCELL)!JJ)
         FAULT(22,0) %UNLESS JJ=QQQ
STUFF:   REGISTER(ACCR)=3
         FPTR=FPTR+MOVEPTR
         -> NEXT PARM
ENTRY SEQ:                             ! CODE FOR RT ENTRY
         %IF REGISTER(ACCR)=3 %THEN %C
            PF1(ST,0,TOS,0) %AND REGISTER(ACCR)=0
         J=JJJ
!
! STRING FNS NEED A WORK AREA TO RETURN THEIR RESULTS
!
         %IF TYPEP=5 %AND NAMP<=1 %THEN %START
            GET WSP(QQQ,268)
            RETURN WSP(QQQ,268);        ! SAFE AS STRING IMMEDIATLY COPIED
            III=X'18000100'; QQQ=QQQ+8
            STORE CONST(JJ,8,ADDR(III))
            PF1(LD,0,PC,JJ)
            PSF1(INCA,1,PTR OFFSET(RBASE))
            PF1(STD,0,TOS,0)
            FPTR=FPTR+8
         %FINISH
!
! ORDINARY ROUTINES WILL AND RT PARAMS MAY REQUIRE AN EXTRA PARAMETER
! BEING LNB FOR THE LEVEL OF ROUTINE DECLARATION TO BE STACKED
!
         %IF JJJ=14 %THEN %START;    ! EXTERNAL
            NMDECS(LEVEL)=NMDECS(LEVEL)!2
            II=SET XORYNB(-1,-1)
            PSF1(RALN,0,FPTR>>2)
            PF1(CALL,2,II,RDISP)
         %FINISH %ELSE %START
            %IF NAMP&1=0 %THEN %START;! INTERNAL RT CALLS
               %IF LP=0 %THEN %START
                  PSF1(LD,1,12)
                  PSF1(INCA,0,RDISP) %UNLESS RDISP=0
                  PSF1(RALN,0,FPTR>>2)
                  PF1(CALL,2,7,0)
               %FINISH %ELSE %START;! NORMAL INTERNAL CALL
                  II=SET XORYNB(XNB,LP)
                  PSF1(RALN,0,FPTR>>2)
                  RT JUMP(CALL,ASLIST(DLINK)_S1)
               %FINISH
            %FINISH %ELSE %START
               AREA=-1; BASE=LP
               AREA=AREA CODE
               GET IN ACC(DR,2,0,AREA,RDISP);! DESCR TO DR
               PSORLF1(LXN,0,AREA,RDISP+12);! XNB TO ENVIRONMENT
               PSF1(RALN,0,FPTR>>2);    ! RAISE FOR NORMAL PARAMS
               PF1(CALL,2,7,0)         ;! AND ENTER VIA DESCRPTR IN DR
            %FINISH
         %FINISH
         FORGET(-1)
         ROUT=1; TYPE=TYPEP; NAM=NAMP
         PREC=PRECP; PTYPE=PT
         %END
%ROUTINE RT JUMP(%INTEGER CODE,%INTEGERNAME LINK)
!***********************************************************************
!*       PLANTS A CALL TO THE APPROPIATE ENTRY ADDRESS IN LINK         *
!*       IF ROUTINE HAS BEEN SPECIFIED BUT NOT DESCRIBED THE JUMP CAN  *
!*       NOT BE PLANTED AND IS LINKED INTO A LIST HEADED BY LINK       *
!*       TO AWAIT FILLING (BY ' RHEAD ') WHEN THE BODY IS GIVEN.       *
!*       THE FORMAT OF AN ENTRY IS :-                                  *
!*       S1(32 BITS) = INSTRN TO BE PLANTED                            *
!*       S2(32 BITS) = ADDRESS OF JUMP TO BE FILLED                    *
!*       THE CODING ASSUMES I,J&OLDI ARE SET UP FOR THE CALLED ROUTINE *
!***********************************************************************
%INTEGER DP
         %IF J=15 %THEN %START;        ! RT BODY NOT GIVEN YET
            PUSH(LINK,CODE<<24!3<<23,CA,0)
            PF1(CODE,0,0,0)
         %FINISH %ELSE %START;          ! BODY GIVEN AND ADDRESS KNOWN
            DP=LINK-CA
            DP=DP//2 %IF CODE=CALL;    ! CALL WORKS IN HALFWORDS!
            PSF1(CODE,0,DP)
         %FINISH
%END
%INTEGERFN TSEXP(%INTEGERNAME VALUE)
%SWITCH SW(1:3)
%INTEGER PP,REXP,KK,SIGN,CT
         TYPE=1; PP=P
         REXP=2-A(P+1+FROM AR2(P+1))
         P=P+3
         SIGN=A(P)
         ->TYPED %UNLESS SIGN=4 %OR A(P+1)=2
         ->SW(A(P+1))
SW(1):                                  ! NAME
         P=P+2; REDUCE TAG
         ->TYPED
SW(2):                                  ! CONSTANT
         CT=A(P+2); TYPE=CT&7
         ->TYPED %UNLESS CT=X'51' %AND SIGN#3
         KK=FROMAR4(P+3)
         %IF REXP#0 %AND A(P+8)=CONCOP %THEN TYPE=5 %AND ->TYPED
         ->TYPED %UNLESS REXP=0 %AND 0<=KK<=255
         VALUE=KK
         P=P+8
         %IF SIGN#2 %THEN %RESULT=1
          VALUE=-VALUE; %RESULT=-1
SW(3):                                  ! SUB EXPRN
TYPED:   P=PP; %RESULT=0
%END
%ROUTINE SKIP EXP
!***********************************************************************
!*       SKIPS OVER THE EXPRESSION POINTED AT BY P. USED FOR ERROR     *
!*       RECOVERY AND TO EXTRACT INFORMATION ABOUT THE EXPRESSION.     *
!***********************************************************************
%INTEGER OPTYPE, PIN, J
         PIN=P
         P=P+3;                         ! TO P<+'>
         %CYCLE;                        ! DOWN THE LIST OF OPERATORS
           OPTYPE=A(P+1);               ! ALT OF P<OPERAND>
           P=P+2
           %IF OPTYPE=0 %OR OPTYPE>3 %THEN ABORT
           %IF OPTYPE=3 %THEN SKIP EXP; ! SUB EXPRESSIONS
!
           %IF OPTYPE=2 %THEN %START;   ! OPERAND IS A CONSTANT
              J=A(P)&7;                 ! CONSTANT TYPE
              %IF J=5 %THEN P=P+A(P+5)+6 %ELSE P=P+1+BYTES(A(P)>>4)
           %FINISH
!
           %IF OPTYPE=1 %THEN %START;   ! NAME
              P=P-1
              %UNTIL A(P)=2 %THEN P=P+3 %AND SKIP APP;! 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
         %WHILE A(P)=1 %THEN P=P+1 %AND SKIP EXP
         P=P+1
          %END
         %ROUTINE NO APP
            P=P+2
            %IF A(P)=1 %THEN %START;    ! <APP> PRESENT
               FAULT(19,FROM AR2(P-2))
               SKIP APP
            %FINISH %ELSE P=P+1;         ! P NOW POINTS TO ENAME
         %END
%ROUTINE TEST APP(%INTEGERNAME NUM)
!***********************************************************************
!*       THIS ROUTINE COUNTS THE NUMBER OF ACTUAL PARAMETERS           *
!*       WHICH IT RETURNS IN NUM.                                      *
!***********************************************************************
%INTEGER PP, Q
         Q=0;  PP=P;  P=P+2;            ! P ON NAME AT ENTRY
         %WHILE A(P)=1 %CYCLE;          ! NO (MORE) PARAMETERS
            P=P+1;  Q=Q+1
            SKIP EXP
         %REPEAT
         P=PP;  NUM=Q
%END
%ROUTINE TEST ASS(%INTEGER REG,TYPE,SIZE)
!***********************************************************************
!*       TEST ACC OR B FOR THE UNASSIGNED PATTERN                      *
!***********************************************************************
%INTEGER OPCODE,A,D
         %IF TYPE=5 %THEN %START
            ABORT %UNLESS REG=DR
            PF1(STD,0,TOS,0)
            PF2(SWEQ,1,1,0,0,UNASSPAT&255)
         %FINISH %ELSE %START
            %IF REG=BREG %THEN OPCODE=CPB %ELSE OPCODE=UCP
            %IF SIZE=16 %THEN PF1(STUH,0,TOS,0)
            %IF SIZE=2 %THEN A=0 %AND D=UNASSPAT>>16 %ELSE %C
                  A=PC %AND D=PLABS(1)
            PF1(OPCODE,0,A,D)
            %IF SIZE=16 %THEN PF1(LUH,0,TOS,0)
         %FINISH
         PPJ(8,5);                      ! BE ERROR ROUTINE 5
         %IF TYPE=5 %THEN PF1(LD,0,TOS,0)
%END
         %ROUTINE     CBPAIR(%INTEGERNAME LB,UB)
!***********************************************************************
!*       EXTRACT UPPER AND LOWER BOUNDS FROM A CONSTANT BOUND PAIR     *
!***********************************************************************
         %INTEGER KK,KKK,JJ,BP
         P=P+1; KK=0
         %CYCLE JJ=1,1,2
           KKK=KK
           %IF A(P)=2 %THEN KK=-1 %ELSE KK=1;  ! EXTRACT SIGN
           BP=FROMAR4(P+2)
           KK=KK*BP
           P=P+6
         %REPEAT
         %IF KKK>KK %THEN FAULT(43,0) %AND KK=KKK
         LB=KKK; UB=KK
         %END
         %ROUTINE GET WSP(%INTEGERNAME PLACE,%INTEGER SIZE)
!***********************************************************************
!*       FIND OR CREATE A TEMPORARY VARIABLE OF 'SIZE' WORDS           *
!***********************************************************************
         %INTEGER J,K,L
         %IF SIZE>4 %THEN SIZE=0
         POP(AVL WSP(SIZE,LEVEL),J,K,L)
         %IF K<=0 %THEN %START;        ! MUST CREATE TEMPORARY
            %IF SIZE>1 %THEN ODD ALIGN
            K=N
            %IF SIZE=0 %THEN N=N+268 %ELSE N=N+SIZE<<2
         %FINISH
         PLACE=K
         PUSH(TWSPHEAD,K,SIZE,0) %UNLESS SIZE=0
         %END
         %ROUTINE RETURN WSP(%INTEGER PLACE,SIZE)
         %IF SIZE>4 %THEN SIZE=0
         %IF PLACE<511 %THEN PUSH(AVL WSP(SIZE,LEVEL),0,PLACE,0) %C
            %ELSE INSERT AT END(AVL WSP(SIZE,LEVEL),0,PLACE,0)
         %END
         %ROUTINE SETLINE
!***********************************************************************
!*       UPDATE THE STATEMENT NO                                       *
!***********************************************************************
         %IF PARMLINE=1 %THEN %START
            PSF1(LSS,0,LINE)
            PSF1(ST, 1, DIAGINF(LEVEL))
            GRUSE(ACCR)=5; GRINF(ACCR)=LINE
          %FINISH
          %END
         %ROUTINE FORGET(%INTEGER REG)
%INTEGER L,U
         L=REG; U=L
         %IF L<0 %THEN L=0 %AND U=7
         %CYCLE REG=L,1,U
            %IF REGISTER(REG)>= 0 %THEN GRUSE(REG)=0 %AND GRINF(REG)=0
         %REPEAT
         %END
%ROUTINE SAVE IRS
!***********************************************************************
!*       DUMP ACC AND-OR B ONTO THE STACK.  USED BEFORE CALLING FNS     *
!*      IN EXPRESSIONS.                                                 *
!***********************************************************************
         ABORT %IF REGISTER(ACCR)=1=REGISTER(BREG)
         %IF REGISTER(ACCR)>=1 %THEN BOOT OUT(ACCR)
         %IF REGISTER(BREG)>=1 %THEN BOOT OUT(BREG)
         %IF REGISTER(DR)>=1 %THEN BOOT OUT(DR)
%END
%ROUTINE BOOT OUT(%INTEGER REG)
!***********************************************************************
!*       REMOVE TEMPORARIES FROM REG INTO LOCAL OR ONTO STACK          *
!*       IT IS VITAL THAT ACC IS STACKED FIRST BEFORE B OR DR          *
!*       OTHERWISE MIXUPS OCCUR WHEN PASSING MULTI-DIMENSION ARRAY     *
!*       ELEMENTS WITH FNS AS SUBSCRIPTS AS VALUE SCALARS              *
!***********************************************************************
%CONSTBYTEINTEGERARRAY BOOTCODE(0:7)=X'48',X'58',X'5C',0(4),X'5A';
%INTEGER CODE
%RECORDNAME R(RD)
         CODE=BOOTCODE(REG)
         ABORT %UNLESS 1<=REGISTER(REG)<=3 %AND  CODE#0
         R==RECORD(OLINK(REG))
         %IF REGISTER(REG)=2 %THEN %START
            %IF R_D=0 %THEN GET WSP(R_D,BYTES(R_PTYPE>>4)>>2)
               PSF1(CODE,1,R_D)
         %FINISH %ELSE %START
            %IF REG#ACCR %AND(REGISTER(ACCR)=1 %OR REGISTER(ACCR)=3)%C
               %THEN BOOT OUT(ACCR)
            PF1(CODE,0,TOS,0)
         %FINISH
         CHANGE RD(REG)
         REGISTER(REG)=0
%END
%ROUTINE COPY DR
!***********************************************************************
!*       COPY THE DR TO ACC SAVING ANYTHING IN ACC                     *
!***********************************************************************
         %IF REGISTER (ACCR)#0 %THEN BOOT OUT(ACCR)
         PSF1(CYD,0,0)
         GRUSE(ACCR)=0
%END
%ROUTINE CHANGE RD(%INTEGER REG)
!***********************************************************************
!*         CHANGE A RESULT DESCRIPTOR WHEN OPERAND IS STACKED          *
!***********************************************************************
%RECORDNAME OPND(RD)
         ABORT %UNLESS 1<=REGISTER(REG)<=3;! I-R OR PARAM
         OPND==RECORD(OLINK(REG))
         %IF REGISTER(REG)=1 %THEN %START;   ! CHANGE RESULT DESCRIPTOR
            ABORT %UNLESS OPND_FLAG=9 %AND OPND_XB>>4=REG
            OPND_FLAG=8;             ! CHANGE TO 'STACKED'
            OPND_XB=TOS<<4
         %FINISH
         %IF REGISTER(REG)=2 %START
            OPND_FLAG=7; OPND_XB=LNB<<4
         %FINISH
%END
%ROUTINE STORE TAG(%INTEGER KK, SLINK)
%INTEGER Q, QQ, QQQ, I, TCELL
%RECORDNAME LCELL(LISTF)
         TCELL=TAGS(KK)
         Q=PTYPE<<16!LEVEL<<8!RBASE<<4!J
!         ABORT %UNLESS (KFORM!ACC)>>16=0
         QQQ=SLINK<<16!KFORM
         QQ=SNDISP<<16!ACC
         %IF FROM1(TCELL)>>8&63=LEVEL %THEN %START
            FAULT(7,KK)
            Q=FROM1(TCELL)&X'C000'!Q;! COPY USED BITS ACCROSS
            REPLACE123(TCELL,Q,QQ,QQQ)
         %FINISH %ELSE %START
            I=ASL; %IF I=0 %THEN I=MORE SPACE
            LCELL==ASLIST(I)
            ASL=LCELL_LINK
            LCELL_LINK=TAGS(KK)!NAMES(LEVEL)<<18
            LCELL_S1=Q; LCELL_S2=QQ; LCELL_S3=QQQ
            TAGS(KK)=I
            NAMES(LEVEL)=KK
         %FINISH
%END
%ROUTINE COPY TAG(%INTEGER KK)
%INTEGER QQ,QQQ
%RECORDNAME LCELL(LISTF)
         TCELL=TAGS(KK)
         %IF TCELL=0 %THEN %START;        ! NAME NOT SET
           TYPE=7; PTYPE=X'57'; PREC=5
           ROUT=0; NAM=0; ARR=0; LITL=0; ACC=4
           I=-1; J=-1; K=-1; OLDI=-1
         %FINISH %ELSE %START
            LCELL==ASLIST(TCELL)
            KK=LCELL_S1
            LCELL_S1=KK!X'8000'
            QQ=LCELL_S2
            QQQ=LCELL_S3
            PTYPE=KK>>16; USEBITS=KK>>14&3
            OLDI=KK>>8&63; I=KK>>4&15; J=KK&15
            SNDISP=QQ&X'FFFF0000'//X'10000'
            ACC=QQ&X'FFFF'
            K=QQQ&X'FFFF0000'//X'10000'
            KFORM=QQQ&X'FFFF'
            LITL=PTYPE>>14
            ROUT=PTYPE>>12&3
            NAM=PTYPE>>10&3
            ARR=PTYPE>>8&3
            PREC=PTYPE>>4&15
            TYPE=PTYPE&15
         %FINISH
%END
%ROUTINE REDUCE TAG
!***********************************************************************
!*       AS COPY TAG FOR NAME AT A(P) EXCEPT:-                         *
!*       1) SPECIAL NAMES HAVE THEIR CORRECT PREC & TYPE SUBSTITUTED   *
!*       2) RECORD ELEMENTS HAVE THE SUBNAME PARTICULARS RETURNED      *
!***********************************************************************
%INTEGER SUBS,QQ,PP
         COPY TAG(FROMAR2(P))
         %IF PTYPE=SNPT %THEN %START
            PTYPE=TSNAME(K);  UNPACK
            ROUT=1
         %FINISH;                       ! TO AVOID CHECKING PARAMS
         %IF TYPE=3 %THEN %START
            PP=P; QQ=COPY RECORD TAG(SUBS); P=PP
         %FINISH
%END
%ROUTINE REPLACE TAG(%INTEGER KK)
%INTEGER P, Q
         P=TAGS(KK)
         Q=PTYPE<<16!USEBITS<<14!OLDI<<8!I<<4!J
         REPLACE 1(P, Q)
         REPLACE3(P, K<<16!KFORM)
%END
! LAYOUT OF PTYPE
! ****** ** *****
! PTYPE REQUIRES 16 BITS TO DEFINE A VARIABLE AND CAN BE REGARDED AS
! AS TWO BYTEINTEGERS:=
! UPPER ONE(UPTYPE):= LITL<<6!ROUT<<4!NAM<<2!ARR
! LOWER ONE(PTYPE) :=PREC<<4!TYPE
! OFTEN (EG IN EXPOP) ONLY THE LOWER PART IS REQUIRED AS FUNCTIONS
! ETC ARE PREFETCHED AND STACKED.
! LITL:= 1=CONST,2=EXTERNAL,3=EXTRINSIC(OR DYNAMIC), 0=NONE OF THESE
! ROUT:= 1 FOR ROUTINE OR FN OR MAP, =0 NONE OF THESE
! NAM := 2 FOR MAPS AND 'REFREFS',=1 FOR NAMES ,=0 DIRECTLY ADDRESSED
! ARR :=1 FOR ARRAYS =0 SCALARS
! PREC IS DESCRIPTOR SIZE CODE FOR EACH PRECISION:-
!     :=0 BITS,=3 BYTES, =5 WORDS, =6 D-WRDS, =7,QUAD WRDS
! TYPE:= THE VARIABLE TYPE 
!     :=0 (TYPE GENERAL),=1 INTEGER, =2 REAL, =3 RECORD
!     :=4 (RECORDFORMAT),=5 STRING,  =6 LABEL/SWITCH. =7 NOT SET
!
%ROUTINE UNPACK
         LITL=PTYPE>>14
         ROUT=PTYPE>>12&3
         NAM=PTYPE>>10&3
         ARR=PTYPE>>8&3
         PREC=PTYPE>>4&15
         TYPE=PTYPE&15
%END
%ROUTINE PACK(%INTEGERNAME PTYPE)
         PTYPE=((((LITL<<2!ROUT)<<2!NAM)<<2!ARR)<<4!PREC)<<4!TYPE
%END
%ROUTINE PPJ(%INTEGER MASK,N)
!***********************************************************************
!*       PLANT A 'JCC MASK,PERMENTRY(N)'                               *
!*       IF MASK=0 THEN PLANT A JLK                                    *
!*       IF MASK=-1 THEN PLANT A CALL TO PERM                          *
!***********************************************************************
%INTEGER VAL, INSTRN, CODE
         %IF MASK=0 %THEN CODE=JLK %ELSE CODE=CALL
         %IF MASK>0 %THEN CODE=JCC
         %IF MASK>=16 %THEN CODE=JAT
         %IF MASK>=32 %THEN CODE=JAF
         VAL=PLABS(N)
         %IF MASK<=0 %THEN INSTRN=CODE<<24!3<<23 %ELSE %C
            INSTRN=CODE<<24!(MASK&15)<<21
         %IF VAL>0 %THEN INSTRN=INSTRN!((VAL-CA)//2)&X'3FFFF' %ELSE %C
            PUSH(PLINK(N),CA,INSTRN,0)
         PCONST(INSTRN)
         FORGET(-1) %IF MASK<=0
%END
%INTEGERFN SET XORYNB(%INTEGER WHICH,RLEV)
!***********************************************************************
!*       SET EXTRA NAME BASE TO ADDRESS ROUTINE LEVEL 'RLEV'           *
!*       RLEV=0 FOR OWNS, =-1 FOR THE PLT THESE ARE THE SAME! BUT CODED*
!*       SEPARATELY SO THAT THEY CAN BE SEPARATED IF NECESSARY         *
!***********************************************************************
%INTEGER USE,INF,OFFSET
         ABORT %UNLESS -1<=RLEV<=RLEVEL
      %IF RLEV<=0 %THEN USE=3 %AND INF=0 %ELSE USE=4 %AND INF=RLEV
      %IF WHICH<=0 %THEN WHICH=XORYNB(USE,INF)
      %IF GRUSE(WHICH)=USE %AND GRINF(WHICH)=INF %THEN %C
         GRAT(WHICH)=CA %AND %RESULT=WHICH
      OFFSET=PTR OFFSET(RLEV)
      PSF1(LDCODE(WHICH),1,OFFSET)
      GRUSE(WHICH)=USE; GRINF(WHICH)=INF; GRAT(WHICH)=CA
      %RESULT=WHICH
%END
%INTEGERFN XORYNB(%INTEGER USE,INF)
!***********************************************************************
!*    CHECKS IF XNB OR YNB SET UP. IF NOT DECIDES WHICH TO OVERWRITE   *
!***********************************************************************
      %IF GRUSE(XNB)=USE %AND GRINF(XNB)=INF %THEN GRAT(XNB)=CA %C
            %AND %RESULT=XNB
      %IF GRUSE(CTB)=USE %AND GRINF(CTB)=INF %THEN GRAT(CTB)=CA %C
            %AND %RESULT=CTB
      %IF GRUSE(XNB)!GRUSE(CTB)=0 %THEN %START;! BOTH REGS ARE FREE
         %IF USE=3 %THEN %RESULT=CTB
         %RESULT=XNB
      %FINISH
!
! IF ONLY ONE FREE THEN NO PROBLEM
      %IF GRUSE(XNB)=0 %THEN %RESULT=XNB
      %IF GRUSE(CTB)=0 %THEN %RESULT=CTB
!
! BOTH ARE IN USE. THIS IS WORTH CAREFUL CONSIDERATION AND EXPERIMENT
! A VALUE TABLE MAY BE USE AS MAY LOOK AHEAD. CURRENTLY TRY LRU
!
      %IF GRAT(XNB)<GRAT(CTB) %THEN %RESULT=XNB
      %RESULT=CTB
%END
%ROUTINE ODDALIGN
!***********************************************************************
!*    SETS N TO ODD WORD BOUNDARY. SINCE PRECALL ALSO SETS SF TO ODD   *
!*    WORD BOUNDARY THIS MEANS 64 BIT QUANTITIES ARE 64 BIT ALIGNED    *
!*    AND CAN BE REFERNCED IN A SINGL CORE CYCLE                       *
!***********************************************************************
      %IF N&7=0 %THEN RETURN WSP(N,1) %AND N=N+4
%END
%INTEGERFN PTROFFSET(%INTEGER RLEV)
!***********************************************************************
!*    RETURNS OFFSET FROM LNB OF RELEVANT ITEM IN THE CURRENT DISPLAY  *
!*    WHICH ENABLES TEXTTUAL LEVEL 'RLEV' TO BE ADDRESSED              *
!*    A FUNCTION IS USED TO ALLOW CHANGES IN THE DISPLAY FORMAT        *
!***********************************************************************
      %IF RLEV<=0 %THEN %RESULT=16
      %RESULT=DISPLAY(RLEVEL)+(RLEV-1)<<2
%END
%INTEGERFN AREA CODE
!***********************************************************************
!*       RETURNS THE AREA CODE FOR ROUTINE LEVEL 'BASE' LOADING        *
!*       XNB WHERE THIS IS NEEDED                                      *
!***********************************************************************
         %IF AREA<0 %THEN %START
            %IF BASE=RBASE %THEN AREA=LNB %AND %RESULT=LNB;! LOCAL LEVEL
            AREA=SET XORYNB(-1,BASE)
         %FINISH
         %RESULT=AREA
%END
%ROUTINE GET IN ACC(%INTEGER REG,SIZE,ACCESS,AREA,DISP)
!***********************************************************************
!*         LOADS THE REGISTER SPECIFIED ARRANGING FOR AUTOMATIC        *
!*       STACKING WHEN THIS IS NEEDED                                  *
!*       IT IS VITAL THAT ACC IS STACKED FIRST BEFORE B OR DR          *
!*       OTHERWISE MIXUPS OCCUR WHEN PASSING MULTI-DIMENSION ARRAY     *
!*       ELEMENTS WITH FNS AS SUBSCRIPTS AS VALUE SCALARS              *
!***********************************************************************
%INTEGER OPCODE
      SIZE=1 %IF SIZE=0;       ! BITS ABD BYTES!
!      ABORT %UNLESS REG=ACCR %OR(REG=DR %AND SIZE=2) %OR %C
             (REG=BREG %AND SIZE=1)
      %IF REG=DR %THEN OPCODE=LD %ELSE %START
         %IF REG=BREG %THEN OPCODE=LB %ELSE OPCODE=LSS+SIZE&6
      %FINISH
!
      %IF REGISTER(REG)>=1 %THEN %START
         %IF REGISTER(REG)=2 %THEN BOOT OUT(REG) %ELSE %START
            %IF REG#ACCR %AND(REGISTER(ACCR)=1 %OR REGISTER(ACCR)=3)%C
               %THEN BOOT OUT(ACCR)
            CHANGE RD(REG)
            REGISTER(REG)=0
           %IF REG=ACCR %THEN OPCODE=OPCODE-32 %ELSE OPCODE=OPCODE-40
         %FINISH
      %FINISH
      PSORLF1(OPCODE,ACCESS,AREA,DISP)
      %IF ACCESS>=2 %THEN GRUSE(DR)=0
      GRUSE(REG)=0
%END
%ROUTINE NOTE ASSMENT(%INTEGER REG, ASSOP, VAR)
!***********************************************************************
!*       NOTES THE ASSIGNMENT TO SCALAR 'VAR'.  THIS INVOLVES REMOVING *
!*       OLD COPIES FROM REGISTERS TO AVOID CONFUSING OLD AND NEW VALUE*
!*       ASSOP =1 FOR'==',=2 FOR '=',=3 FOR '<-'                       *
!***********************************************************************
%CONSTINTEGER EEMASK=B'11110000000'
%INTEGER I
         %IF ASSOP=1 %THEN %START
            %CYCLE I=0,1,7
               GRUSE(I)=0 %IF EEMASK&1<<GRUSE(I)#0 %AND %C
               (GRINF(I)&X'FFFF'=VAR %OR GRINF(I)>>16=VAR)
            %REPEAT
         %FINISH %ELSE %START
            %CYCLE I=0,7,7
               GRUSE(I)=0 %IF 9<=GRUSE(I)<=10 %AND %C
                  (GRINF(I)&X'FFFF'=VAR %OR GRINF(I)>>16=VAR)
            %REPEAT
            %IF ASSOP=2 %AND VAR>0 %AND(GRUSE(REG)#5 %OR GRINF(REG)<0%C
               %OR GRINF(REG)>3) %THEN %START
               %IF GRUSE(REG)#9 %THEN GRUSE(REG)=9 %AND GRINF(REG)=0
               GRINF(REG)=GRINF(REG)<<16!VAR
            %FINISH
         %FINISH
 %END
%END;                                  ! OF ROUTINE CSS
!*DELSTART
%ROUTINE PRINTUSE
%CONSTSTRING(3)%ARRAY REGS(0:7)='ACC',' DR','LNB','XNB',
                                      ' PC','CTB','TOS','  B';
%CONSTSTRING(15)%ARRAY USES(0:15) =' NOT KNOWN ',' I-RESULT  ',
                                   ' TEMPORARY ','  PLTBASE  ',
                                   ' NAMEBASE  ',' LIT CONST ',
                                   ' TAB CONST ',' DESC FOR  ',
                                   ' RECD BASE ',' LOCAL VAR ',
                                   ' NAME+CNST ','    FREE   ',
                                   ' BYTE DES  ',' HALF DES  ',
                                   '    FREE   ','    FREE   ';
%CONSTSTRING(11)%ARRAY STATE(-1:3)=%C
                                        '  LOCKED   ','   FREE    ',
                                        ' I-RESULT  ',' TEMPORARY ',
                                        ' RT-PARAM  ';
%INTEGER I,USE,INF
      %CYCLE I=0,1,7
         %IF REGISTER(I)!GRUSE(I)#0 %START
            USE=GRUSE(I); INF=GRINF(I)
            PRINTSTRING(REGS(I).STATE(REGISTER(I)). %C
               ' USE = '.USES(USE))
            %IF 7<=USE<=10 %THEN PRINTNAME(INF&X'FFFF') %C
               %ELSE WRITE(INF,1)
            %IF USE=10 %THEN PRINTSYMBOL('+') %AND %C
               WRITE(INF>>16,1)
            %IF USE=9 %AND INF>>16#0 %THEN PRINT SYMBOL('+') %C
               %AND PRINT NAME(INF>>16)
            NEWLINE
         %FINISH
      %REPEAT
%END
!*DELEND
%ROUTINE ABORT
         PRINTSTRING('
****************      ABORT********************    ABORT    *******')
!*DELSTART
         NCODE(ADDR(CODE(0)), ADDR(CODE(PPCURR)), CABUF) %C
            %UNLESS CA=CABUF
         PRINT USE
!*DELEND
         %MONITOR
         %STOP
%END
%ROUTINE EPILOGUE
!***********************************************************************
!*       PLANT ANY SUBROUINES THAT HAVE BEEN REQUIRED DURING           *
!*       THE CODE GENERATION PHASE                                     *
!***********************************************************************
%INTEGER D,J
%ROUTINESPEC FILL(%INTEGER LAB)
         %IF PLINK(15)=0 %THEN ->P16
         FILL(15)
!
! CONTINGENCY ENTRY - LNB RESTORE FOR MAIN PROGRAM. ACC HAS WORD DECP
! TO 18 WORD AREA OF FAILURE & IMAGE STORE:-
! WORD0 = FAILURE?, WORD1=XTRA?,WORD2=LNB,WORD4=PC
! THIS ROUTINE TRANSCRIBES THESE INTO A CALL ON MDIAGS
!
!         ST    TOS
!        PRCL  4                        REPLACE THE CONTINGENCY
!        LSS   -1
!        ST    TOS
!        JLK   +2                       ROUND NEXT INST
!        J     -5                       BACK TO ENTRY POINT
!        STLN  TOS
!        LDTB  WORD DESCRIPTOR          FOR REPORT WORD
!        LXN   (LNB+4)                  TO PLT
!        LDA   (XNB+5)                  BY STORED LNB IN PLT
!        INCA  20
!        STD TOS
!        RALN  10
!        CALL ROUTINE SIGNAL
!
!         LD    TOS                  DESCRIPTOR TO DR
!         PRCL  4                    TO PLANT PARAMS
!         LSS   (DR+4)               PC FIRST PARAM
!         SLSS  (DR+2)                LNB SECOND PARAM
!         SLSS  10                   ERROR NO 10
!         SLSS  (DR)                 XTRA IS FAILURE NO
!         ST    TOS
!         LXN   (LNB+4)              TO PLT(GLA)
!         RALN  9
!         CALL  ((XNB+10))           TO MDIAGS - DOES NOT RETURN
!
         PF1(ST,0,TOS,0)
         PSF1(PRCL,0,4)
         PSF1(LSS,0,-1)
         PF1(ST,0,TOS,0)
         PSF1(JLK,0,2)
         PSF1(JUNC,0,-5)
         PF1(STLN,0,TOS,0)
         PF1(LDTB,0,PC,PARAM DES(5))
         PSF1(LXN,1,16)
         PF1(LDA,0,XNB,20)
         PSF1(INCA,0,20)
         PF1(STD,0,TOS,0)
         PSF1(RALN,0,10)
         PF1(CALL,2,XNB,SIGREFDIS)
         PF1(LD,0,TOS,0)
         PSF1(PRCL,0,4)
         PF1(LSS,1,0,4)
         PF1(SLSS,1,0,2)
         PSF1(SLSS,0,10)
         PF1(SLSS,2,7,0)
         PF1(ST,0,TOS,0)
         PSF1(LXN,1,16)
         PSF1(RALN,0,9)
         PF1(CALL,2,XNB,40)
P16:
!
! STRING RESOLUTION SUBROUTINE
! THIS IS ENTERED VIA A CALL INSTRN AND HAS 3 PARAMETERS
! P1(LNB+5) = RESD A CURRENT LENGTH DESCRIPTOR POINTING AT THE FIRST BYTE
!             OF THE STRING BEING RESOLVED
! P2(LNB+7) = STD A MAX LENGTH DESCRIPTOR TO THE STRING IN WHICH ANY
!             FRAGMENT IS TO BE STORED
! P3(LNB+9) - EXPD A CURRENT LENGTH DESCRIPTOR POINTING AT THE 
!             LENGTH BYTE OF STRING TO BE SEARCHED FOR
!
! IF RESOLUTION IS SUCCESSFULL CC IS SET TO 0 AND AN UPDATED VERSION
! OF RESD IS RETURNED IN THE ACC IN CASE THERE ARE FURTHER RESLNS
!
! CODE IS AS FOLLOWS:-
!
!        LXN   (LNB+0)                  OLD LNB
!        LD    (XNB+3)                  PLT DESCRIPTOR
!        LDB   0                        ZERO BOUND FOR MDIAG
!        STD   (LNB+3)                  STANDARD PLACE
!        ASF   4                        GRAB 2 TEMPORARIES
!        LD    (LNB+5)                  RESULT IF NULL ROUTE TAKEN
!        SLD   (LNB+9)                  EXPD
!        LB    0
!        JAT   11,LNULL                 JUMP IF EXP NULL
!        INCA  1                        TO FIRST CHAR
!        LB    @DR                      FIRST CHAR INTO B
!        STD   (LNB+11)                 TEMP1
!        LSS   (LNB+5)                  TYPE&BND OF RESD
!        AND   XIFF
!        JAT   4,RESFAIL                RESD IS NULL &EXPD NOT NULL
!        LD    (LNB+5)                  RESD TO DR
!AGN     SWNE  L=DR                     SEARCH FOR FIRST CHAR
!        JCC   8,RESFAIL                NOT FOUND
!        STD   (LNB+13)                 SAVE IN TEMP 2
!        CYD   0
!        LD    (LNB+11)                 EXP DESCRIPTOR FOR COMPARISON
!        CPS   L=DR,FILLER=FF           CHECK REST OF EXPRSN
!        JCC   8,L2                     RESLN HAS SUCCEEDED
!        LD    (LNB+13)                 RESUME SCANNING
!        SWEQ  L=1                      ADVANCE BY 1 AVOIDING MODD
!        J     AGN
!
! RESOLUTION COMPLETE. ARRANGE TO STORE FRAGMENT WITHOUT ANY FILLER CHARS
! SO S->S.(T).Z WORKS OK AND ALLOWING STD TO BE NULL
!
!L2      SLSS  (LNB+5)                  STORE UPDATED DES & GET BND
!        ISB   (LNB+13)                 GIVE LENGTH OF FRAGMENT
!        ST    B
!        LSS   (LNB+7)                  LENGTH OF STD
!        JAF   4,*+6                    ! ZERO FOR NO 1ST PART RESLN
!        LSS   1
!        AND   X1FF
!        ICP   B
!        JCC   12,RESFAIL
!LNULL   LD    (LNB+7)                  STD TO DR
!        JAT   11,L3                    STD NULL DONT SET LENGTH
!        LSD   (LNB+5)                  ORIGINIAL STRING
!        MVL   L=1                      SET LENGTH BYTE FROM B
!        LDB   B                        TO STORE CHARS
!        MV    L=DR,FILLER=X'80'        ASSIGN
!L3      LD    TOS                      RESULT AND SET CC=0
!        CYD   0
!        EXIT
!RESFAIL MPSR  X'24'                    SET CC=1
!        EXIT
         %IF PLINK(16)=0 %THEN ->P17
         FILL(16)
         PSF1(LXN,1,0)
         PF1(LD,0,XNB,12)
         PSF1(LDB,0,0)
         PSF1(STD,1,12)
         PSF1(ASF,0,4)
         PSF1(LD,1,20)
         PSF1(SLD,1,36)
         PSF1(LB,0,0)
         PF3(JAT,11,0,X'24')
         PSF1(INCA,0,1)
         PF1(LB,2,7,0)
         PSF1(STD,1,44)
         PSF1(LSS,1,20)
         PF1(AND,0,0,X'1FF')
         PF3(JAT,4,0,X'27')
         PSF1(LD,1,23)
         PF2(SWNE,1,0,0,0,0)
         PF3(JCC,8,0,X'23')
         PSF1(STD,1,52)
         PSF1(CYD,0,0)
         PSF1(LD,1,44)
         PF2(CPS,1,1,0,0,X'FF')
         PF3(JCC,8,0,5)
         PSF1(LD,1,52)
         PF2(SWEQ,0,0,0,0,0)
         PSF1(JUNC,0,-12)
         PSF1(SLSS,1,20)
         PSF1(ISB,1,52)
         PF1(ST,0,BREG,0)
         PSF1(LSS,1,28)
         PF3(JAF,4,0,3)
         PSF1(LSS,0,1)
         PF1(AND,0,0,X'1FF')
         PF1(ICP,0,BREG,0)
         PF3(JCC,12,0,13)
         PSF1(LD,1,28)
         PF3(JAT,11,0,7)
         PSF1(LSD,1,20)
         PF2(MVL,0,0,0,0,0)
         PF1(LDB,0,BREG,0)
         PF2(MV,1,1,0,0,UNASSPAT&255)
         PF1(LD,0,TOS,0)
         PSF1(CYD,0,0)
         PSF1(EXIT,0,-X'40')
         PSF1(MPSR,0,X'24')
         PSF1(EXIT,0,-X'40')
P17:
!
! EVALUATE X**Y
! ******** ****
! Y IS IN ACC X IS STACKED BELOW THE LINK(UNAVOIDABLE)
! FAULT(21) IS GIVEN IF X<0 OR (X=0 AND Y<=0)
! REPEATED MULTIPLICATION IS USED IF Y>0 AND FRACPT(Y)=0
! OTHERWISE RESULT=EXP(Y*LOG(Y))
!
!        LB    TOS                      SWOP RETURN ADDRESS & X
!        LD    TOS                      X TO DR
!        STB   TOS
!        STD   TOS
!        SLSD  TOS                      X TO ACC Y TO TOS
!        JAT   2,EXPERR                 ERROR IF X<0
!        JAF   0,TRYMULT                JUMP X#0
!        SLSD  TOS                      STACK X & GET Y
!        JAF   1.EXPERR                 Y<=0
!        LSD   TOS                      X (=0) =RESULT TO ACC
!        J     TOS                      RETURN
!TRYMULT                                X IS IN ACC & Y STACKED
!        SLSD  TOS                      Y TO ACC AND X STACKED
!        ST    TOS                      Y STACKED
!        JAT   2,NONINT                 Y IS NEGATAIVE
!        RSC   55
!        RSC   -55
!        FIX   B                        FIX PINCHED FROM ICL ALGOL
!        MYB   4
!        CPB   -64
!        JCC   10,*+3
!        LB    -64
!        ISH   B
!        STUH  B                        ACC TO 1 WORD
!        JCC   7,NONINT                 JUMP IF TRUNCATION
!        ASF   -2                       LOSE Y OF STACK
!        ST    B                        INTEGER VERSION OF Y TO B
!        LSS   1
!        FLT   0
!        JAF   12,MUL                   JUMP IF B#0
!        ASF   -2                       LOSE X OFF STACK
!        J     TOS                      X**0 =1
!AGN     STD   TOS                      STACK ANOTHER COPY OF X
!MUL     RMY   TOS
!        DEBJ  AGN                      REPEATED MULTIPLICATION
!        J     TOS
!NONINT                                 Y IS STACKED OVER X
!        LSD   TOS
!        SLSD  TOS
!        PRCL  4
!        ST    TOS
!        LXN   (LNB+4)
!        RALN  7
!        CALL  ((XNB+LOGEPDISP)
!        RMY   TOS
!        PRCL  4
!        ST    TOS
!        LXN   (LNB+4)                  TO PLT
!        RALN  7
!        CALL  ((XNB+EXPEPDISP))        CALL EXP
!        J     TOS
!EXPERR  J     ERROR RT NO 7
!
         %IF PLINK(17)=0 %THEN ->P18
         FILL(17)
         %IF LOGEPDISP=0 %THEN CXREF('S#ILOG',0,2,LOGEPDISP)
         %IF EXPEPDISP=0 %THEN CXREF('S#IEXP',0,2,EXPEPDISP)
         PF1(LB,0,TOS,0)
         PF1(LD,0,TOS,0)
         PF1(STB,0,TOS,0)
         PF1(STD,0,TOS,0)
         PF1(SLSD,0,TOS,0)
         PF3(JAT,2,0,X'35')
         PF3(JAF,0,0,7)
         PF1(SLSD,0,TOS,0)
         PF3(JAF,1,0,X'30')
         PF1(LSD,0,TOS,0)
         PF1(JUNC,0,TOS,0)
         PF1(SLSD,0,TOS,0)
         PF1(ST,0,TOS,0)
         PF3(JAT,2,0,26)
         PSF1(RSC,0,55)
         PSF1(RSC,0,-55)
         PF1(FIX,0,BREG,0)
         PSF1(MYB,0,4)
         PSF1(CPB,0,-64)
         PF3(JCC,10,0,3)
         PSF1(LB,0,-64)
         PF1(ISH,0,BREG,0)
         PF1(STUH,0,BREG,0)
         PF3(JCC,7,0,14)
         PSF1(ASF,0,-2)
         PF1(ST,0,BREG,0)
         PSF1(LSS,0,1)
         PSF1(FLT,0,0)
         PF3(JAF,12,0,5)
         PSF1(ASF,0,-2)
         PF1(JUNC,0,TOS,0)
         PF1(STD,0,TOS,0)
         PF1(RMY,0,TOS,0)
         PSF1(DEBJ,0,-2)
         PF1(JUNC,0,TOS,0)
         PF1(LSD,0,TOS,0)
         PF1(SLSD,0,TOS,0)
         PSF1(PRCL,0,4)
         PF1(ST,0,TOS,0)
         PSF1(LXN,1,16)
         PSF1(RALN,0,7)
         PF1(CALL,2,XNB,LOGEPDISP)
         PF1(RMY,0,TOS,0)
         PSF1(PRCL,0,4)
         PF1(ST,0,TOS,0)
         PSF1(LXN,1,16)
         PSF1(RALN,0,7)
         PF1(CALL,2,XNB,EXPEPDISP)
         PF1(JUNC,0,TOS,0)
         PF1(JUNC,0,0,(PLABS(7)-CA)//2)
P18:
!
! MAPPED STRING ASSIGNMENT CHECK. CHECKING MODE ONLY. MUST MOVE ONLY
! CURRENT LENGTH INTO MAPPED STRINGS BUT MUST NOT OMIT THE CAPACITY
! CHECK. ACC & DR SET FOR MV
!
!        ST    TOS                      SAVE ACC DESRPTR
!        AND   X'FF00000000'            GET CURRENT LENGTH
!        STUH  B                        INTO BREG
!        LSD   TOS                      RESTORE ACC
!        STD   TOS                      SAVE DR DESCRPTR
!        SBB   1
!        JAF 13,*+3
!        MODD  B                        PROVOKE FAILURE IF RELEVANT
!        ADB   1
!        LD    TOS
!        LDB   B                        BOUND=CURRENT L +1(FOR LBYTE)
!        J     TOS
!
         %IF PLINK(18)=0 %THEN ->P19
         CNOP(0,8)
         D=CA
         PCONST(255)
         PCONST(0);                     ! XFF00000000
         FILL(18)
         PF1(ST,0,TOS,0)
         PF1(AND,0,PC,D)
         PF1(STUH,0,BREG,0)
         PF1(LSD,0,TOS,0)
         PF1(STD,0,TOS,0)
         PSF1(SBB,0,1)
         PF3(JAF,13,0,3)
         PF1(MODD,0,BREG,0)
         PSF1(ADB,0,1)
         PF1(LD,0,TOS,0)
         PF1(LDB,0,BREG,0)
         PF1(JUNC,0,TOS,0)
P19:
! CONCATENATION ONE
! COPY THE FIRST STRING INTO THE WORK AREA
! B HAS REL DISP OF THE WORK AREA FROM LNB
! DR HAS CURRENT LENGTH DESCRIPTOR OF FIRST STRING
! RESULT IS A CURRENT LENGTH DESCRIPTOR TO WORK AREA IN DR AND ACC
!
!        STLN TOS
!        ADB   TOS
!        LXN   B                        XNB TO WORK AREA
!        SLB   @DR                      CURRENT LENGTH TO B
!        STB   (%XNB+2)                 INTO LENGTH BYTE OF WK AREA
!        INCA  1                        DR PAST LENGTH BYTE
!        CYD   0                        BECOMES SOURCE STRING
!        LD    =X'180000FF0000000C'     
!        INCA  TOS                      DESCRIPTOR TO WK STRING
!        STD   (%XNB+0)                 STORED FOR LATER
!        LDB   B                        ADJUSTED SO NO FILLING
!        MV    L=DR                     THE MOVE
!        LD    (%XNB+0)                 SET UP DR WITH RESULT
!        LDB   B                        CURRENT LENGTH AS BOUND
!        INCA  -1                       TO POINT AT LENGTH BYTE
!        CYD   0                        TO ACC AS WELL
!        J     TOS                      RETURN
      %IF PLINK(19)!PLINK(20)=0 %THEN ->P21
      CNOP(0,8);                        ! DOUBLE WORD ALLIGN
      D=CA
      PCONST(X'180000FF'); PCONST(12)
      FILL(19)
      PF1(STLN,0,TOS,0)
      PF1(ADB,0,TOS,0)
      PF1(LXN,0,BREG,0)
      PF1(SLB,2,7,0)
      PF1(STB,0,XNB,8)
      PSF1(INCA,0,1)
      PSF1(CYD,0,0)
      PF1(LD,0,PC,D)
      PF1(INCA,0,TOS,0)
      PF1(STD,0,XNB,0)
      PF1(LDB,0,BREG,0)
      PF2(MV,1,0,0,0,0)
      PF1(LD,0,XNB,0)
      PF1(LDB,0,BREG,0)
      PSF1(INCA,0,-1)
      PSF1(CYD,0,0)
      PF1(JUNC,0,TOS,0)
!
! CONCATENATION TWO
! ADD THE SECOND AND SUBSEQUENT STRINGS TO THE FIRST
! PARAMETERS AND RESULTS AS CONCATENATION ONE
!
!        STLN TOS
!        ADB   TOS
!        LXN   B                        XNB TO WORK AREA
!        LB    @DR                      CURRENT LENGTH TO B
!        STB   TOS                      KEEP FOR THE MOVE
!        ADB   (%XNB+2)                 ADD OLD LENGTH
!        INCA  1                        PAST LENGTH BYTE
!        CYD   0                        BECOMES SOURCE STRING
!        LD    (%XNB+0)                 GET DESCRIPTOR TO WK STRING
!        MODD  (%XNB+2)                 MOVE ON PAST FIRST STRING
!        LDB   TOS                      TO MOVE RIGHT AMOUNT
!        MV    L=DR
!        STB   (%XNB+2)                 UP DATE WK STRING LENGTH
!        CPB   255
!        JCC   2,CAPACITY EXCEEDED
!        LD    (%XNB+0)                 SET UP DR WITH RESULT
!        LDB   B                        CURRENT LENGTH AS BOUND
!        INCA  -1                       TO POINT AT LENGTH BYTE
!        CYD   0                        TO ACC AS WELL
!        J     TOS                      RETURN
      %IF PLINK(20)=0 %THEN ->P21
      FILL(20)
      PF1(STLN,0,TOS,0)
      PF1(ADB,0,TOS,0)
      PF1(LXN,0,BREG,0)
      PF1(LB,2,7,0)
      PF1(STB,0,TOS,0)
      PF1(ADB,0,XNB,8)
      PSF1(INCA,0,1)
      PSF1(CYD,0,0)
      PF1(LD,0,XNB,0)
      PF1(MODD,0,XNB,8)
      PF1(LDB,0,TOS,0)
      PF2(MV,1,0,0,0,0)
      PF1(STB,0,XNB,8)
      PF1(CPB,0,0,255)
      PF3(JCC,2,0,(PLABS(9)-CA)//2)
      PF1(LD,0,XNB,0)
      PF1(LDB,0,BREG,0)
      PSF1(INCA,0,-1)
      PSF1(CYD,0,0)
      PF1(JUNC,0,TOS,0)
P21:
!
! THE STOP SEQUENCE
! CALL %SYSTEMROUTINE STOP(NO PARAMETERS)
!
!STOP1   PRCL   4
!        LXN   (LNB+4)
!        RALN  5
!        CALL  ((XNB+STOPEPDISP))       ! **PLEASE DONT COME BACK**
!
         %IF PLINK(21)=0 %THEN ->P22
         FILL(21)
         CXREF('S#STOP',0,2,J)
         PSF1(PRCL,0,4)
         PSF1(LXN,1,16)
         PSF1(RALN,0,5)
         PF1(CALL,2,XNB,J)
         PF1(X'4E',0,0,X'B00B');        ! IDLE B00B
P22:
         %RETURN
%ROUTINE FILL(%INTEGER LAB)
!***********************************************************************
!*       FILL JUMPS TO THIS LAB WITH JUMP TO CURRENT ADDRESS           *
!***********************************************************************
%INTEGER AT,INSTRN,SPARE
         %WHILE PLINK(LAB)#0 %CYCLE
             POP(PLINK(LAB),AT,INSTRN,SPARE)
            INSTRN=INSTRN!(CA-AT)>>1
             PLUG(1,AT,INSTRN,4)
         %REPEAT
         PLABS(LAB)=CA
%END
%END
%ROUTINE DUMP CONSTS
!***********************************************************************
!*    OUTPUT THE CONSTANT TABLE AND MAKE ANY RELEVANT RELOCATIONS      *
!***********************************************************************
%ROUTINESPEC DOIT(%INTEGER VAL)
%INTEGER I,J,K,DISP
      LPUT(1,CONSTPTR*4,CA,ADDR(CTABLE(0))) %IF CONSTPTR#0
!*DELSTART
      %IF DCOMP#0 %START
         PRINTSTRING("
CONSTANT TABLE")
         I=0
         %CYCLE
            NEWLINE
            PRHEX(CA+4*I,5)
            %CYCLE J=0,1,7
               SPACES(2)
               PRHEX(CTABLE(I+J),8)
            %REPEAT
            SPACE
            %CYCLE J=0,1,31
               K=BYTEINTEGER(ADDR(CTABLE(I))+J)
               %IF K<31 %OR K>95 %THEN K=32
               PRINT SYMBOL(K)
            %REPEAT
            I=I+8
            %EXIT %IF I>=CONSTPTR
         %REPEAT
      %FINISH
!*DELEND
!
      DISP=CA//2;                     ! RELOCATION FACTOR
      %WHILE CREFHEAD#0 %CYCLE
         POP(CREFHEAD,I,J,K)
         DOIT(I)
         %IF J#0 %THEN DOIT(J)
         %IF K#0 %THEN DOIT(K)
      %REPEAT
      CA=CA+4*((CONSTPTR+1)&(-2))
      %RETURN
%ROUTINE DOIT(%INTEGER VAL)
!***********************************************************************
!*    IF VAL +VE THEN VAL IS CODE ADDRESS FOR LPUT(18) UPDATE          *
!*    IF VAL -VE IT IS GLAWRDADDRR<<16!CTABLE WRD ADDR                 *
!*    THE GLA WORD IS TO RELOCATED BY HEAD OF CODE(ALREADY DONE)       *
!*    HOWEVER THE GLAWORD NEEDS UPDATING FROM  REL CTABLE TO REL CODE  *
!***********************************************************************
%INTEGER I,J
      %IF VAL>0 %THEN LPUT(18,0,VAL,DISP) %ELSE %START
         I=(VAL>>16&X'7FFF')<<2;        ! GLA BYTE ADDRESS
         J=4*(VAL&X'FFFF')+CA;          ! CTABLE ENTRY REL HD OF CODE
         PLUG(2,I,J,4);                 ! UPDATE THE GLA WORD
      %FINISH
%END
%END
%END;                                   ! OF SUBBLOCK CONTAINING PASS2
         %ROUTINE MESSAGE(%INTEGER N)
!***********************************************************************
!*       OUTPUTS AN ERROR MESSAGE STORED IN A COMPRESSED FORMAT        *
!***********************************************************************
%CONSTBYTEINTEGERARRAY WORD(0: 330)=0,%C
   1,   1,   2,   3,   0,   2,   4,   5,
   7,   8,   4,   9,  10,  11,   7,   5,
   9,   4,  12,   0,   6,   9,   4,   7,
   8,   7,  10,   7,   8,   0,   8,  13,
  14,  11,  16,   9,  13,  14,  11,  16,
  10,  13,  14,  11,  16,  11,   4,  11,
   7,   0,  13,   1,  18,   0,   0,  14,
   2,   3,  20,   0,  15,  18,  20,   0,
   0,  16,  10,  11,   7,   0,  17,  11,
  21,  10,   0,  18,   9,  23,  12,   0,
  19,  24,  25,  26,  14,  20,   9,  10,
  27,  28,  22,  30,  14,  11,  16,  23,
  21,  10,  27,  28,  24,  31,  27,  32,
  28,  25,  34,  35,  11,  32,  26,  37,
  38,  24,  39,  28,  21,  40,  18,   0,
  29,  41,  11,  42,   0,  30,  44,  45,
  26,  46,  31,  48,  45,  26,  46,  34,
   2,   3,  49,   0,  35,   2,   3,  21,
  49,  36,  50,  37,  25,   0,  39,  31,
  52,   0,   0,  40,  23,  53,   0,   0,
  42,  55,  35,  27,  28,  43,  56,  57,
  45,   0,  44,  50,  58,   0,   0,  45,
  24,  25,  26,  58,  47,  50,  59,   0,
   0,  48,  60,  61,  27,  38,  51,  62,
   2,   3,   0,  52,   1,  18,  63,  62,
  53,  62,  18,   0,   0,  54,  64,  45,
  26,  46,  57,  65,  18,   0,   0,  62,
  11,  66,  10,   0,  64,  67,  18,   0,
   0,  65,  67,  11,  27,  66,  66,  50,
  69,  70,   0,  67,  11,  69,  10,   0,
  69,  67,  45,  26,  46,  70,  50,  55,
  23,   0,  71,  35,  27,  55,  28,  72,
  50,  55,  72,   0,  73,  74,  45,  26,
  46,  74,  74,  24,  66,   0,  81,  50,
  76,   0,   0,  82,  41,  11,  78,  10,
  83,  80,  76,   0,   0,  84,  50,  69,
  70,   0,  85,  81,   0,   0,   0,  98,
  84,   0,   0,   0,  99,  84,   0,   0,
   0, 103,  87,   2,  88,   0, 104,   2,
   3,  87,   0, 106,  55,  58,   2,  88,
 108,  89,  61,  27,  38, 127,  90,   0,
   0,   0
 %CONSTINTEGERARRAY LETT(0: 92)=0,%C
X'48B02868',X'51EF0000',X'342EC800',X'30222B00',
X'25D60B13',X'13EF9000',X'4CB40000',X'52E91940',
X'4EE9A0D0',X'382D2800',X'39F40000',X'16527C80',
X'19F26858',X'40320B4B',X'50B29800',X'067F9C0B',
X'0C000000',X'35339A5D',X'1C000000',X'15C49800',
X'49F5A25D',X'14000000',X'10A36380',X'5E4F71C0',
X'39E00000',X'3CC00000',X'25C00000',X'171094E7',
X'38000000',X'0474A858',X'48A16000',X'25D429CB',
X'48000000',X'0F236140',X'58324845',X'30A00000',
X'18356500',X'4E8D7500',X'30B62B00',X'09E4C800',
X'31130000',X'10B3A3A9',X'38000000',X'48B4AC9C',
X'3EB40000',X'0DEEA171',X'50000000',X'48B3AB28',
X'30B62B26',X'258C29C3',X'30000000',X'17107500',
X'35338303',X'0CA40000',X'4E924B8E',X'06520E40',
X'25D3490A',X'0DEE9D00',X'15932800',X'4EA20000',
X'0D019000',X'192E4CD0',X'06800000',X'1709A000',
X'08A74B80',X'19F26868',X'4EA2705B',X'14000000',
X'48A37C88',X'3E059069',X'38000000',X'3E059069',
X'3E400000',X'48B37B2B',X'512F7000',X'16354D83',
X'30AE1940',X'41E9750B',X'48000000',X'39EE0000',
X'112D2BA7',X'25EE0B13',X'53200000',X'04849167',
X'4C224B13',X'53200000',X'382D2CC0',X'31EE3800',
X'15A00000',X'4CA5FA5B',X'43ED0BAB',X'05800000'
%INTEGER I,J,K,M,Q,S
      PRINTSTRING(' (')
      I=-4
      %UNTIL N=WORD(I) %OR I= 326 %THEN I=I+5
      %CYCLE J=1,1,4
         K=WORD(I+J)
         %IF K=0 %THEN %EXIT
         SPACE %UNLESS J=1
         %UNTIL M&1=0 %CYCLE
            M=LETT(K); S=26
            %UNTIL S<0 %CYCLE
               Q=M>>S&31; 
               %IF Q=31 %THEN Q=-32
               %IF Q\=0 %THEN PRINT SYMBOL(Q+64)
               S=S-5
            %REPEAT
            K=K+1
         %REPEAT
      %REPEAT
      PRINTSTRING(') ')
%END
%ROUTINE FAULT(%INTEGER N, FNAME)
%INTEGER I, J, QP
!*DELSTART
         %MONITOR %IF SMAP#0 %OR PRINTMAP#0
!*DELEND
         QP=Q
         %IF N=100 %THEN %START
           PRINTSTRING('
*    FAILED TO ANALYSE LINE ')
            WRITE(LINE, 2)
            NEWLINE;  SPACES(5)
            FAULTY=FAULTY+1
            %IF LINE#OLDLINE %THEN  PRINTSTRING(%C
"TEXT MODE FAILURE-- ERRONEOUS SOURCE LINE NOT AVAILABLE
") %AND %RETURN
            T=0;  J=0;  S=0
            %UNTIL (J=';' %AND Q>QMAX) %OR Q=LENGTH %CYCLE
               I=J;  J=BYTEINTEGER(FNAME+Q);! FNAME HAS ADDR(CC(0))
               %IF J>128 %AND I<128 %THEN PRINTSTRING(' %') %AND T=T+2
               %IF I>128 %AND J<128 %THEN SPACE %AND T=T+1
               PRINT SYMBOL(J)
               T=T+1
               %IF Q=QMAX %THEN S=T
               Q=Q+1
            %REPEAT
            %IF Q=QMAX %THEN S=T
!
            %IF S<115 %THEN %START
               NEWLINE;  SPACES(S+4)
               PRINT SYMBOL('!')
            %FINISH
            NEWLINE
         %FINISH %ELSE %START
            PRINTSTRING('
*');  WRITE(LINE, 4)
            I=3;  I=3*LEVEL %IF LIST=0;  SPACES(I)
            PARMOPT=1;  FAULTY=FAULTY+1
            INHCODE=1;                     ! STOP GENERATING CODE
            PRINTSTRING('FAULT');  WRITE(N, 2)
            MESSAGE(N)
            %IF N>100 %THEN %START
               PRINTSTRING(' DISASTER ')
               %MONITOR; %STOP
            %FINISH
            %IF N=45 %THEN WRITE(FNAME,1) %ELSE %START
               PRINTNAME(FNAME) %UNLESS FNAME=0
            %FINISH
         %FINISH
         %IF TTOPUT#0 %THEN %START
            Q=QP; TTOPUT=0
            SELECT OUTPUT(87)
            FAULT(N, FNAME)
            FAULTY=FAULTY-1
            NEWLINE
            SELECT OUTPUT(82)
            TTOPUT=1
         %FINISH
         %IF N>100 %THEN %MONITOR %AND %STOP
%END
%ROUTINE WARN(%INTEGER N,V)
%CONSTSTRING(23)%ARRAY MESS(1:5)=' SHORT INTEGER USED',
                                 ' NAME ? NOT USED ',
                                 ' LABEL ? NOT USED',
                                 ' GLOBAL CYCLE CONTROL ?',
                                 ' NAME ? NOT ADDRESSABLE'
         %STRING(30) T; %STRING(120) S
         %IF MESS(N)->S.("?").T %THEN S=S.STRING(DICTBASE+WORD(V)) %C
            .T %ELSE S=MESS(N)
         PRINTSTRING('
?  WARNING :- '.S.' AT LINE NO')
         WRITE(LINE,1)
         NEWLINE
%END
                                        ! THE NEXT 4 ROUTINES CAN BE 
                                        !MACROISED USING MVC
!
%ROUTINE TOAR2(%INTEGER PTR,VALUE)
!QOUT;         A(PTR+1)<-VALUE
!QOUT;         A(PTR)<-VALUE>>8
!QIN      *LSS_VALUE
!QIN      *LDTB_X'58000002'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *ST_(%DR)
%END
%ROUTINE TOAR4(%INTEGER PTR, VALUE)
!QOUT;%INTEGER I
!QOUT;         %CYCLE I=0,1,3
!QOUT;            A(PTR+I)=BYTE INTEGER(ADDR(VALUE)+I)
!QOUT;         %REPEAT
!QIN      *LSS_VALUE
!QIN      *LDTB_X'58000004'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *ST_(%DR)
%END
%ROUTINE TOAR8(%INTEGER PTR, %LONGREAL VALUE)
!QOUT;%INTEGER I
!QOUT;         %CYCLE I=0,1,7
!QOUT;            A(PTR+I)=BYTE INTEGER(ADDR(VALUE)+I)
!QOUT;         %REPEAT
!QIN      *LSD_VALUE
!QIN      *LDTB_X'58000008'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *ST_(%DR)
%END
%INTEGERFN FROMAR2(%INTEGER PTR)
!QOUT;         %RESULT=A(PTR)<<8!A(PTR+1)
!QIN      *LDTB_X'58000002'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *LSS_(%DR)
!QIN      *EXIT_-64
%END
%INTEGERFN FROMAR4(%INTEGER PTR)
!QOUT;         %RESULT=A(PTR)<<24!A(PTR+1)<<16!A(PTR+2)<<8!A(PTR+3)
!QIN      *LDTB_X'58000004'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *LSS_(%DR)
!QIN      *EXIT_-64
%END
%LONGREALFN FROMAR8(%INTEGER PTR)
!QOUT;%LONGREAL AD
!QOUT;%INTEGER I
!QOUT;         %CYCLE I=0,1,7
!QOUT;            BYTE INTEGER(ADDR(AD)+I)=A(PTR+I)
!QOUT;         %REPEAT
!QOUT;         %RESULT=AD
!QIN      *LDTB_X'58000008'
!QIN      *LDA_A+4
!QIN      *INCA_PTR
!QIN      *LSD_(%DR)
!QIN      *EXIT_-64
%END
%ROUTINE PRINTNAME(%INTEGER N)
%INTEGER V, K
         SPACE;  V=WORD(N)
         K=BYTE INTEGER(DICTBASE+V)
         %IF K=0 %THEN PRINTSTRING('???') %ELSE %C
            PRINTSTRING(STRING(DICTBASE+V))
 %END
!*DELSTART
%ROUTINE PRHEX(%INTEGER VALUE, PLACES)
%CONSTBYTEINTEGERARRAY HEX(0:15)='0','1','2','3','4',
               '5','6','7','8','9','A','B','C','D','E','F'
%INTEGER I
         %CYCLE I=PLACES<<2-4, -4, 0
            PRINT SYMBOL(HEX(VALUE>>I&15))
         %REPEAT
%END
         %ROUTINE PRINT LIST(%INTEGER HEAD)
         %INTEGER I,J,K
         %WHILE HEAD#0 %CYCLE
            FROM123(HEAD,I,J,K)
            NEWLINE
            WRITE(HEAD,3)
            SPACES(3)
            PRHEX(I,8)
            SPACES(3)
            PRHEX(J,8)
            SPACES(3)
            PRHEX(K,8)
            NEWLINE
            MLINK(HEAD)
         %REPEAT
         %END
!
%ROUTINE CHECK ASL
!***********************************************************************
!*    CHECK ASL AND PRINT NO OF FREE CELLS. DEBUGGING SERVICE ONLY     *
!***********************************************************************
%INTEGER N,Q
      Q=ASL; N=0
      %WHILE Q#0 %CYCLE
         N=N+1
         Q=ASLIST(Q)_LINK
      %REPEAT
      NEWLINE
      PRINTSTRING('FREE CELLS AFTER LINE ')
      WRITE(LINE,3)
      PRINTSYMBOL('=')
      WRITE(N,3)
%END
!*DELEND
%INTEGERFN MORE SPACE
!***********************************************************************
!*    FORMATS UP SOME MORE OF THE ASL                                  *
!***********************************************************************
%INTEGER I,N
      N=ASL CUR BTM-1
      ASL CUR BTM=ASL CUR BTM-(NNAMES+1)//8
      %IF ASL CUR BTM<=1 %THEN ASL CUR BTM=1
      CONST LIMIT=4*ASL CUR BTM-8
      %IF ASL CUR BTM>=N %OR CONST PTR>CONST LIMIT %THEN FAULT(107,0)
      %CYCLE I=ASL CUR BTM,1,N-1
         ASLIST(I+1)_LINK=I
      %REPEAT
      ASLIST(ASL CUR BTM)_LINK=0
      ASL=N; %RESULT=N
%END
%INTEGERFN NEW CELL
!***********************************************************************
!*       PROVIDE A NEW LIST PROCESSING CELL. CRAPOUT IF NONE AVAILABLE *
!***********************************************************************
%INTEGER I
         %IF ASL=0 %THEN ASL=MORE SPACE
         I=ASL; ASL=ASLIST(ASL)_LINK
         ASLIST(I)_LINK=0
         %RESULT =I
%END
%ROUTINE PUSH(%INTEGERNAME CELL, %INTEGER S1, S2, S3)
!***********************************************************************
!*       PUSH A CELL CONTAINING THE 3 STREAMS OF INFORMATION GIVEN     *
!*       ONTO THE TOP OF THE LIST POINTED AT BY CELL.                  *
!***********************************************************************
%RECORDNAME LCELL(LISTF)
%INTEGER I
         I=ASL
         %IF I=0 %THEN I=MORE SPACE
         LCELL==ASLIST(I)
         ASL=LCELL_LINK
         LCELL_LINK=CELL; CELL=I
         LCELL_S1=S1
         LCELL_S2=S2
         LCELL_S3=S3
%END
%ROUTINE POP(%INTEGERNAME CELL, S1, S2, S3)
!***********************************************************************
!*       COPY THE INFORMATION FROM THE TOP CELL OF LIST 'CELL' INTO    *
!*         S1,S2&S3 AND THEN POP THE LIST UP 1 CELL. EMPTYLIST GIVE -1S*
!***********************************************************************
%RECORDNAME LCELL(LISTF)
%INTEGER I
         I=CELL; LCELL==ASLIST(I)
         S1=LCELL_S1
         S2=LCELL_S2
         S3=LCELL_S3
         %IF I# 0 %THEN %START
            CELL=LCELL_LINK
            LCELL_LINK=ASL
            ASL=I
         %FINISH
%END
%ROUTINE REPLACE1(%INTEGER CELL, S1)
         ASLIST(CELL)_S1=S1
%END
%ROUTINE REPLACE2(%INTEGER CELL, S2)
         ASLIST(CELL)_S2=S2
%END
%ROUTINE REPLACE3(%INTEGER CELL, S3)
         ASLIST(CELL)_S3=S3
%END
         %ROUTINE BINSERT(%INTEGERNAME TOP,BOT,%INTEGER S1,S2,S3)
!***********************************************************************
!*       INSERT A CELL AT THE BOTTOM OF A LIST                         *
!*       UPDATING TOP AND BOTTOM POINTERS APPROPIATELY                 *
!***********************************************************************
%INTEGER I
%RECORDNAME LCELL(LISTF)
         I=ASL
         %IF I=0 %THEN I=MORE SPACE
         LCELL==ASLIST(I)
         ASL=LCELL_LINK
         LCELL_S1=S1; LCELL_S2=S2
         LCELL_S3=S3; LCELL_LINK=0
         J=BOT
         %IF J=0 %THEN BOT=I %AND TOP=BOT %ELSE %START
            ASLIST(J)_LINK=I
            BOT=I
         %FINISH
%END
%ROUTINE INSERT AT END(%INTEGERNAME CELL, %INTEGER S1, S2, S3)
!***********************************************************************
!*       ADD A CELL TO THE BOTTOM OF THE LIST HEADED BY 'CELL'         *
!***********************************************************************
%INTEGER I,J,N
%RECORDNAME LCELL(LISTF)
         I=CELL; J=I
         %WHILE I#0 %THEN J=I %AND I=ASLIST(J)_LINK
         N=ASL
         %IF N=0 %THEN N=MORE SPACE
         LCELL==ASLIST(N)
         ASL=LCELL_LINK
         %IF J=0 %THEN CELL=N %ELSE ASLIST(J)_LINK=N
         LCELL_S1=S1
         LCELL_S2=S2
         LCELL_S3=S3
         LCELL_LINK=0
%END
%ROUTINE REPLACE123(%INTEGER CELL,S1,S2,S3)
         ASLIST(CELL)_S1=S1
         ASLIST(CELL)_S2=S2
         ASLIST(CELL)_S3=S3
%END
%ROUTINE MLINK(%INTEGERNAME CELL)
         CELL=ASLIST(CELL)_LINK
%END
%INTEGERFN FIND(%INTEGER LAB, LIST)
!***********************************************************************
!*       THIS FUNCTION SEARCHES LIST 'LIST' FOR LAB IN STREAM2 AND     *
!*       RETURNS THE CORRESPONDING CELL NO.IT USED FOR MORE THAN       *
!*       SCANNING LABEL LISTS.                                         *
!***********************************************************************
         %WHILE LIST#0 %CYCLE
            %RESULT=LIST %IF LAB=ASLIST(LIST)_S2
            LIST=ASLIST(LIST)_LINK
         %REPEAT
         %RESULT=-1
%END
%INTEGERFN FIND3(%INTEGER S3, LIST)
!***********************************************************************
!*       SEARCHES LIST FOR S3 IN STREAM 3                              *
!*       RETURNS CELL NO AS RESULT                                     *
!***********************************************************************
         %WHILE LIST#0 %CYCLE
            %RESULT=LIST %IF S3=ASLIST(LIST)_S3
            LIST=ASLIST(LIST)_LINK
         %REPEAT
         %RESULT=-1
%END
%ROUTINE FROM123(%INTEGER CELL, %INTEGERNAME S1, S2, S3)
!***********************************************************************
!*       ALL THE FROMS RETURN INFO FROM CELLS OF A LIST WITHOUT        *
!*       AFFECTING THE LIST IN ANY WAY.                                *
!***********************************************************************
         LCELL==ASLIST(CELL)
         S1=LCELL_S1
         S2=LCELL_S2
         S3=LCELL_S3
%END
%ROUTINE FROM12(%INTEGER CELL, %INTEGERNAME S1, S2)
         LCELL==ASLIST(CELL)
         S1=LCELL_S1
         S2=LCELL_S2
%END
%INTEGERFN FROM1(%INTEGER CELL)
         %RESULT =ASLIST(CELL)_S1
%END
%INTEGERFN FROM2(%INTEGER CELL)
         %RESULT =ASLIST(CELL)_S2
%END
%INTEGERFN FROM3(%INTEGER CELL)
         %RESULT =ASLIST(CELL)_S3
%END
%ROUTINE CLEAR LIST(%INTEGERNAME OPHEAD)
!***********************************************************************
!*       THROW AWAY A COMPLETE LIST (MAY BE NULL!)                     *
!***********************************************************************
%INTEGER I, J
          I=OPHEAD; J=I
         %WHILE I#0 %THEN J=I %AND I=ASLIST(J)_LINK
         %IF J#0 %START
            ASLIST(J)_LINK=ASL
            ASL=OPHEAD; OPHEAD=0
         %FINISH
%END
!%ROUTINE CONCAT(%INTEGERNAME LIST1, LIST2)
!!***********************************************************************
!!*        ADDS LIST2 TO BOTTOM OF LIST1                                *
!!***********************************************************************
!%INTEGER I,J
!         I=LIST1
!         J=I
!         %WHILE I#0 %THEN J=I %AND I=ASLIST(J)_LINK
!         %IF J=0 %THEN LIST1=LIST2 %ELSE ASLIST(J)_LINK=LIST2
!         LIST2=0
!%END;                                   ! AN ERROR PUTS CELL TWICE ONTO
                                        ! FREE LIST - CATASTROPHIC!
%ENDOFPROGRAM