! IMP77 compiler  first pass

!###########################################################
! This program is a Copyright work.                        #
!                                                          #
! Over the last 40+ years a long and distinguished list of #
! institutions, individuals and other entities have made   #
! contributions to portions of this program and may have a #
! reasonable claim over rights to certain parts of the     #
! program.                                                 #
!                                                          #
! This version is therefore provided for education and     #
! demonstration purposes only                              #
!###########################################################

begin
    conststring(4) version = "8.4"

    !configuration parameters
    { minus one represents all bits set for an %integer     }
    { %integer could be 16,32,64 bits wide depending on the }
    { processor being targeted                              }
    { i.e 8086 (16 bits), 80386 (32 bits), i86_64 (64 bits) }
    constinteger minus one    = -1;
! Wee change needed to cross-compile the compiler when going from 16 bit to 32 bit world
!    %constinteger minus one    = 16_7fff;

    { now to set up various constants }
    constinteger max int      = ((minus one)>>1)//10
    constinteger max dig      = (minus one)>>1-maxint*10
    constinteger byte size    = 8;             !bits per byte
    constinteger max tag      = 800;           !max no. of tags
    constinteger max dict     = 6000;          !max extent of dictionary
    constinteger name bits    = 11;            !size of name table as a power of two
    constinteger max names    = 1<<namebits-1; !table limit (a mask, eg 255)
    owninteger   spare names  = max names
    constinteger lit max      = 50;            !max no. of constants/stat.
    constinteger rec size     = 520;           !size of analysis record
    constinteger dim limit    = 6;             !maximum array dimension

    !symbols
    constinteger ff     = 12;               !form feed
    constinteger marker = '^';              !marker for faults
    constinteger squote = '"';              !string quote
    constinteger cquote = '''';             !character quote

    !streams
    constinteger report = 0,  source = 1
    constinteger object = 1, listing = 2

    !types
    constinteger integer = 1
    constinteger real    = 2
    constinteger stringv = 3
    constinteger record  = 4

    !forms
    constinteger iform = integer<<4+1
    constinteger var = 91
    constinteger const   = 93
    constinteger swit    = 105
    constinteger comment = 22
    constinteger termin  = 20
    constinteger lab     = 3
    constinteger jump    = 54
    constinteger recfm = 4
    constinteger proc  = 7;                      !class for proc

    !phrase entries
    constinteger escdec   = 252
    constinteger escproc  = 253
    constinteger escarray = 254
    constinteger escrec   = 255

    !%recordformat arfm(%shortinteger class,sub,link,ptype,papp,pformat,x,pos);!imp77:
    recordformat arfm(integer class,sub,link,ptype,papp,pformat,x,pos)

    recordformat tagfm(integer app, format, integer flags, index, text, link)

    !flags
    !      *===.===.===.===.===.====.====.====.===.======.======*
    !      ! u ! c ! c ! p ! s ! a  ! o  ! pr ! s ! type ! form !
    !      ! 1 ! 1 ! 1 ! 1 ! 1 ! 1  ! 1  ! 1  ! 1 !  3   !  4   !
    !      *===^===^===^===^===^====^====^====^===^======^======*
    !        u   c   c   p   s   a    o    p    s    t      f
    !        s   l   o   a   u   n    w    r    p    y      o
    !        e   o   n   r   b   a    n    o    e    p      r
    !        d   s   s   a   n   m         t    c    e      m
    !            e   t   m   a   e     
    !            d       s   m
    !                        e
    !
    !                             

    constinteger used bit   = 2_1000000000000000
    constinteger closed     = 2_0100000000000000
    constinteger const bit  = 2_0010000000000000
    constinteger parameters = 2_0001000000000000
    constinteger subname    = 2_0000100000000000
    constinteger aname      = 2_0000010000000000
    constinteger own bit    = 2_0000001000000000
    constinteger prot       = 2_0000000100000000
    constinteger spec       = 2_0000000010000000

    constinteger trans bit  = 16_4000
    constinteger error      = 16_8000

    record(arfm)array ar(1:rec size)

    owninteger class        = 0;              !class of atom wanted
    owninteger x            = 0;              !usually last tag
    owninteger atom1        = 0;              !atom class (major)
    owninteger atom2        = 0;              !atom class (minor)
    owninteger subatom      = 0;              !extra info about atom
    owninteger type         = 0
    owninteger app          = 0
    owninteger format       = 0;              !atom info
    integer hash value
    owninteger faulty       = 0;              !fault indicator
    owninteger fault rate   = 0;              !fault rate count
    owninteger lines        = 0;              !current line number
    owninteger text line    = 0;              !starting line for string const
    owninteger margin       = 0;              !statement start margin
    owninteger error margin = 0
    owninteger error sym    = 0
    owninteger column       = 0
    owninteger stats        = 0;              !statements compiled
    owninteger mon pos      = 0;              !flag for diagnose
    owninteger sym          = nl;             !current input symbol
    owninteger symtype      = 0;              !type of current symbol
    owninteger quote        = 0;              !>0 strings, <0 chars
    owninteger end mark     = 0;              !%end flag
    owninteger cont         = ' '
    owninteger csym         = ' ';            !listing continuation marker
    owninteger decl         = 0;              !current declarator flags
    owninteger dim          = 0;              !arrayname dimension
    owninteger spec given   = 0

    owninteger escape class = 0;              !when and where to escape
    owninteger protection   = 0
    owninteger atom flags   = 0
    owninteger otype        = 0;              !current 'own' type
    owninteger reals ln     = 1;              ! =4 for %REALSLONG
    owninteger last1        = 0;              !previous atom class
    owninteger gen type     = 0
    owninteger ptype        = 0;              !current phrase type
    owninteger papp         = 0;              !current phrase parameters
    owninteger pformat      = 0;              !current phrase format
    owninteger force        = 0;              !force next ptype
    owninteger g            = 0
    owninteger gg           = 0
    owninteger map gg       = 0;              !grammar entries
    owninteger fdef         = 0;              !current format definition
    owninteger this         = -1;             !current recordformat tag
    owninteger nmin         = 0;              !analysis record atom pointer
    owninteger nmax         = 0;              !analysis record phrase pointer
    owninteger rbase        = 0;              !record format definition base
    owninteger dmax         = 1
    owninteger tmin         = max tag;        !upper bound on tags
    owninteger ss           = 0;              !source statement entry
    string(63) include file
    owninteger include list = 0
    owninteger include level= 0
    owninteger include      = 0;              !=0 unused, #0 being used
    owninteger perm         = 1;              !1 = compiling perm, 0 = program
    owninteger progmode     = 0;              !-1 = file, 1 = begin/eop
    owninteger sstype       = 0;              !-1:exec stat
                                              ! 0: declaration
                                              ! 1: block in
                                              ! 2: block out
    owninteger spec mode    = 0;              !>=0: definition
                                              ! -1: proc spec
                                              ! -2: recordformat
    owninteger ocount       = -1;             !own constants wanted
    owninteger limit        = 0;              !lookup limit
    owninteger copy         = 0;              !duplicate name flag
    owninteger order        = 0;              !out of sequence flag
    owninteger for warn     = 0;              !non-local flag
    owninteger dubious      = 0;              !flag for dubious statements
    owninteger dp           = 1
    owninteger pos1         = 0
    owninteger pos2         = 0;              !error position
    owninteger pos          = 0;              !input line index
    owninteger dimension    = 0;              !current array dimension
    owninteger local        = 0;              !search limit for locals
    owninteger fm base      = 0;              !entry for format decls
    owninteger search base  = 0;              !entry for record_names
    owninteger format list  = 0;              !size of current format list
    integer recid
    ownbyteintegerarray char(0:133) = ;   !input line
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10
    integerarray lit pool(0:lit max)
    owninteger lit          = 0;              !current literal (integer)
    owninteger lp           = 0;              !literals pointer
    owninteger block x      = 0;              !block tag
    owninteger list         = 1;              !<= to enable
    owninteger control      = 0
    owninteger diag         = 0;              !diagnose flags
    integerarray hash(0:max names)
    record(tagfm)array tag(0:max tag)
    integerarray dict(1:max dict)
    byteintegerarray buff(1:512)
    owninteger bp           = 0

    { grammar related constants }
    constinteger max grammar  = 1720
    owninteger gmin       = max grammar               ; ! upper bound on grammar
    constinteger manifest = 120, figurative = 130
    constinteger actions  = 180, phrasal    = 200

    constbyteintegerarray amap(0:15) = c
       89,   91,   92,  104,   94,   93,  105,  100,  101,  102,  103,  106,  107,  108,  109,   89
    !   ?     v     n     l    fm const  swit    rp    fp    mp    pp     a    an    na    nan    ?

    constbyteintegerarray atoms(0:15) = 89, 1, 1, 10,  9,  1, 10,  7,
                                          7, 7, 7,  4,  1,  4,  1, 89

    !*** start of generated tables ***
!    %include "i77.tables.imp"
   endoflist
conststring(8)array text(0:255) = c
"Z","VDEC","OWNVDEC","EXTVSPEC","ADEC","OWNADEC","EXTASPEC","PROC",
"PROCSPEC","FORMDEC","SWDEC","LDEC","FORMSPEC","","","",
"","","OPTION","COMMA","T","COLON","COMMENT","LB",
"ALIAS","RB","SUB","ARRAYD","STYPE","ARRAY","NAME","PROCD",
"FNMAP","SWITCH","OWN","EXTERNAL","STRING","RECORD","FORMAT","SPEC",
"MCODE","LABEL","OP1","OP2","OP3","SIGN","UOP","MOD",
"DOT","COMP","ACOMP","EQ","EQEQ","JAM","JUMP","RESOP",
"AND","OR","NOT","WHILE","UNTIL","FOR","CWORD","EXIT",
"ON","SIGNAL","THEN","START","ELSE","FINISH","FELSE","CYCLE",
"REPEAT","PROGRAM","BEGIN","END","ENDPROG","ENDPERM","FRESULT","MRESULT",
"BACK","MONITOR","STOP","LIST","REALSLN","CONTROL","INCLUDE","MASS",
"RTYPE","ADDOP","IDENT","V","N","CONST","FM","",
"R","F","M","P","RP","FP","MP","PP",
"L","S","A","AN","NA","NAN","","",
"","","","","","","","",
"%MSTART","%CLEAR","%PRED","","%DUBIOUS","%DUP","%PIN","%POUT",
"%EDUP","","PIDENT","CIDENT","OIDENT","FNAME","SWID","DOTL",
"DOTR","ASEP","CSEP","OSEP","PSEP","ARB","BPLRB","ORB",
"PRB","CRB","RCRB","RECRB","RECLB","LAB","MLAB","SLAB",
"XNAME","OWNT","DBSEP","PCONST","CMOD","CSIGN","CUOP","COP1",
"COP2","COP3","INDEF","XELSE","CRESOP","NLAB","RUNTIL","ACONST",
"ORRB","FMANY","OSTRING","FMLB","FMRB","FMOR","RANGERB","FSID",
"","","","","","%DUMMY","%DECL","%TYPE",
"%ZERO","%APPLY","%PROT","%SETPROT","%PTYPE","%GAPP","%LOCAL","%GUARD",
"%MCODE","%CDUMMY","%SETTYPE","%OPER","%PARAM","%BLOCK","%OTHER","%COMPILE",
"APP","BASEAPP","APP2","APP3","APP4","APP5","APP6","ADEFN",
"NPARM","SWDEF","SWIDS","CIEXP","RCONST","SCONST","ARRAYP","XIMP",
"IMP","COND","SCOND","EXP1","EXP2","SEXP","IEXP","IEXP1",
"IEXP2","ISEXP","SEQ","FDEF","EXP","NARRAYP","STRUCT","RESEXP",
"BPL","CONSTB","FITEM","MOREA","CLIST","FPP","FPP0","FPP1",
"FPP2","INITVAR","RECEXP","EIMP","IDENTS","RANGE","RCONSTB","VARP",
"INITDEC","","","","ESCDEC","ESCPROC","ESCARRAY","ESCREC"

constinteger gmax1=719
owninteger gmax=719
constinteger imp phrase =25

!  FLAG<1> 0<1> SS<2> 0<3> T<1> LINK<8>
constshortintegerarray initial(0:119) = c
    24,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    23,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,
    20,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0, -32551,    0,
    0,    0,    0,    13,    0,    14,    4, -32557,
    16, -32550,    0,    0,    5,    6,    3,    12,
    15,    8,    7,    9,    10,    11, -32558, -32554,
 -32559, -32552, -32553,    18,    22,    17,    21,    19,
    0,    0,    0, -32562, -32560,    0,    0,    0,
 -32561,    0,    0,    0,    0,    0,    0,    0,
    1,    2,    0, -32556,    0, -32555,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0

constbyteintegerarray atomic(130:179) = c
  90,  90,  90,  90,  90,  48,  48,  19,
  19,  19,  19,  25,  25,  25,  25,  25,
  25,  25,  23, 104, 104, 105,  30,  20,
  21,  93,  47,  45,  46,  42,  43,  44,
  40,  68,  55, 104,  60,  93,  25,  40,
  93,  23,  25,  57,  25,  90, 176, 177,
 178, 179

ownshortintegerarray phrase(200:255) = C
  0, 564, 565, 567, 569, 571, 573, 562,
 614, 203, 200, 602, 478, 480, 624, 298,
 206, 308, 318, 433, 426, 437, 444, 458,
 453, 461, 467, 482, 402, 627, 629, 603,
 521, 511, 486, 502, 575, 527, 528, 543,
 550, 578, 397, 287, 197, 636, 516, 621,
 167,  0,  0,  0, 640, 693, 701, 709

!  MORE<1> 0<1> ORDER<2> TYPE<4> CLASS<8>
ownshortintegerarray gram(0:max grammar) = c
    0, -28523, -28521, -28602, -32706, -28509, -28603, -24502,
 -24503, -20405, -20404, -28595, -32697, -32709, -16323, -28600,
 -32704, -28587, -28589, -32681, -16344, -28586, -28588, -12270,
 -32586,   216, -12287, -16380,  -8185,  -8184, -12285, -12286,
 -12283, -12282, -12279, -12276, -16373,  20490, -32706, -32701,
   216, -16364, -28610, -28613, -28612,  16445,   217, -16364,
    62, -32701,  16450, -16364,   5346, -16364,   166, -16344,
   4332,   130, -16360, -16361,   126,   217, -32701,   216,
 -16364,  16450, -32700,  16404, -32701, -32706,   216,  16405,
  16407, -16222,   8414,   130,   217, -32697,  16450,   1250,
   4307,   4318,   192,    93,   170,    90,   207, -16365,
  16404,    90, -16360, -16365,  16404,   241, -16365,  16404,
   132,   132, -16360,   4329, -16365,  16404,   133,   175,
    90, -16365,  16404,   209, -16365,  16404,   4313,   217,
  16451,   4263,  16384,  16384,   120,   216, -32700,  16404,
 -32706,  16404,   243,  16409,   454, -32685,  16404,   454,
   248, -16365,  16404,   4263,   194, -16360,   4329, -32717,
  16404,   4263,  16407,   454,   237,   127,   215,   454,
   4263,  16384, -16364,   1502, -32629, -16361,   153, -32606,
   222,   143, -32629,   153,   454,   126,  16409,   454,
  16384,   234, -16365, -32595,   147, -32678,   234,   193,
 -32677, -32676, -32661,   109, -32717,    53,    52,    52,
    52,   194,   194,   194, -28581,   4188,   194, -28566,
   4203,   194, -28564,   4205,   4580,  16429,   183,   183,
   186,   186, -28583,    0,   9437,    90, -16365,    0,
   134, -16365,    0,   210,   4329,   199, -32677, -32672,
 -32676, -32688, -32690, -32705, -32661, -32659, -32689, -32686,
 -32687, -16330,    65, -32716,   186, -28583, -32717, -32715,
 -32713,    52, -32664,   4201,   186, -32717, -32715,    55,
 -16328,    0,   197,   197,    52,    52,   197, -28581,
 -28580,   186, -28581,   4188,   4318,   194, -28581,   4188,
   9437,   194,   194,   454,  16407,   216,   194, -28566,
 -28565,   186, -28566,   4203,   194, -28564, -28563,   186,
 -28564,   4205,   183,   183,   186,   183, -16365,    0,
   183,   4580,  16429,   5095,   9444,   5348,   186, -28583,
 -16328,    0,  16409, -16365,    0,   9437,   5348,   217,
 -32701,  16450, -32701,   216, -32700,    0, -32701, -32706,
   216,   243,   217, -16318,    0, -32552,    0, -32700,
    0, -32706,    0,   215, -32550,   228, -28616, -28615,
    0,   4096,   218,   218, -28616,    0, -32677, -32676,
 -16361, -32710, -32669, -32662, -32661, -32660, -32659,   740,
 -32039,   740, -32719,   4096,   194, -32719, -32718, -32604,
 -32726, -32725, -32724, -32720,   4096,   710,   6116, -32719,
    0,   710,   6116, -28581,   4188,   218,   122,    50,
  16409, -32726, -32725, -32724, -32719,   4096,   710,   454,
   195,   195,   195,   454, -28581,   4188,   194, -28566,
 -28565, -28564,   4205,   195,   195,   195,   710,   4836,
   5095,   4829, -32726, -32725, -32724, -32719,   4096,   4827,
   4828,   454, -32720, -32719,   4096,   4829,   4827,   4828,
   194, -32719,    0,   710,   4836, -16291, -32677,    92,
   184,   121, -28581, -28580, -32722, -32723,   4317, -32726,
 -32725, -32724,    0,   183, -32726, -32725, -32724, -32720,
    0,   4316,   195,   195,   195,   454, -28581,   4188,
   4315,   183,   4317, -32726, -32725,    0,   195,   195,
   4315,   4317, -32726,    0,   195, -32677, -32676, -16361,
  16431,   228,   228,    47, -32610, -32611,   5345, -32609,
 -32608, -32607,    0,   4320,   4319,   5345, -32609, -32608,
    0,   4319,   5345, -32609,    0, -32613, -16361,  16431,
   222,   222,   156, -32677,    92,   183,   186,   1222,
  16435,   228,  16403,   4324,   138,   8420, -32723,   4189,
    93,   454,   148, -32674,  16546,  16409, -32597,   182,
 -16383,  16388,   234, -16365, -32595,   172, -32678,   234,
    90,   244,   246, -16365,    0,   235, -32678,   234,
 -16365,   246, -16365,    0, -32678,   234,    90,  16407,
   222,  16405,   222,   145,  16407,   222,  16405,   222,
   146,  16407,   1252,   154,   5348, -16365,   142,   126,
   182, -16383,  16391,    90, -16365,   127, -32678,   238,
    90,   125,   239, -16365,   8319,   8430,   128,   126,
 -16361,   127,   190,   240,   189,  16409,   182, -16383,
  16391,    90, -16365,    0, -32678,   240,    90,  16623,
 -16365,    0,   244,   232,   1252,   1252,   137,   1252,
   137,   1252,   137,   1252,   137,   1252,   137,   222,
 -16365,    0,   131,   194, -16360, -16333, -16332,   124,
   181, -16292, -16277,  16493, -31802,   5342, -28581,   4188,
   4263,   181,   186,   454,  16475,   183, -28583,   199,
   5598,   9438,   222, -32677, -32676,  16407,   186,   228,
   135,  16409, -32632,    0, -32677,    92, -32677, -32676,
 -32662, -32661, -32660, -32659,   165, -32677,    92,   188,
 -32662,   107,   188, -32660,   109, -32732,    37, -16344,
   4318,   148, -32674,  16424,   222,  16405,   222,   174,
 -28644, -32734, -32680, -28641, -32733, -32730, -32735, -32727,
 -32738,   4326, -32738, -32739, -32741, -32736,   199, -28644,
 -32680, -28641,   4326, -32739, -32741,   199, -32738, -32739,
 -32741, -32736, -32729,   199, -32616,   199, -32739, -32741,
 -32729,   199, -32616, -32729,   199, -28644, -32680,   4326,
 -32738, -32739, -32741,   199,   245,   4318,   245,  16409,
   152,   4318,  16409,   152,   245, -32672, -32671, -32670,
    99,  16407,   200,   144,   185, -32677,    92,  16407,
 -32582,   200,   200,   187,   141, -32677,    92,  16410,
   191, -32677, -32676, -32662, -32661, -32660,   109,   198,
0(max grammar-gmax1)

ownshortintegerarray glink(0:max grammar) = c
   -1,    71,    72,    38,    46,    47,    67,    67,
    75,    67,    0,    67,    51,    76,    79,    53,
    55,    80,    67,    81,    82,    83,    67,    84,
    26,    41,    85,    86,    57,    57,    89,    93,
    96,    97,   102,   103,   104,   107,    46,    67,
    67,    0,   110,   110,   111,    52,    49,    0,
    61,    67,    62,    0,    67,    0,   111,   112,
   112,    58,   113,   114,   115,    64,    67,    66,
   116,   117,    68,    0,    67,   122,    67,    0,
    73,   123,   123,    67,    77,    67,    40,    77,
    67,    67,    0,   124,   127,   128,    87,    86,
    0,    90,   131,    89,    0,    94,    93,    0,
   132,    98,   137,   100,    97,    0,   138,    67,
   105,   104,    0,   108,   107,    0,    67,    67,
    67,   139,   140,   141,    0,   118,   120,   116,
   142,   116,    67,    71,   125,    67,    0,    67,
   129,    85,    0,   143,   133,   144,   135,   145,
    0,   156,   157,    59,   158,    67,   119,    91,
   159,   146,   145,   148,   146,   151,    0,   153,
   153,   154,   146,    0,    99,   160,    67,   134,
   161,   162,   165,   161,   141,   162,   162,   168,
   172,   174,   175,   176,   177,   178,   179,   182,
   185,   188,   189,   180,   190,   190,   183,   191,
   191,   186,   191,   191,    0,   188,   192,   193,
   194,    0,   196,    0,    0,   198,   197,    0,
   201,   200,    0,   204,   205,    0,   228,   232,
   219,   234,   235,    0,   236,   237,   238,    0,
   232,   226,   244,   245,   221,   248,   249,   250,
   251,   245,    0,   252,   229,   249,   250,   251,
   253,    0,    0,   188,   254,   260,   239,   269,
   269,   242,   191,   191,   270,   246,   272,   272,
   229,   273,   274,   275,   276,    0,   255,   266,
   266,   258,   267,   267,   261,   266,   266,   264,
   267,   267,   232,   268,   232,    0,   277,    0,
   278,   232,   273,   232,   282,   283,   279,   285,
   253,    0,    0,   286,    0,   232,    0,   288,
    0,   290,    0,   292,   294,    0,    0,   297,
    0,    0,   299,   301,    0,   303,    0,   305,
    0,   307,    0,    0,   310,   313,   314,   315,
    0,    0,   316,   311,   314,    0,   332,   332,
   328,   349,   350,   351,   351,   351,   351,   330,
   282,   352,   358,    0,   333,   341,   347,   359,
   360,   361,   362,   363,    0,   342,   343,   345,
    0,   346,    0,   269,   269,    0,    0,   366,
   353,   371,   372,   373,   374,    0,   375,   376,
   377,   383,   384,   364,   385,   385,   367,   269,
   269,   269,   269,   389,   390,   391,   392,   393,
    0,   378,   360,   361,   362,   341,    0,   379,
   380,   386,   363,   341,    0,   353,   354,   355,
   375,   395,    0,   396,    0,   400,   269,   269,
   401,    0,   411,   411,   406,   417,   407,   418,
   419,   420,    0,   412,   418,   419,   420,   421,
    0,   409,   406,   424,   417,   422,   425,   425,
   408,   415,   427,   430,   431,    0,   426,   432,
   428,   434,   436,    0,   433,   269,   269,   441,
   442,   282,   443,    0,   446,   451,   447,   446,
   452,   451,    0,   449,   448,   454,   453,   457,
    0,   455,   459,   458,    0,   269,   464,   465,
   282,   466,    0,   469,   469,   470,   471,   472,
   473,   474,   475,   476,   477,    0,   479,   269,
   481,    0,   483,   485,   485,   205,   490,   488,
   496,   497,   491,   494,   490,    0,   491,   491,
    0,   498,   499,   501,    0,    0,   504,   506,
   510,   499,   508,    0,   506,   506,   504,   512,
   513,   514,   515,    0,   517,   518,   519,   520,
    0,   522,   523,   524,   525,   522,    0,   528,
   529,   531,   536,   532,   534,    0,   532,    0,
   537,   538,   539,   541,   542,   542,    0,   544,
   546,    0,   547,   548,   549,   533,   551,   553,
   558,   554,   556,    0,   554,    0,   559,   560,
   557,    0,   563,   205,    0,   566,   564,   568,
   565,   570,   567,   572,   569,   574,   571,   576,
   575,    0,   579,   580,   592,   593,   584,   205,
   585,   588,   588,   588,   590,   205,   594,   594,
   595,   596,   597,   581,   600,   598,   601,    0,
   205,   205,   205,   606,   606,   607,   608,   609,
   605,   610,   612,    0,   193,   193,   193,   193,
   193,   193,   193,   193,    0,   623,   623,   192,
   626,   626,    0,   626,   626,   631,   633,   282,
   282,   634,   282,   282,   637,   638,   639,    0,
   650,   677,   684,   666,   655,   205,   205,   205,
   205,   650,   659,   668,   685,   666,    0,   662,
   686,   666,   662,   668,   685,    0,   670,   674,
   689,   666,   205,    0,   205,    0,   674,   689,
   205,    0,   666,   205,    0,   680,   692,   680,
   659,   668,   685,    0,   650,   687,   662,   688,
   205,   690,   691,   666,   680,   697,   697,   697,
   697,   698,   699,   700,    0,   703,   703,   704,
   706,   707,   708,   708,   700,   711,   711,   712,
   713,   719,   719,   719,   719,   719,   719,    0,
0(max grammar-gmax1)

constshortinteger max kdict = 618
constshortintegerarray kdict(32:max kdict) = c
    0,   511,   131,   531,   131,   551,   559,   131,
   567,   575,   583,   603,   623,   631,   663,   671,
   129,   129,   129,   129,   129,   129,   129,   129,
   129,   129,   691,   698,   707,   751,   795,   131,
   131,   824,   900,   960,   1076,   1120,   1280,   128,
   128,   1392,   128,   128,   1460,   1600,   1636,   1704,
   1792,   128,   1872,   2088,   2284,   2316,   128,   2356,
   128,   128,   128,   2375,   2383,   2415,   2423,   2443,
   131,   131,   131,   131,   131,   131,   131,   131,
   131,   131,   131,   131,   131,   131,   131,   131,
   131,   131,   131,   131,   131,   131,   131,   131,
   131,   131,   131,   131,   2451,   131,   2459, -32351,
  16428,    25,  16428,    29, -32349,  16433,    1,  16434,
    1, -16127,    0,  16427,    21,  16407,    0,  16409,
    0, -32323, -10840,    40,  16471,    0, -32341, -10580,
    32,  16473,   117,  16384,    19, -31955, -32322, -10580,
    36,  -9290,    0,  16473,   113,  16432,    13, -32337,
  16427,    46,  16427,    17,  16405,    0,  16404,    0,
 -31556, -31939, -32322,  -9551,    2,  16433,    1,  16433,
    5,  16426,    5, -31606, -32323,  -9807,    0, -32374,
  -9678,    0,  16436,    0,  16435,    0, -31939, -32322,
  16433,    4,  16426,    9,  16433,    3, -30772, -31666,
  10578,  11457, -32344,  16413,    2,  16411,    2,    68,
 -32374,  16440,    0,  16440,    0,   8393,    83,  16408,
    0, -31291,  10841,    69, -32311,  16412,    18,  10830,
   9157,  10565,  16412,    18,   9415,    78,  16458,    0,
 -32049,   8665,   8908,  16455,    0, -30131,    78, -31277,
    84, -32055,  10194,    76,  16469,    0,  10958,    69,
  16447,    32,    84, -32319,  16418,    2,  10830,  16418,
    2,   8909,  10830,  16406,    0, -31927,  10073,   9921,
   8649,  16419,    5,   9153,  10190,   8915,  16469,    1,
 -27956, -31282,    88, -31927,   8916,  10066,   9793,  16419,
    3,    84,  16447,    4,    68, -32305,  16459,    2,
    70, -30650, -31284,    80, -31931,  10194,  10567,   9921,
  16460,    1,   9938,  16461,    0,  10697,    84,  16467,
    3,   9801,    69,  16460,    0,   8915,  16452,    0,
 -29631, -30903, -31282, -31793,  10069,  10819,  10185,    78,
  16416,    9,    82,  16445,    0,  16416,    9,   9422,
   9299, -32315,  16453,    0,  10700,    69,  16454,    0,
  10700,    69,  16464,   1210, -30778,    78, -31549,   8916,
   8903,    82, -32344,  16412,    17,  16472,    17,  10956,
   8900,  16470,    0,  16446,    44, -28735, -29239,  10063,
    71, -30263, -31668, -32302,  16412,    20,   8389,    76,
  16412,    36,  10063,    71, -32311,  16412,    21,  10830,
   9157,  10565,  16412,    21,  10830,   9157,  10565,  16412,
    20,  10835,  16467,    1,   8898,    76,  16425,    6,
 -31935,  10063,  10825,  10575,  16465,   109,    80,  16416,
    10, -32191,  10831,  16442,    0,   8909, -32314,  16414,
    1, -31794,  10069,  10819,  10185,    78,  16416,    10,
  16416,    10, -30770, -31408, -32174,  10071,  16418,    1,
 -32374,  16441,    2,  16441,    2,   9428,  10063,  16402,
    0, -32315,  16448,    0,   8918,  10830,  16448,    0,
 -30523,    82, -31419, -31927,   9167,   8402,    77,  16457,
    0,    77,  16419,    6,   9412,   8387,   8916,  16415,
   123,   9938,  16419,    7, -31931,  10959,   9428,   8910,
  16415,   104, -28351, -30397, -31024, -32045,  10964,  10066,
  16464,   1319,   9813,   7892, -32323,  16462,   1384,  16463,
   1241,   8389,    84,  16456,    0,  10575,    68, -32314,
  16421,    64,  10575,   8397,    84, -32301,  16422,    9,
   8912,    67,  16422,    12,    76, -32301,  16412,    33,
 -31924,  10190,   9938,   9793,  16468,    1,  10063,    71,
  16468,    4, -27704, -28983, -29488, -31276, -31913,  10713,
   8916,    77,  16419,    4,  10825,   9283,  16417,    12,
 -31423, -31921,   9426,   9166,    40,  16420,    48,    80,
  16466,   115,  10834,  16451,    0,   8645,  16423,    0,
  10055,   9793, -32315,  16449,    0,   8918,  10830,  16449,
    0,  10575,    84, -32311,  16412,    19,  10830,   9157,
  10565,  16412,    19, -32056,  10962,    69,  16464,   1354,
  10053,  16450,    0,    78, -32052,   9428,    76,  16444,
   182,  10693,    83,  16446,    46,   9416,   8908,  16443,
   180,  16407,    0, -31939, -32292, -10454,    51,  16426,
    13,  16433,    1,  16409,    0, -32290, -10454,    51,
  16426,    13,  16410,    0,  16431,    14, -32323,  16430,
    51,  16433,    1
   list
!%endoffile
    !***  end  of generated tables ***

    routine flush buffer( integer limit )
        integer j
        if bp >= limit start
        if faulty = 0 start
            selectoutput(object)
            for j = 1, 1, bp cycle
                printsymbol(buff(j))
            repeat
            selectoutput(listing)
        finish
        bp = 0
        finish
    end

    routine add char( byteinteger ch )
        bp = bp + 1
        buff(bp) = ch
    end

    routine op(integer code, param)
        buff(bp+1) = code
        buff(bp+2) = param>>8
        buff(bp+3) = param
        bp = bp+3
    end

    routine set const(integer m)
        buff(bp+1) = 'N'
        buff(bp+5) = m;  m = m>>8
        buff(bp+4) = m;  m = m>>8
        buff(bp+3) = m;  m = m>>8
        buff(bp+2) = m
        bp = bp+5
    end

    routine octal(integer n)
        integer m
        m = n>>3
        octal(m) if m # 0
        add char( n&7+'0' )
    end

    routine hexadecimal(integer n)
        integer m
        m = n>>4
        hexadecimal(m) if m # 0
        if n&15 > 9 then add char( n&15+'A' ) else add char( n&15+'0' )
    end

    routine print ident(integer p, mode)

        routine putit(integer ch)
            if mode = 0 then start
                printsymbol(ch)
            else
                add char( ch )
            finish
        end

        integer k, l
        p = tag(p)_text
        if p = 0 start
            putit('?')
            return
        finish
        p = p+1;       ! advance to name string
        k = dict(p)
        l = k & 255;   ! length
        while l > 0 cycle
            putit(k>>8)
            l = l-1
            p = p+1
            k = dict(p)
            exit if l = 0
            putit(k&255)
            l = l-1
        repeat
    end

    routine abandon(integer n)
        switch reason(0:9)
        integer stream
        stream = listing
        cycle
            newline if sym # nl
            printsymbol('*');  write(lines,4);  space
            ->reason(n)
reason(0):  printstring("compiler error!");          ->more
reason(1):  printstring("switch vector too large");  ->more
reason(2):  printstring("too many names");           ->more
reason(3):  printstring("program too complex");      ->more
reason(4):  printstring("feature not implemented");  ->more
reason(5):  printstring("input ended: ")
            if quote # 0 start
                if quote < 0 then printsymbol(cquote) else printsymbol(squote)
            else
                printstring("%endof")
                if progmode >= 0 then printstring("program") else printstring("file")
            finish
            printstring(" missing?");                ->more
reason(6):  printstring("too many faults!");         ->more
reason(7):  printstring("string constant too long"); ->more
reason(8):  printstring("dictionary full");          ->more
reason(9):  printstring("Included file ".include file." does not exist")

more:       newline
            printstring("***  compilation abandoned ***");  newline
            exit if stream = report
            close output
            stream = report
            select output(report)
        repeat
        !%signal 15,15 %if diag&4096 # 0
        stop
    end

    routine compile block(integer level, block tag, dmin, tmax, id)

        integerfnspec gapp
        routinespec delete names(integer quiet)
        routinespec analyse
        routinespec compile

        integer open;    open       = closed;       !zero if can return from proc
        integer dbase;   dbase      = dmax;         !dictionary base
        integer tbase;   tbase      = tmax;         !tag base
        integer tstart;  tstart     = tmax
        integer label;   label      = 4;            !first internal label
        integer access;  access     = 1;            !non-zero if accessible
        integer inhibit; inhibit    = 0;            !non-zero inhibits declaratons

        integername bflags;      bflags      == tag(block tag)_flags
        integer block type;      block type   = bflags>>4&7
        integer block form;      block form   = bflags&15
        integer block fm;        block fm     = tag(block tag)_format
        integer block otype;     block otype  = otype
        integername block app;   block app   == tag(block tag)_app

        integer l, new app

        routine fault(integer n)
            ! -5 : -1  - warnings
            !  1 : 22  - errors

            switch fm(-5:22)
            integer st

            routine print ss
                integer s, p
                return if pos = 0
                space
                p = 1
                cycle
                    printsymbol(marker) if p = pos1
                    exit if p = pos
                    s = char(p);  p = p+1
                    exit if s = nl or (s='%' and p = pos)
                    if s < ' ' start;           !beware of tabs
                        if s = ff then s = nl else s = ' '
                    finish
                    printsymbol(s)
                repeat
                pos = 0 if list <= 0
            end

            pos1 = pos2 if pos2 > pos1
            newline if sym # nl
            st = report
            st = listing if n = -3;               !don't report unused on the console
            cycle
                select output(st)
                if n < 0 then printsymbol('?') and pos1 = 0 else printsymbol('*')
                if st # report start
                    if list <= 0 and pos1 # 0 start
                        spaces(pos1+margin);  printstring("      ! ")
                    finish
                finish else start
                    printstring(include file) if include # 0
                    write(lines, 4);  printsymbol(csym);  space
                finish
                ->fm(n) if -5 <= n and n <= 22
                printstring("fault");  write(n, 2);              ->ps

fm(-5):         printstring("Dubious statement");  dubious = 0;        ->psd
fm(-4):         printstring("Non-local")
                pos1 = for warn;  for warn = 0;                        ->ps
fm(-3):         print ident(x, 0);  printstring(" unused");            ->nps
fm(-2):         printstring("""}""");                                  ->miss
fm(-1):         printstring("access");                                 ->psd
fm(0):          printstring("form");                                   ->ps
fm(1):          printstring("atom");                                   ->ps
fm(2):          printstring("not declared");                           ->ps
fm(3):          printstring("too complex");                            ->ps
fm(4):          printstring("duplicate ");  Print Ident(x, 0);         ->ps
fm(5):          printstring("type");                                   ->ps
fm(6):          printstring("match");                                  ->psd
fm(7):          printstring("context");                                ->psd
fm(8):          printstring("%cycle");                                 ->miss
fm(9):          printstring("%start");                                 ->miss
fm(10):         printstring("size");  write(lit, 1) if pos1 = 0;      ->ps
fm(11):         printstring("bounds")
                write(ocount, 1) unless ocount < 0;                   ->ps
fm(12):         printstring("index");                                  ->ps
fm(13):         printstring("order");                                  ->psd
fm(14):         printstring("not a location");                         ->ps
fm(15):         printstring("%begin");                                 ->miss
fm(16):         printstring("%end");                                   ->miss
fm(17):         printstring("%repeat");                                ->miss
fm(18):         printstring("%finish");                                ->miss
fm(19):         printstring("result");                                 ->miss
fm(20):         printsymbol('"'); print ident(x, 0); printsymbol('"'); ->miss
fm(21):         printstring("context ");  print ident(this, 0);        ->ps
fm(22):         printstring("format");                                 ->ps

miss:           printstring(" missing");                               ->nps
psd:            pos1 = 0
ps:             print ss
nps:            newline
                exit if st = listing
                st = listing
            repeat
            if n >= 0 start
                !%signal 15,15 %if diag&4096 # 0
                if n # 13 start;             !order is fairly safe
                    ocount = -1
                    gg = 0
                    copy = 0;  quote = 0
                    search base = 0;  escape class = 0
                    gg = 0
                finish
                faulty = faulty+1
   
                !check that there haven't been too many faults
   
                fault rate = fault rate+3;  abandon(6) if fault rate > 30
                fault rate = 3 if fault rate <= 0
            finish
            tbase = tstart
            if list <= 0 and sym # nl start
                error margin = column
                error sym = sym;  sym = nl
            finish
        end

        dmin = dmin-1;  dict(dmin) = -1;            !end marker for starts & cycles
        abandon(2) if dmax = dmin

        if list > 0 and level > 0 start
            write(lines, 5);  spaces(level*3-1)
            if block tag = 0 start
                printstring("Begin")
            finish else start
                printstring("Procedure ");  print ident(block tag, 0)
            finish
            newline
        finish

        !deal with procedure definition (parameters)
        if block tag # 0 start;                     !proc
            analyse;  compile if ss # 0

            if block otype # 0 start;                !external-ish
                if bflags&spec = 0 start;             !definition
                    if progmode <= 0 and level = 1 then progmode = -1 else fault(7)
                finish
            finish

            new app = gapp;                          !generate app grammar
            if spec given # 0 start;                 !definition after spec
                fault(6) if new app # block app;      !different from spec
            finish
            block app = new app;                     !use the latest

            if level < 0 start;                      !not procedure definition
                delete names(0)
                return
            finish
        finish else start
            open = 0;                                !can return from a block?
        finish

        cycle
            analyse
            if ss # 0 start
                compile
                fault(-5) if dubious # 0
                flush buffer( 128 )                    ;! flush if bp >= 128
                if sstype > 0 start;                   !block in or out
                    exit if sstype = 2;                 !out
                    compile block(spec mode, block x, dmin, tmax, id)
                    exit if ss < 0;                     !endofprogram
                finish
            finish
        repeat
        if list > 0 and level > 0 start
            write(lines, 5);  spaces(level*3-1)
            printstring("End")
            newline
        finish
        delete names(0)
        return

        ! generate app grammar (backwards)
        integerfn gapp
            constinteger comma = 140;                !psep
            routinespec set cell(integer g, tt)
            routinespec class(record(tagfm)name v)
            record(tagfm)name v
            integer p, link, tp, c, ap, t

            result = 0 if tmax = local;              !no app needed

            p = gmax1;  link = 0;  t = tmax

            cycle
                v == tag(t);  t = t-1
                class(v);                             ! deduce class from tag
                if c < 0 start;                       ! insert %PARAM
                    c = -c
                    set cell(196, tp)
                    tp = -1
                finish
                set cell(c, tp)
                exit if t = local;                    ! end of parameters
                set cell(comma, -1);                  ! add the separating comma
            repeat
            abandon(3) if gmax > gmin

            result = link

            routine set cell(integer g, tt)
                ! add the cell to the grammar, combining common tails
                while p # gmax cycle
                    p = p+1
                    if glink(p) = link and gram(p) = g start
                        if tt < 0 or (gram(p+1) = tt and glink(p+1)=ap) start
                            link = p;                    ! already there
                            return
                        finish
                    finish
                repeat

                !add a new cell
                gmax = gmax+1
                gram(gmax) = g
                glink(gmax) = link
                link = gmax

                if tt >= 0 start;               ! set type cell
                    gmax = gmax+1
                    gram(gmax) = tt
                    glink(gmax) = ap
                finish
                p = gmax

            end

            routine class(record(tagfm)name v)
                constinteger err    = 89
                constinteger rtp    = 100
                constinteger fnp    = 101
                constinteger mapp   = 102
                constinteger predp  = 103
                constintegerarray class map(0:15) = c
                          err,1764, 247, err(4), -rtp, -fnp, -mapp, -predp, err, 214,
                !         err,1764, 247, err(4), -rtp, -fnp, -mapp, -predp, err, 214,
                          err, 229, err
                !         err, 229, err
                integer tags, type, form

                ap = 0
                tags = v_flags
                type = tags>>4&7;  form = tags&15
                tp = v_format<<3!type
                c = class map(form)
                c = 208 and tp = 0 if type = 0 and form = 2;     !%name
                ap = v_app if tags&parameters # 0
            end
        end

        routine delete names(integer quiet)
            integer flags
            record(tagfm)name tx

            while tmax > tbase cycle
                x = tmax;  tmax = tmax-1
                tx == tag(x)
                flags = tx_flags
                fault(20) if flags&spec # 0 and flags&own bit = 0
                !{spec with no definition & not external}
                if flags&used bit = 0 and level >= 0 and list <= 0 start
                    fault(-3) if quiet = 0;           !unused
                finish
                dict(tx_text) = tx_link
            repeat
        end

        routine analyse
            constinteger order bits = 16_3000, order bit = 16_1000
            constinteger escape     = 16_1000
            integer strp, mark, flags, prot err, k, s, c
            owninteger key = 0
            integer node
            integername z
            record(arfm)name arp
            switch act(actions:phrasal), paction(0:15)

            routine trace analysis
                !diagnostic trace routine (diagnose&1 # 0)
                integer a

                routine show(integer a)
                    if 0 < a and a < 130 start
                        space
                        printstring(text(a))
                    finish else write(a, 3)
                end

                owninteger la1=0, la2=0, lsa=0, lt=0
                newline if mon pos # pos and sym # nl
                mon pos = pos
                write(g, 3)
                space
                printstring(text(class))
                printsymbol('"') if gg&trans bit # 0
                a = gg>>8&15
                if a # 0 start
                    printsymbol('{')
                    write(a, 0)
                    printsymbol('}')
                finish
                if atom1 # la1 or atom2 # la2 or lsa # subatom or lt # type start
                    printstring(" [")
                    la1 = atom1
                    show(la1)
                    la2 = atom2
                    show(la2)
                    lsa = subatom
                    write(lsa, 3)
                    lt = type
                    write(lt, 5)
                    printsymbol(']')
                finish
                newline
            end

            routine get sym
                readsymbol(sym)
                abandon(5) if sym < 0
                pos = pos+1 if pos # 133
                char(pos) = sym
                printsymbol(sym) if list <= 0
                column = column+1
            end

            routine read sym
                owninteger Last = 0
                constbyteintegerarray mapped(0:127) = c
                  0,  0,  0,  0,   0,  0,  0,  0,    0,  0, 10,  0,   3,  0,  0,  0,
                  0,  0,  0,  0,   0,  0,  0,  0,    0,  0,  0,  0,   0,  0,  0,  0,
                  0,'!','"','#', '$',  1,'&', 39,  '(',')','*','+', ',','-','.','/',
                '0','1','2','3', '4','5','6','7',  '8','9',':',';', '<','=','>','?',
                '@','A','B','C', 'D','E','F','G',  'H','I','J','K', 'L','M','N','O',
                'P','Q','R','S', 'T','U','V','W',  'X','Y','Z','[', '¬',']','^','_',
                '`','A','B','C', 'D','E','F','G',  'H','I','J','K', 'L','M','N','O',
                'P','Q','R','S', 'T','U','V','W',  'X','Y','Z', 2 , '|','}','~',  0

                !!   0 = space
                !!   1 = %
                !!   2 = {
                !!   3 = ff
                !!   other values represent themselves

                if sym = nl start
s1:                 lines = lines+1
                    printsymbol(end mark) if end mark # 0
s11:                pos = 0;  pos1 = 0;  pos2 = 0;  margin = 0;  column = 0
                    Last = 0
                    end mark = 0
                    if list <= 0 start
                        if include # 0 start
                            printstring(" &");  write(lines, -4)
                        finish else  write(lines, 5)
                        csym = cont;  printsymbol(csym)
                        space
                        if error margin # 0 start
                            lines = lines-1
                            spaces(error margin)
                            error margin = 0
                            if error sym # 0 start
                                printsymbol(error sym)
                                pos = 1;  char(1) = error sym
                                sym = error sym;  error sym = 0
                                ->s5
                            finish
                        finish
                    finish
s2:                 symtype = 1
                finish
s3:             readsymbol(sym)
                abandon(5) if sym < 0
                pos = pos+1 if pos # 133
                char(pos) = sym
                printsymbol(sym) if list <= 0
                column = column+1
s5:             if sym # nl start
                    Last = Sym
                    return if quote # 0;                       !dont alter strings
                    sym = mapped(sym&127)
                    if sym <= 3 start;                         !special symbol
                        ->s2 if sym = 0;                        !space (or dubious control)
                        symtype = 2 and ->s3 if sym = 1;        !%
                        cont = '+' and ->s11 if sym = 3;        !ff
                        !must be {
                        cycle
                            get sym
                            ->s3 if sym = '}'
                            ->s4 if sym = nl
                        repeat
                    finish
                    key = kdict(sym)
                    if key&3 = 0 and symtype = 2 start;               !keyword
                        if sym = 'C' and nextsymbol = nl start;        !%c...
                            getsym;  cont = '+';  ->s1
                        finish
                    else
                        symtype = key&3-2
                    finish
                    return
                finish
s4:             symtype = quote
                ->S1 if last = 0 and Quote = 0
                Cont = '+'
            end

            integerfn format selected
                format list = tag(format)_app;      !number of names
                if format list < 0 start;           !forward ref
                    atom1 = error+22
                    result = 0
                finish
                if sym = '_' start
                    escape class = esc rec
                    search base = tag(format)_format
                finish
                result = 1
            end

            routine code atom(integer target)
                integer dbase, da
                integer base, n, mul, pend quote
                integer j,k,l, pt

                routine lookup(integer d)
                    integer new name, vid, k1, k2, form
                    record(tagfm)name t
                    integer new

                    ! twee little function because SKIMP86 can't do string compare properly
                    ! returns 1 if the two names are the same, else zero
                    integerfn dict match(integer ptr1, ptr2)
                        integer len;
                        ! start with a cheap check of the length and first character
                        if dict(ptr1) # dict(ptr2) then result = 0
                        len = dict(ptr1) & 255
                        ptr1 = ptr1 + 1
                        ptr2 = ptr2 + 1
                        len = len - 1
                        while len >= 2 cycle
                            if dict(ptr1) # dict(ptr2) then result = 0
                            ptr1 = ptr1 + 1
                            ptr2 = ptr2 + 1
                            len = len - 2
                        repeat
                        ! if the string was odd length, we might need one last byte checked
                        if len = 1 start
                            if dict(ptr1)&255 # dict(ptr2)&255 then result = 0
                        finish
                        result = 1
                    end

                    !first locate the text of the name
                    new = dmax+1;     ! points to text of string in dictionary
                    k1 = hash value & max names;        ! rather crude hash!

                    cycle
                        newname = hash(k1)
                        exit if newname = 0;                  !not in
                        ->in if dict match(newname+1, new) = 1
                        k1 = (k1+1)&max names
                    repeat

                    ! not found
                    spare names = spare names-1
                    abandon(2) if spare names <= 0
                    hash(k1) = dmax;                               !put it in
                    dict(dmax) = -1
                    newname = dmax;  dmax = dp;  ->not in

in:                 search base = rbase if this >= 0 and d # 0;    !record elem defn
                    if search base # 0 start;                      !record subname
                        new = -1
                        x = search base
                        cycle
                            ->not in if x < format list
                            exit if tag(x)_text = new name
                            x = x-1
                        repeat
                    finish else start;                      !hash in for normal names
                        x = dict(newname)
                        ->not in if x <= limit;              !wrong level
                    finish

                    subatom = x;                            !name found, extract info
                    t == tag(x)
                    atom flags = t_flags
                    format = t_format;  app = t_app
                    protection = atom flags&prot
                    type = atom flags>>4&7;  atom1 = amap(atom flags&15)

                    if diag&8 # 0 start
                        printstring("lookup:")
                        write(atom1, 3)
                        write(type, 1)
                        write(app, 3)
                        write(format, 5)
                        write(atom flags, 3)
                        newline
                    finish

                    if d = 0 start;                               !old name wanted
                        t_flags = t_flags!used bit
                        search base = 0

                        if atom flags&subname # 0 and format # 0 start;    !a record
                            return if format selected = 0
                        finish

                        if atom flags&parameters # 0 start;        !proc or array
                            if app = 0 start;                       !no parameters needed
                                atom2 = atom1
                                atom1 = atom1-4
                                if 97 <= atom1 and atom1 <= 98 start
                                    map gg = atom1;  atom1 = var
                                finish
                            finish else start
                                if sym = '(' start
                                    search base = 0;                  !ignore format for now
                                    if atom1 >= 106 start;            !arrays
                                        app = phrase(app+200)
                                        escape class = esc array
                                        atom1 = (atom1-106)>>1+91;     !a,an->v  na,nan->n
                                    finish else start;                !procedures
                                        escape class = esc proc
                                        atom1 = atom1-4
                                    finish
                                    phrase(200) = app
                                finish
                            finish
                            pos2 = pos;  return
                        finish

                        !deal with constintegers etc
                        if atom flags&const bit # 0 and atom1 = var start
                            map gg = const;  atom2 = const
                            subatom = -subatom if type = integer
                        finish
                        return
                    finish
                                                                !new name wanted
                    ->not in if tbase # tstart;                 !don't fault proc parm-parm
                    if d = lab+spec+used bit start
                        t_flags = t_flags!used bit
                        return
                    finish
                    if atom flags&spec # 0 start;              !a spec has been given
                        if d = lab start;                       !define label
                            t_flags = t_Flags-Spec
                            return
                        finish
                        if 7 <= decl&15 and decl&15 <= 10 and decl&spec = 0 start
                            !procedure definition after spec
                            if (decl!!atom flags)&2_1111111 = 0 start;    !correct type?
                                t_flags = t_flags-spec
                                spec given = 1
                                return
                            finish
                            !note that an external procedure must be speced as a
                            !non-external procedure.
                        finish
                        if decl&15 = recfm start;                !recordformat
                            t_flags = record<<4+recfm
                            t_format = fdef
                            return
                        finish
                    finish
                    return if last1 = jump and atom1 = swit
                    copy = x if copy = 0
notin:              app = 0;  vid = 0
                    atom1 = error+2

                    return if d = 0;                           !old name wanted
                    type = d>>4&7;  form = d&15;  atom1 = amap(form)

                    if this < 0 start;                         !normal scope
                        new = newname
                        tmax = tmax+1;  x = tmax
                    finish else start;                         !recordformat scope
                        new = -1
                        recid = recid-1;  vid = recid
                        tmin = tmin-1;  x = tmin
                        format list = tmin
                    finish

                    if 11 <= form and form <= 14 start;                  !arrays
                        dim = 1 if dim = 0;                     !set dim for owns
                        app = dim
                    finish

                    d = d!used bit if (otype > 2 and d&spec = 0) or perm # 0 or Level = Include Level

                    !external definitions need not be used in the file in which
                    !they are defined, so inhibit a useless unused warning.

                    t == tag(x)
                    if form = lab start
                        id = id+1;  vid = id
                    finish
                    t_index = vid
                    t_text   = new name
                    t_flags = d
                    t_app    = app
                    t_format = fdef;  format = fdef
                    subatom = x

                    if new >= 0 start;                               !insert into hash table
                        t_link = dict(new);  dict(new) = x
                        if gmin = max grammar start;                  !proc param params
                            tmin = tmin-1;  subatom = tmin
                            tag(tmin) = t
                        finish
                    finish
                    abandon(3) if tmax >= tmin
                end

top:            pos1 = pos
                subatom = 0;  pend quote = 0;  atom flags = 0

                !app and format must be left for assigning to papp & pformat
                ->name if symtype = -2;                ! letter
                ->number if symtype < 0;               ! digit
                if symtype = 0 start
                    atom1 = termin;  atom2 = 0
                    return
                finish
                if symtype # 2 start;                  ! catch keywords here
                    ->text if quote # 0;               ! completion of text
                    ->strings if sym = squote;         ! start of string
                    ->symbols if sym = cquote;         ! start of symbol
                    ->number if sym = '.' and '0' <= nextsymbol and nextsymbol <= '9'
                finish

                ! locate atom in fixed dict
                k = key>>2;  read sym
                cycle
                    j = kdict(k)
                    exit if j&16_4000 # 0
                    if j&127 # sym or symtype < 0 start
                        ->err unless j < 0
                        k = k+1
                    finish else start
                        l = j>>7&127;  read sym
                        if j > 0 start
                            if l # 0 start
                                ->err if l # sym or symtype < 0
                                read sym
                            finish
                            l = 1
                        finish
                        k = k+l
                    finish
                repeat
                atom1 = j&127
                if atom1 = 0 start;                    ! comma
                    atom1 = 19;  subatom = 19;  atom2 = 0
                    if sym = nl start
                        return if ocount >= 0

                        ! special action needs to be taken with <comma nl> as
                        ! const array lists can be enormous
                        read sym
                    finish
                    return
                finish
                atom2 = j>>7&127
                subatom = kdict(k+1)&16_3fff
                !!!!!cont = ' '
                return

                ! report an error. adjust the error marker (pos1) to point
                ! to the faulty character in an atom, but care needs to be taken
                ! to prevent misleading reports in cases like ...?????

err:            atom1 = error+1;  atom2 = 0
                pos1 = pos if pos-pos1 > 2
                return

                ! take care with strings and symbol constants.
                ! make sure the constant is valid here before sucking it in
                ! (and potentially loosing many lines)

symbols:        atom1 = var;  atom2 = const;  type = integer
                map gg = const;  protection = prot
                subatom = lp;  abandon(3) if lp >= lit max
                quote = ¬pend quote
                return

                ! an integer constant is acceptable so get it in and
                ! get the next atom
chars:          n = 0;  cont = cquote
                cycle
                    read sym
                    if sym = cquote start
                        exit if nextsymbol # cquote
                        read sym
                    finish
                    if n&(¬((-1)>>byte size)) # 0 start;   ! overflow
                        pos1 = pos;  atom1 = error+10;  return
                    finish
                    ->err if quote = 0
                    n = n<<byte size+sym
                    quote = quote+1
                repeat
                quote = 0;  cont = ' '
                readsym if sym # nl
                lit pool(lp) = n;  lp = lp+1
                ->top

                !sniff the grammar before getting the string
strings:        atom1 = var;  atom2 = const;  type = stringv
                subatom = strp!16_4000
                map gg = const;  protection = prot
                quote = subatom
                text line = lines;                     ! in case of errors
                return

                ! a string constant is ok here, so pull it in and get
                ! the next atom
                ! ABD - temp variable to help pack bytes into words
                integer flipflop

text:           ->chars if quote < 0;                  ! character consts
                l = strp;                              ! point to beginning
                k = 0;                                 ! length so far
                flipflop = 0;                          ! space for the length is up the spout

                cycle
                    cont = squote;  quote = 1
                    cycle
                        read sym
                        if sym = squote start;         ! terminator?
                            exit if nextsymbol # squote;   ! yes ->
                            read sym;                  ! skip quote
                        finish
                        if flipflop >= 0 start
                            glink(strp) = sym<<8 + flipflop
                            strp = strp+1
                            flipflop = -1
                        else
                            flipflop = sym
                        finish
                        k = k+1
                        lines = text line and abandon(7) if k > 255;   ! too many chars
                    repeat
                    if flipflop >=0 start;             ! tail-end charlie
                        glink(strp) = flipflop
                        strp = strp+1
                    finish
                    glink(l) = glink(l)!k;             ! plug in length

                    quote = 0;  cont = ' ';  read sym
                    code atom(target)
                    return unless atom1 = 48 and sym = squote;    ! fold "???"."+++"
                repeat

                routine get(integer limit)
                    integer s, shift
                    shift = 0
                    if base # 10 start
                        if base = 16 start
                            shift = 4
                        finish else start
                            if base = 8 start
                                shift = 3
                            finish else start
                                if base = 2 start
                                    shift = 1
                                finish
                            finish
                        finish
                    finish
                    n = 0
                    cycle
                        if symtype = -1 start;         ! digit
                            s = sym-'0'
                        finish else start
                            if symtype < 0 start;      ! letter
                                s = sym-'A'+10
                            finish else start
                                return
                            finish
                        finish
                        return if s >= limit
                        pt = pt+1;  glink(pt) = sym
                        if base = 10 start;            ! check overflow
                            if n >= max int and (s > max dig or n > max int) start
                                !too big for an integer,
                                !so call it a real
                                base = 0;  type = real;  n = 0
                            finish
                        finish
                        if shift = 0 start
                            n = n*base+s
                        finish else start
                            n = n<<shift+s
                        finish
                        read sym
                    repeat
                end

number:         base = 10
bxk:            atom1 = var;  atom2 = const;  type = integer;  subatom = lp
                map gg = const;  protection = prot
                abandon(3) if lp >= lit max
                pt = strp;  mul = 0
                cycle
                    get(base)
                    exit unless sym = '_' and base # 0 and pend quote = 0;     ! change of base
                    pt = pt+1;  glink(pt) = '_'
                    read sym
                    base = n
                repeat

                if pend quote # 0 start
                    ->err if sym # cquote
                    readsym
                finish
                if sym = '.' start;                    ! a real constant
                    pt = pt+1;  glink(pt) = '.'
                    read sym
                    type = real;  n = base;  base = 0;  get(n)
                finish

                if sym = '@' start;                    ! an exponent
                    pt = pt+1;  glink(pt) = '@';  k = pt
                    readsym
                    type = integer;  base = 10
                    if sym = '-' start
                        read sym;  get(10);  n = -n
                    finish else start
                        get(10)
                    finish
                    pt = k+1;  glink(pt) = lp;  litpool(lp) = n;  lp = lp+1
                    atom1 = error+10 if base = 0
                    type = real;                       ! exponents force the type
                finish

                if type = real start
                    glink(strp) = pt-strp;             ! store the length (difference)
                    subatom = (strp)!16_2000;  strp = pt+1
                finish else start
                    litpool(lp) = n
                    lp = lp+1
                finish
                return

name:           atom1 = 0 and return if 27 <= target and target <= 41
                hash value = 0

                ! ABD changed to remove dependency on direct addressing
                dp = dmax+1
                dbase = dp
                n = 0
                dict(dp) = 0
                cycle
                    hash value = hash value+(hash value+sym); ! is this good enough?
                    dict(dp) = dict(dp) ! (sym << 8);
                    n = n+1
                    dp = dp+1
                    read sym
                    exit if symtype >= 0
                    dict(dp) = sym;
                    n = n+1
                    read sym
                    exit if symtype >= 0
                repeat
                if sym = cquote start
                    pend quote = 100
                    ->symbols if hash value = 'M'
                    read sym
                    if hash value = 'X' then base = 16 and ->bxk
                    if hash value = 'K' or hash value = 'O' then base = 8 and ->bxk
                    if hash value = 'B' then base = 2 and ->bxk
                    ->err
                finish
                dict(dbase) = dict(dbase)!n
                if n&1 = 0 then dp = dp+1
                abandon(8) if dp >= dmin

                atom2 = 90;                            ! ident
                if last1 = 0 and sym = ':' start;      ! label
                    limit = local;  lookup(lab);  return
                finish
                if last1 = jump start;                 ! ->label
                    limit = local;  lookup(lab+spec+used bit);  return
                finish
                if decl # 0 and target = 90 start;     ! identifier
                    search base = fm base
                    limit = local;  lookup(decl)
                    search base = 0
                finish else start
                    limit = 0;  lookup(0)
                finish
            end

            integerfn parsed machine code
                !   *opcode_??????????
                atom1 = error and result=0 unless symtype = -2;    ! starts with letter
                flush buffer( 128 );                   ! flush if bp >= 128
                add char( 'w' )
                cycle
                    add char( sym ); read sym
                repeat until Sym = '_' or Symtype = 0;    ! pull in letters and digits
                add char( '_' )
                if symtype # 0 start;                  ! not terminator
                    read sym
                    while symtype # 0 cycle
                        if symtype < 0 start;          ! complex
                            code atom(0);  result=0 if atom1&error # 0
                            if atom2 = const and type = integer start
                                if subatom < 0 then set const(tag(-subatom)_format) else set const(litpool(subatom))
                            finish else if 91 <= atom1 and atom1 <= 109 start
                                if atom1 = 104 and Tag(Subatom)_Flags&Closed = 0 start
                                    This = Subatom;  Atom1 = Error+21
                                    result = 0
                                finish
                                op(' ', tag(subatom)_index)
                            finish else start
                                atom1 = error;  result=0
                            finish
                        finish else start
                            sym = sym!128 if symtype = 2      {underline with %}
                            add char( sym ); read sym
                        finish
                    repeat
                finish
                add char( ';' )
                result=1
            end

            cont = ' ' if gg = 0
            last1 = 0;  mapgg = 0
            s = 0;  ss = 0;  sstype = -1; fdef = 0
            fm base = 0
            app = 0

            ! deal with alignment following an error in one statement
            ! of several on a line
            margin = column;                           ! start of statement
            pos = 0
            strp = gmax+1;  lp = 0
            tbase = tstart;                            ! ??????????????
            local = tbase

            if gg = 0 or ocount >= 0 start;            ! data or not continuation(z)
again:          while sym type = 0 cycle;              ! skip redundant terminators
                    c = cont
                    cont = ' ';  cont = '+' if ocount >= 0
                    read sym
                    cont = c
                repeat
                ->skip if sym = '!';                   ! comment
                this = -1
                code atom(0)
                if atom1 = comment start
skip:               quote = 1
                    c = cont
                    read sym and cont = c while sym # nl;   ! skip to end of line
                    quote = 0;  symtype = 0
                    ->again
                finish
            finish
            decl = 0;  mark = 0
            gentype = 0;  force = 0
            dim = 0;  prot err = 0
            node = 0;  nmax = 0;  nmin = rec size+1
            order = 1;  gmin = max grammar+1
            sstype = 0 and ->more if gg # 0;           ! continuation
            ptype = 0;  spec given = 0

            stats = stats+1;  op('O', lines) if perm = 0

            ->fail1 if atom1&error # 0;                ! first atom faulty

            if escape class # 0 start;                 ! enter the hard way after
                g = imp phrase;  sstype = -1;  ->a3
            finish

            g = initial(atom1);                        ! pick up entry point
            if g = 0 start;                            ! invalid first atom
                g = initial(0);  sstype = 0;  ->a3;    ! declarator?
            finish
            if g < 0 start;                            ! phrase imp
                g = g&255
                nmax = 1
                ar(1)_class = 0;  ar(1)_link = 0;  ar(1)_sub = imp phrase
            finish

            gg = gram(g);  class = gg&255;  sstype = gg>>12&3-1
            ->a1

act(194):   ptype = type;  papp = app;  pformat = format;  ->more
act(196):   k =g+1;  ->a610
act(188):   k = ar(nmax)_sub+1
a610:       papp = glink(k)
            k = gram(k)
            ->more if k = 0;                           ! %name
            ptype = k&7;  pformat = k>>3
act(183):   k = type;  gentype = k if gentype = 0 or k = real
            if pformat < 0 start;                      ! general type
                app = papp;  format = pformat
                k = real if ptype = real and type = integer
                k = force and force = 0 if force # 0
            finish
            ->fail2 unless papp = app and (ptype = k or ptype = 0)
            ->more if pformat=format or pformat = 0 or format = 0
            ->fail2
act(197):   arp == ar(nmin)
            k = arp_sub
            ->fail3 unless block form = k&15
            arp_sub = k>>4

            type = block type
            ptype = block type;  pformat = block fm;  papp = app
            pformat = -1 if ptype # record
            ->more
act(195):   ->Fail2 if Type # 0 and Type # Integer and Type # Real
            arp == ar(nmin)
            k = arp_sub
            arp_sub = k>>2
            k = k&3
                                                       ! 1 = check integer
                                                       ! 2 = check real
                                                       ! 3 = check real + int
            ->more if k = 0;                           ! 0 = no action
            if k = 1 start
                force = integer
                ->more if type = integer or type = 0
                ->fail2
            finish
            ->fail2 unless ptype = real or ptype = 0;   ! {or added?}
            force = integer if k = 3
            ->more
act(198):   ! %OTHER
            k = gg>>8&15
            if k = 0 start;                            ! restore atom
                atom1 = last1
                ->more
            finish
            if k = 1 start;                            ! test string
                ->fail2 unless type = stringv
                ->more
            finish
            if k = 2 start;                            ! {fault record comparisons}
                ->fail2 if type = record
                ->more
            finish
            if k = 3 start;                            ! check OWN variable coming
                code atom(0)
                ->A7 if atom flags&own bit = 0
                ->more
            finish
            for warn = pos1 if x <= local;             ! %for TEST
            ->more
paction(1): if type = record then g = phrase(242) else pformat = -1; ->a3
paction(2): ptype = real;     pformat = -1;                             ->a3
paction(3): ptype = stringv;  pformat = -1;                             ->a3
paction(4): ptype = integer;  pformat = -1;                             ->a3
paction(5): ->a3 if ptype = integer
            g = phrase(212) and pformat=-1 if ptype = real
            g = phrase(213) if ptype = stringv
                                                                        ->a3
paction(6): ptype = gram(ar(nmax)_sub+1)&7;  pformat = -1;              ->a3
paction(7): ptype=real if ptype = integer;  pformat = -1;              ->a3

a1:         last1 = class;  atom1 = 0;  s = subatom
a2:         if gg&trans bit = 0 start;                 ! insert into analysis record
                z == node
                cycle;                                 ! insert cell in order
                    k = z
                    exit if gg&order bits = 0 or k = 0
                    gg = gg-order bit;  z == ar(k)_link
                repeat
                gg = map gg if map gg # 0 and gg&255 = var
                nmin = nmin-1;  ->fail0 if nmin = nmax
                z = nmin
                arp == ar(nmin)
                arp_sub = s;  arp_class = (gg&255)!mark
                arp_link = k
            finish
            mark = 0;  map gg = 0
more:       g = glink(g);                              ! chain down the grammar
paction(0):
a3:         gg = gram(g);  class = gg&255
            trace analysis if diag&1 # 0
            ->a5 if class = 0;                         ! end of phrase

            if class < actions start;                  ! not a phrase or an action
                class = atomic(class) if class >= figurative
                ->a2 if class >= manifest
                code atom(class) if atom1 = 0
                if escape class # 0 start;             ! escape to new grammar
                    class = escape class;  escape class = 0
                    g = g+escape

                    ! note that following an escape the next item is
                    ! forced to be transparent!

esc:                gg = 0
                    arp == ar(nmax+1)
                    arp_papp = papp;  arp_x = x;  ->a4
                finish

                ->a1 if class = atom1 or class = atom2

a7:             ->fail1 if gg >= 0;                    ! no alternative
                g = g+1
                ->a3
            finish

            if class >= phrasal start;                 ! a phrase
a4:             nmax = nmax+1;  ->fail0 if nmax = nmin
                arp == ar(nmax)
                arp_ptype = ptype
                arp_pos = pos1
                arp_pformat = pformat
                arp_link = gentype
                arp_class = node
                arp_sub = g
                node = 0
                g = phrase(class)
                ptype = force and force = 0 if force # 0
                gentype = 0
                ->paction(gg>>8&15)
            finish
            ->act(class);                              ! only actions left

a5:         ;! reverse links
            s = 0
            while node # 0 cycle
                z == ar(node)_link
                k = z;  z = s;  s = node;  node = k
            repeat
            ss = s
a6:         if nmax # 0 start
                k = gentype;                           ! type of phrase
                arp == ar(nmax);  nmax = nmax-1
                node = arp_class
                gentype = arp_link
                ptype = arp_ptype
                pformat = arp_pformat
                g = arp_sub
                if g&escape # 0 start
                    g = g-escape
                    papp = arp_papp
                    mark = 255
                    subatom = s
                    ->a3
                finish
                gentype = k if gentype = 0 or k = real
                type = gen type

                k = gg;                                ! exit-point code
                cycle
                    gg = gram(g)
                    ->a2 if k = 0
                    ->fail1 if gg >= 0;                ! no alternative phrase
                    k = k-order bit
                    g = g+1;                           ! sideways step
                repeat
            finish

            Fault(4)  if copy # 0
            fault(13) if order = 0
            fault(-4) if for warn # 0
            pos1 = 0
            fault rate = fault rate-1
            return

act(193):   gg = 0 and ->a5 unless sym = '=' or sym = '<';    ! cdummy
act(181):   atom1 = amap(decl&15);                     ! dummy
            ->more

act(182):   class = escdec;  g = glink(g)!escape;      ! an example of ! as an operator
            decl = 0;  otype = 0;  ->esc;              ! decl

act(199):   ;                                          ! compile
            s = 0
            while node # 0 cycle
                z == ar(node)_link
                k = z;  z = s;  s = node;  node = k
            repeat
            ss = s

            code atom(28) if quote # 0;                ! expend
            compile;  ->more if atom1&error = 0
            ->fail1

act(184):   ->fail4 unless type = integer
            if subatom < 0 then lit = tag(-subatom)_format else lit = lit pool(subatom)
            ->fail4 if lit # 0
            ->more
act(185):   ;                                          ! apply parameters
            s = 0
            while node # 0 cycle
                z == ar(node)_link
                k = z;  z = s;  s = node;  node = k
            repeat
            ss = s

            atom1 = ar(s)_class;  atom2 = 0
            atom1 = var if atom1 = 97 or atom1 = 98
            arp == ar(nmax)
            x = arp_x
            pos1 = arp_pos
            pos2 = 0
            app = 0
            format = tag(x)_format
            flags = tag(x)_flags
            type = flags>>4&7
            protection = flags&prot
            protection = 0 if flags&aname # 0

            if flags&subname # 0 and format # 0 start
                ->fail1 if format selected = 0
            finish

            ->a6

act(187):   protection = prot;  ->more;                ! %SETPROT
act(186):   ->More if protection&prot = 0
            prot err = nmin
            ->A7
act(191):   k = protection;                            ! %GUARD
            code atom(0)
            protection = k if atom flags&aname = 0
            ->more

act(192):   ->fail1 if parsed machine code=0
            ->more

act(189):   k = gapp;                                  ! %GAPP
            delete names(1)
            tmax = tbase;  tbase = gram (gmin);        ! restore tmax
            local= tbase
            gmin = gmin+1

            x = ar(ar(nmax)_class)_sub
            tag(x)_app = k;                            ! update app
            ->more

act(190):   gmin = gmin-1;                             ! %LOCAL
            abandon(2) if gmin <= gmax
            gram (gmin) = tbase;  tbase = tmax
            local = tbase
            ->more

            ! errors

fail4:      k = error+10;            ->failed;         ! *size
fail3:      k = error+7;             ->failed;         ! *context
fail2:      k = error+5;  pos2 = 0;  ->failed;         ! *type
fail0:      k = error+3;             ->failed;         ! *too complex
fail1:      k = atom1;    pos2 = 0
failed:     if diag&32 # 0 start
                printstring("Atom1 =");      write(atom1, 3)
                printstring("  Atom2 =");    write(atom2, 3)
                printstring("  subatom =");  write(subatom, 3); newline
                printstring("Type =");       write(type, 1)
                printstring("   Ptype =");   write(ptype, 1);   newline
                printstring("App =");        write(app, 1)
                printstring("   Papp =");    write(papp, 1);    newline
                printstring("Format =");     write(format, 1)
                printstring("   Pformat ="); write(pformat, 1); newline
                !%signal 13,15
            finish

            quote = 0 and readsym while sym # nl and sym # ';'
            if k&error # 0 start
                fault(k&255)
            finish else start
                if prot err = nmin then fault(14) else fault(0)
            finish
            gg = 0;  ss = 0;  symtype = 0
        end;                                           ! of analyse

        routine compile
            constinteger then = 4, else = 8, loop = 16

            switch c(0:actions), litop(1:12)

            constbyteintegerarray operator(1:14) = '[', ']', 'X', '/', '&', '!', '%', '+', '-', '*', 'Q', 'x', '.', 'v'
            constbyteintegerarray cc(0 : 7) = '#','=',')','<','(','>', 'k','t'
            constbyteintegerarray anyform(0:15) = 1,0,1,1,1,1,1,1,0,1,1,0,1,1,1,1

            constintegerarray decmap(0:15) = c
            1,             2,
            16_100B,       16_100D,       16_140C,      16_140E,
            3,             4,
            16_1007,       16_1008,       16_1009,      16_100A,
            6,             0,             0,            0
            ownbyteintegerarray cnest(0:15)
            integer lmode, clab, dupid
            integer resln
            owninteger last def = 0
            owninteger lb, ub
            integer cp, ord
            integer next, link, j, k, n, done
            integer class
            integer lit2, defs, decs, cident
            integer pending;  ownintegerarray pstack(1:40)
            ownstring(8) name = ""
            owninteger count = 0

            routine def lab(integer l)
                op(':', l)
                access = 1
            end

            routine get next
                record(arfm)name p
gn:             if next = 0 start;                     ! end of phrase
                    class = 0 and return if link = 0;    ! end of statement
                    p == ar(link)
                    next = p_link
                    link = p_sub
                finish
                cycle
                    p == ar(next)
                    x = p_sub
                    class = p_class
                    exit if class < actions;           ! an atom
                    if x = 0 start;                    ! null phrase
                        next = p_link;  ->gn
                    finish
                    if p_link # 0 start;               ! follow a phrase
                        p_sub = link;  link = next
                    finish
                    next = x
                repeat
                next = p_link
                if diag&2 # 0 start
                    spaces(8-length(name)) unless length(name) = 0
                    name = text(class)
                    write(x, 2)
                    space
                    printstring(name)
                    space
                    count = count-1
                    if count <= 0 start
                        count = 5
                        name = ""
                        newline
                    finish
                finish
            end

            routine set subs(integer n)
                !update the app field in n array descriptors
                integer p
                p = tmax
                while n > 0 cycle
                    !%signal 15,15 %if p < tbase
                    tag(p)_app = dimension
                    p = p-1;  n = n-1
                repeat
            end

            routine set bp
                !define a constant bound pair from the last stacked constants
                pending = pending-2
                lb = pstack(pending+1);  ub = pstack(pending+2)
                if ub-lb+1 < 0 start
                    pos1 = 0;  next = link;  fault(11)
                    ub = lb
                finish
                set const(lb);  set const(ub)
                add char( 'b' ) unless class = 146
            end

            routine compile end(integer type)
                ! type = 0:eof, 1:eop, 2:end
                if access # 0 start
                    open = 0
                    fault(19) if block form > proc;    ! can reach end
                finish

                while dict(dmin) >= 0 cycle;           ! finishes & repeats
                    fault(17+dict(dmin)&1)
                    dmin = dmin+1
                repeat
                !{delete names(0)}
                add char( ';' )
                add char( ';' ) if type = 1;           ! endofprogram

                bflags = bflags!open;                  ! show if it returns

                def lab(0) if block tag # 0 and level # 1;   ! for jump around
                if type # 2 start;                     ! eop, eof
                    fault(16) if level # type;         ! end missing
                finish else start
                    if level = 0 start
                        fault(15);                     ! spurious end
                    finish
                finish

                end mark = 11;               !******Mouses specific******
            end

            routine def(integer p)
                !dump a descriptor
                integer t, f, type
                record(tagfm)name v
                flush buffer( 1 );                     ! flush if bp > 0
                defs = defs+1
                v == tag(p)
                t = 0
                unless v_index < 0 start;              ! no index for subnames
                    id = id+1 and v_index = id if v_index = 0
                    last def = v_index
                    t = last def
                finish
                op('$', t)
                print ident(p, 1);                     ! output the name
                t = v_flags
                type = t
                type = type&(¬(7<<4)) if type&(7<<4) >= 6<<4; !routine & pred
                op(',', type&2_1111111);               ! type & form
                f = v_format
                f = tag(f)_index if t&16_70 = record<<4
                f = v_index if f < 0
                op(',', f);                            ! format
                f = otype+t>>4&2_1111000
                f = f!8 if class = 125;                ! add spec from %DUP
                dim = v_app;                           ! dimension
                dim = 0 unless 0 < dim and dim <= dim limit
                op(',', f+dim<<8);                     ! otype & spec & prot
                defs = 0 if t&parameters = 0
                f = t&15
                if v_flags&spec # 0 start
                    v_flags = v_flags&(¬spec) unless 3 <= f and f <= 10
                    ocount = -1;                       ! external specs have no constants
                finish
                dimension = 0
                if otype = 2 and (f=2 or f=12 or f=14) start
                    v_flags = v_flags-1;               ! convert to simple
                finish
            end

            routine def s lab(integer n)
                ! define a switch label, x defines the switch tag
                integer p, l, b, w, bit
                p = tag(x)_format;                     ! pointer to table
                l = dict(p);                           ! lower bound
                if l <= n and n <= dict(p+1) start
                    b = n-l
                    w = b>>4+p
                    bit = 1<<(b&15)
                    if dict(w+2)&bit # 0 start;        ! already set
                        fault(4) if pending # 0
                        return
                    finish
                    dict(w+2) = dict(w+2)!bit if pending # 0
                    set const(n)
                    op('_', tag(x)_index)   
                finish else start
                    fault(12)
                finish
                access = 1
            end

            routine call
                record(tagfm)name T
                t == tag(x)
                op('@', t_index)
                access = 0 if t_flags&closed # 0;      ! never comes back
                add char( 'E' ) if t_app = 0;          ! no parameters
            end

            routine pop def
                set const(pstack(pending));  pending = pending-1
            end

            routine pop lit
                if pending = 0 then lit = 0 else start
                    lit = pstack(pending);  pending = pending-1
                finish
            end

            !conditions & jumps
            routine push(integer x)
                if cnest(cp)&2 # x start
                    cnest(cp) = cnest(cp)!1;  x = x+4
                finish
                clab = clab+1 if cnest(cp)&1 # 0
                cnest(cp+1) = x;  cp = cp+1
            end

            routine pop label(integer mode)
                lmode = dict(dmin)
                if lmode < 0 or lmode&1 # mode start
                    fault(mode+8)
                finish else start
                    dmin = dmin+1;  label = label-3
                finish
            end

            if sstype < 0 start;                       ! executable statement
                if level = 0 start;                    ! outermost level
                    fault(13);                         ! *order
                finish else start
                    if access = 0 start
                        access = 1;  fault(-1);        ! only a warning
                    finish
                finish
            finish

            if diag&2 # 0 start
                newline if sym # nl
                printstring("ss =")
                write(ss, 1)
                newline
                count = 5
                name = ""
            finish

            next = ss
            pending = 0;  lmode = 0
            link = 0;  decs = 0
            defs = 0;  resln = 0;  done = 0
            ord = level
            ord = 1 if this >= 0;                      ! recordformat declarations
c(0):
top:        if next # link start
                get next;  ->c(class)
            finish

            !all done, tidy up declarations and jumps
            newline if diag&2 # 0 and count # 5

            if lmode&(loop!then!else) # 0 start;       ! pending labels and jumps
                op('B', label-1) if lmode&loop # 0;    ! repeat
                def lab(label)   if lmode&then # 0;    ! entry from then
                def lab(label-1) if lmode&else # 0;    ! entry from else
            finish

            return if decs = 0
            atom1 = error and return if atom1 # 0;     ! %integerroutine
            order = ord
            decl = decl&(¬15)+decmap(decl&15);         ! construct declarator flags
            atom1 = atoms(decl&15);                    ! generate class
            if otype # 0 start;                        ! own, const etc.
                atom1 = atom1+1 if atom1 # proc
                if otype = 2 start;                    ! const
                    n = decl&15
                    if n&1 # 0 start
                        decl = decl!prot
                        decl = decl!const bit if decl&2_1111111 = iform
                    finish
                else
                    decl = decl!own bit
                finish
            finish
            sstype = 1 if sstype = 0 and atom1 = proc
            atom1 = atom1+1 if decl&spec # 0;          ! onto spec variant
            ocount = 0 and cont = '+' if atom1 = 5;    ! own array
            if anyform(decl&15) = 0 start;             ! check meaningful
                if decl>>4&7 = record start
                    this = fdef if tag(fdef)_flags&spec # 0
                    atom1 = error+21 if fdef = this;   ! *context for format
                finish
                atom1 = error+10 if fdef = 0;          ! *size
            finish
            return

atop:       access = 0;  ->top
            ! declarators
c(88):      ;                                          ! rtype
c(28):      decl = x&(¬7);                             ! stype
            fdef = x&7;                                ! precision
            fdef = reals ln if x&2_1110001 = real<<4+1;  ! convert to long
            decs = 1;  ->top
c(34):      ;                                          ! own
c(35):      otype = x;  ord = 1;  ->top;               ! external
c(152):     decl = decl+x<<1;  ->top;                  ! xname
c(31):      ;                                          ! proc
c(32):      spec mode = level+1;                       ! fn/map
            decl = decl!prot if x = 9;                 ! function
c(29):      ord = 1;                                   ! array
            dim = 0
c(30):      decl = decl+x;                             ! name
            decs = 1
            ->top
c(27):      lit = 0;                                   ! arrayd
            if pending # 0 start
                pop lit
                unless 0<lit and lit<=dim limit start
                    atom1 = error + 11;  return
                finish
            finish
            dim = lit
            decl = decl + x;  decs = 1
            -> top
c(37):      x = x!subname;                             ! record
c(36):      lit = 0;                                   ! string
            if pending # 0 start
                pop lit
                unless 0 < lit and lit <= 255 start;    ! max length wrong
                    atom1 = error+10;  return
                finish
            finish
            fdef = lit;                                ! format or length
c(33):      decl = x;                                  ! switch
            decs = 1
            ->top
c(39):      decl = decl!spec;                          ! spec
            ocount = -1;                               ! no initialisation
            spec mode = -1
            ->top
c(38):      decl = 64+4;                               ! recordformat (spec)
            order = 1
            atom1 = x
            decl = decl!spec if atom1 = 12;            ! formatspec
            fdef = tmax+1;                             ! format tag
            return
c(175):     id = id+1;  tag(x)_index = id;  return;    ! FSID
c(41):      decs = 1;  decl = x!spec!closed;  ->top;   ! label
c(133):     recid = 0;  rbase = tmin-1;                ! fname
            this = x
            fm base = fdef;  format list = tmin
            def(this);                      ->top
c(148):     fdef = 0 and ->top if next = 0;            ! reclb
            get next;                                  ! skip name
            fdef = x
            ->top

c(127):     add char( '}' );             ->top;        ! %POUT
c(126):     add char( '{' );             ->top;        ! %PIN
c(174):     set bp;                                    ! rangerb
c(171):     ;                                          ! fmlb
c(172):     ;                                          ! fmrb
c(173):     add char( '~' )
            add char( class-171+'A' );   ->top;        ! fmor
c(168):     rbase = -rbase;                            ! orrb
            sstype = 0;  spec mode = 0

c(147):     search base = 0;                           ! recrb
            tag(this)_app = tmin
            tag(this)_format = rbase
            ->top

c(45):      add char( 'U' ) if x = 36;  ->top;         ! sign
c(46):      add char( '¬' );             ->top;        ! uop
c(47):;                                                ! mod
c(48):;                                                ! dot
c(42):;                                                ! op1
c(43):;                                                ! op2
c(44):      add char( operator(x) );     ->top;        ! op3
c(56):      ;                                          ! and
c(57):      push(x);  ->top;                           ! or
c(58):      cnest(cp) = cnest(cp)!!2;  ->top;          ! not
c(138):     x = 128+32+16+4;                           ! csep: treat like %while
c(59):      ;                                          ! while
c(60):      if class = 138 then op('f', label-1) else def lab(label-1);    ! until
c(166):     ;                                          ! runtil
c(62):      lmode = (lmode&(else!loop)) !(x>>3);       ! cword
            clab = label;  cp = 1;  cnest(1) = x&7
            ->top
c(72):      pop label(0);                              ! repeat
            def lab(label+1) if lmode&32 # 0;  ->atop
c(69):      pop label(1);               ->top;         ! finish
c(163):     ;                                          ! xelse
c(70):      pop label(1);                              ! finish else ...
            fault(7) if lmode&3 = 3;                   ! dangling else
c(68):      lmode = (lmode&else)!3;                    ! ...else...
            if access # 0 start
                op('F', label-1);  lmode = else!3
            finish
            def lab(label)
            ->top if next # 0
c(120):     ;                                          ! MSTART
c(67):      ;                                          ! start
c(71):      ;                                          ! cycle
stcy:       def lab(label-1) and lmode = loop if lmode = 0;   ! cycle
            dmin = dmin-1;  abandon(3) if dmin <= dmax
            dict(dmin) = lmode
            label = label+3
            return

c(64):      fault(13) if dict(dmin) >= 0 or inhibit # 0;   ! on event
            inhibit = 1
            n = 0
            n = 16_FFFF if pending = 0;                ! * = all events
            while pending > 0 cycle
                pop lit;  fault(10) if lit&(¬15) # 0;  ! too big
                j = 1<<lit
                dubious = 1 if n&j # 0
                n = n!j;                               ! construct bit mask
            repeat
            op('o', n);  op(',', label)
            lmode = then!1;  ->stcy

c(104):     op('J', tag(x)_index);                     ! l
            inhibit = 1;            ->atop
c(149):     stats = stats-1;                           ! lab
            access = 1;  inhibit = 1
            op('L', tag(x)_index);  ->top

c(63):      j = dmin;  l = label-3;                    ! exit, continue
            cycle
                fault(7) and ->top if dict(j) < 0
                exit if dict(j)&1 = 0
                j = j+1;  l = l-3
            repeat
            l = l+1 if x = 32;                         ! continue
            op('F', l)
            dict(j) = dict(j)!x;                       ! show given
            ->atop

c(50):      add char( 'C' );          ->cop;           ! acomp
c(49):
            if next # 0 start;                         ! comparator
                add char( '"' )
                push(0);                               ! double sided
            finish else start
                add char( '?' )
            finish

cop:        x = x!!1 if cnest(cp)&2 # 0;               ! invert the condition
            j = cp;  l = clab
            while cnest(j)&4 = 0 cycle
                j = j-1;  l = l-cnest(j)&1
            repeat
            op(cc(x), l)
            def lab(clab+1) if cnest(cp)&1 # 0
            cp = cp-1
            clab = clab-cnest(cp)&1
            ->top

c(78):      ;                                          ! fresult
c(79):      ;                                          ! mresult
c(80):      open = 0;                                  ! return, true, false
c(82):      access = 0;                                ! stop
c(89):      ;                                          ! addop
c(81):      add char( x );              ->top;         ! monitor
c(65):      pop lit;  op('e', lit);     ->atop;        ! signal
c(51):      add char( 'S' );            ->top;         ! eq
c(53):      add char( 'j' );            ->top;         ! jam transfer
c(52):      add char( 'Z' );            ->top;         ! eqeq
c(74):      if level = 0 start;                        ! begin
                if progmode <= 0 then progmode = 1 else fault(7)
                !{Permit BEGIN after external defs}
            finish
            spec mode = level+1
            block x = 0
            add char( 'H' )
            return
c(77):      perm = 0;  lines = 0;  stats = 0;          ! endofperm
            close input
            select input(source)
            list = list-1
            tbase = tmax;  tstart = tmax
            return
c(76):      if include # 0 and x = 0 start;            ! end of ...
                lines = include;  sstype =  0;         ! include
                close input
                list = include list
                include level = 0
                include = 0;  select input(source);  return
            finish
            ss = -1;                                   ! prog/file
c(75):      compile end(x);  return;                   ! %end

c(85):      if x=0 then control=lit else start;        ! control
                diag = lit&16_3FFF if lit>>14&3 = 1
            finish
            op('z'-x, lit)
            ->top
c(83):      list = list+x-2;   ->top;                  ! %LIST/%endoflist
c(84):      reals ln = x;      ->top;                  ! %REALS long/normal
c(86):      if include # 0 start;                      ! include "file"
                fault(7);  return
            finish
            get next;                                  ! sconst
            x = x-16_4000
            j = glink(x)
            k = j&255
            !ABD - another little copy loop because SKIMP can't do the string map
            include file = ""
            cycle
                k = k-1; exit if k < 0
                include file = include file.tostring(j>>8)
                x = x+1
                j = glink(x)
                k = k-1; exit if k < 0
                include file = include file.tostring(j&255)
            repeat
            ! include file = string(x-16_4000+stbase)
            ! remove this event block for SKIMP or pre-event IMP versions
            begin
                on 9 start;  Abandon(9);  finish
                open input(3, include file)
            end
            include = lines;  lines = 0
            include list = list;  include level = level
            select input(3)
            ->top

c(154):     dimension = dimension+1;                   ! dbsep
            fault(11) if dimension = dim limit+1
            ->top
c(145):     set bp;                       ->top;       ! crb
c(146):     set bp;                                    ! rcrb
c(142):     ;                                          ! bplrb
            dimension = 1 if dimension = 0
            op('d', dimension);  op(',', defs)
            if class # 146 start
                set subs(defs)
                fault(13) if dict(dmin) >= 0 or inhibit # 0 or level=0
            finish
            dimension = 0;  defs = 0
            ->top
c(128):     id = dupid;  ->top;                        ! EDUP
c(130):     block x = x
            op('F', 0) if decl&spec = 0 and level # 0;   ! jump round proc
c(125):     dupid = id;                                ! %DUP
            return if Level < 0;                       ! {spec about}
c(90):      def(x);  ->top;                            ! ident
c(131):     ;                                          ! cident
            if tag(x)_flags&(2_1111111+const bit) = iform+const bit start
                tag(x)_format = lit
            finish else start
                set const(lit) if pending # 0
                def(x)
                op('A', 1)
            finish
            cident = x
            ->top
c(124):     dubious = 1 if tag(cident)_flags&prot # 0;  ! %DUBIOUS
            ->top
c(97):      ;                                          ! f
c(98):      ;                                          ! m
c(99):      ;                                          ! p
c(96):      call;  ->top;                              ! r
c(165):     ;                                          ! nlab
c(100):     ;                                          ! rp
c(101):     ;                                          ! fp
c(102):     ;                                          ! mp
c(103):     ;                                          ! pp
c(91):      ;                                          ! v
c(92):      ;                                          ! n
c(106):     ;                                          ! a
c(107):     ;                                          ! an
c(108):     ;                                          ! na
c(109):     ;                                          ! nan
            k = tag(x)_index
            if k < 0 then op('n', -k) else op('@', k)
            ->top
c(121):     set const(0);                   ->top;     ! special for zero
c(167):     add char( 'G' );                ->pstr;    ! aconst (alias)
c(const):   ;                                          ! const
            if x < 0 start;                            ! constinteger
                set const(tag(-x)_format);  ->top
            finish
            if x&16_4000 # 0 start;                    ! strings
                add char( '''' )
pstr:           x = x-16_4000
                j = glink(x)
                k = j&255
                add char( k )
                cycle
                    k = k-1; ->top if k < 0
                    add char( j>>8 );
                    x = x+1
                    j = glink(x)
                    k = k-1; ->top if k < 0
                    add char( j&255 )
                repeat
            finish
            if x&16_2000 # 0 start;                    ! real - ABD also string-like, but NOT packed
                x = x-16_2000
                k = glink(x)
                op('D', k);  add char( ',' )
                cycle
                    ->top if k = 0
                    k = k-1
                    x = x+1;  j = glink(x)
                    if j = '@' start
                        op('@', litpool(glink(x+1)));  ->top
                    finish
                    add char( j )
                repeat
            finish
            set const(lit pool(x))
            ->top

c(137):     add char( 'i' );                ->top;     ! asep
c(141):     add char( 'a' );                ->top;     ! arb

            !own arrays
c(132):     ocount = ub-lb+1
            def(x);                                    ! oident
            dimension = 1;  set subs(1)
            if next = 0 start;                         ! no initialisation
                op('A', ocount) if ocount > 0
                ocount = -1
            finish else start;                         ! initialisation given
                get next
            finish
            ->top
c(162):     lit = ocount;  ->ins;                      ! indef
c(143):     pop lit;                                   ! orb
ins:        fault(10) and lit = 0 if lit < 0
            get next
            ->inst
c(139):     ;                                          ! osep (x=19)
c(153):     lit = 1
inst:       pop def if pending # 0;                    ! ownt (x=0)
            op('A', lit)
            ocount = ocount-lit
            if ocount >= 0 start
                ->top if x # 0;                        ! more coming
                ocount = -1 and return if ocount = 0;    ! all done
            finish
            fault(11);  return

c(swit):    op('W', tag(x)_index);  inhibit = 1;  ->atop
c(134):     def(x);                                    ! swid
            n = ub-lb+1
            n = (n+15)>>4;                             ! slots needed (includes zero)
            j = dmax;  dmax = dmax+n+2
            abandon(1) if dmax >= dmin
            tag(x)_format = j
            dict(j) = lb;  dict(j+1) = ub
            cycle
                n = n-1
                ->top if n < 0
                j = j+1;  dict(j+1) = 0
            repeat
c(151):     stats = stats-1;                           ! slab
            fault(7) and return if x < tbase
            if pending # 0 start;                      ! explicit label
                def s lab(pstack(1))
            finish else start
                fault(4) and return if tag(x)_app # 0
                tag(x)_app = 1
                n = tag(x)_format
                for j = dict(n), 1, dict(n+1) cycle
                    def s lab(j)
                    flush buffer( 128 );               ! flush if bp >= 128
                repeat
            finish
            inhibit = 1
            return

c(140):     add char( 'p' );         ->top;            ! psep
c(144):     ;                                          ! prb
            add char( 'p' );
            add char( 'E' );         ->top

            !constant expressions
c(155):     ;                                          ! pconst
            if x < 0 then lit = tag(-x)_format else lit = lit pool(x)
            pending = pending+1;     pstack(pending) = lit;  ->top
c(156):     lit = pstack(pending);  lit = -lit if lit < 0
            pstack(pending) = lit;  ->top;  !cmod
c(157):     lit = -pstack(pending);  pstack(pending) = lit;  ->top; ! csign
c(158):     lit = ¬pstack(pending);  pstack(pending) = lit;  ->top; ! cuop
c(159):     ;                                          ! cop1
c(160):     ;                                          ! cop2
c(161):     pending = pending-1;                       ! cop3
            lit2 = pstack(pending+1);  lit = pstack(pending)
            ->litop(x>>2)

litop(1):   lit = lit<<lit2;           ->setl
litop(2):   lit = lit>>lit2;           ->setl
litop(3):   n = 1;                                     ! lit = lit¬¬lit2
            fault(10) if lit2 < 0
            while lit2 > 0 cycle
                lit2 = lit2-1
                n = n*lit
            repeat
            lit = n;                   ->setl
litop(4):   if lit2 = 0 then fault(10) else lit = lit//lit2
                                       ->setl
litop(5):   lit = lit&lit2;            ->setl
litop(6):   lit = lit!lit2;            ->setl
litop(7):   lit = lit!!lit2;           ->setl
litop(8):   lit = lit+lit2;            ->setl
litop(9):   lit = lit-lit2;            ->setl
litop(10):  lit = lit*lit2;            ->setl
litop(11):  lit = lit+lit2;            ->setl
litop(12):  n = 1;                                     ! lit = lit¬¬lit2
            fault(10) if lit2 < 0
            while lit2 > 0 cycle
                lit2 = lit2-1
                n = n*lit
            repeat
            lit = n;                   ->setl
setl:       pstack(pending) = lit;     ->top

c(170):     ;
            !Fault(4) %if IMPCOM_Option # ""
            !IMPCOM_Option = String(x-x'4000'+Stbase); ! Option string
            ->Top

            !string resolution
c(135):     resln = 2;                    ->top;       ! dotl
c(136):     resln = resln+1;              ->top;       ! dotr
c(55):      op('r', resln);    resln = 0; ->top;       ! resop
c(164):     op('r', resln+4);  resln = 0;              ! cresop
c(122):     x = 6;                        ->cop;       ! %PRED
c(87):      set const(pstack(1));                      ! mass
            bp=bp+1 and buff(bp)='P';    ->top
        end

    end;                                               ! of compile block

    on 9 start
        abandon(5)
    finish

    selectinput(2);  selectoutput(listing)
    tag(max tag) = 0;                                  ! %begin defn
    tag(0) = 0;  tag(0)_flags = 7;                     ! %begin tag!
    Hash(x) = 0 for x = 0, 1, max names
    printstring("         Edinburgh IMP77 Compiler - Version ")
!    printstring("         Preston IMP2020 Compiler - Version ")
    printstring(version);  newlines(2)
    op('l', 0)
    compile block(0, 0, max dict, 0, 0)
    add char( nl );                                    ! {for bouncing off}
    flush buffer( 0 );                                 ! flush if bp >= 0

    x = listing
    newline
    cycle
        if faulty = 0 start
            write(stats, 5)
            printstring(" Statements compiled")
        else
            printstring(" Program contains ")
            write(faulty, 1)
            printstring(" fault")
            printsymbol('s') unless faulty = 1
        finish
        newline
        exit if x = report
        x = report
        selectoutput(report)
    repeat

    if faulty # 0 then stop;           ! try to flag to shell that we failed

endofprogram