external routine spec close output
external routine spec close input
external routine spec open output(integer i, string(255) s)
external routine spec open input(integer i, string(255) s)
recordformat impcomfm(integer statements, flags, code, gla, diags, perm,
                        string(31) file,
                        string(63) Option)
externalrecord(impcomfm) IMPCOM

!
!            On EMAS all shorts should be changed to integers.
!            Also, the INCLUDE facility will need to be modified.
!
!
         !###################################################
         !            Copyright: 1 January 1980             #
         !     Interactive Datasystems (Edinburgh) Ltd.     #
         !              32 Upper Gilmore Place              #
         !                Edinburgh EH3 9NJ                 #
         !               All Rights Reserved                #
         !###################################################

BEGIN
   CONSTSTRING(4) version = "8.4"

   !configuration parameters

   CONSTINTEGER max int      = ((-1)>>1)//10
   CONSTINTEGER max dig      = (-1)>>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
   CONSTINTEGER max names    = 1<<namebits-1
   OWNINTEGER   spare names  = max names
   CONSTINTEGER max grammar  = 1720
   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 source = 1;  ! input streams
   ! 2 is for prims
   ! 3 is for include files
   CONSTINTEGER report = 0, object = 1, listing = 2; ! output streams


   !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:
!emas:%RECORDFORMAT arfm(%INTEGER class,sub,link,ptype,papp,pformat,x,pos)

   RECORDFORMAT tagfm(INTEGER app, format, C
                       SHORTINTEGER 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   = b'1000000000000000',
                 closed     = b'0100000000000000',
                 const bit  = b'0010000000000000',
                 parameters = b'0001000000000000',
                 subname    = b'0000100000000000',
                 aname      = b'0000010000000000',
                 own bit    = b'0000001000000000',
                 prot       = b'0000000100000000',
                 spec       = b'0000000010000000'

   CONSTINTEGER trans bit  = x'4000'
   CONSTINTEGER error      = x'8000'

   CONSTINTEGER manifest = 120, figurative = 130
   CONSTINTEGER actions  = 180, phrasal    = 200

   CONSTBYTEINTEGERARRAY amap(0:15) = C
 89, 91, 92, 104, 94, const, swit, 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

   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,
               app          = 0,
               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,
               error sym    = 0,
               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         = ' ',
               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,
               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,
               gg           = 0,
               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 stbase       = 0;              !constant work area base
   OWNINTEGER gmin         = max grammar;    !upper bound on grammar
   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,
               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,
               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) = nl(134);   !input line
   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
   SHORTINTEGERARRAY hash(0:max names)
   RECORD(tagfm)ARRAY tag(0:max tag)
   SHORTINTEGERARRAY dict(1:max dict)
   BYTEINTEGERARRAY buff(1:512)
   OWNINTEGER bp           = 0

!*** start of generated tables ***
   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

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

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

!  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

!  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-719)

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-719)

constshortintegerarray kdict(32:607) = 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,    1556,    1592,    1660,
    1748,     128,    1828,    2044,    2240,    2272,     128,    2312,
     128,     128,     128,    2331,    2339,    2371,    2379,    2399,
     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,    2407,     131,    2379,  -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,  -30143,  -30647,   10063,
      71,  -31671,  -32302,   16412,      20,    8389,      76,   16412,
      36,   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
!***  end  of generated tables ***

ROUTINE flush buffer
   INTEGER j
   IF faulty = 0 START
      select output(object)
      FOR j = 1, 1, bp CYCLE
         printsymbol(buff(j))
      REPEAT
      select output(listing)
   FINISH
   bp = 0
END
ROUTINE print ident(INTEGER p, mode)
   INTEGER j, ad
   p = tag(p)_text
   IF p = 0 START
      bp = bp+1 AND buff(bp) = '?' if Mode # 0
      RETURN
   FINISH
   ad = addr(dict(p+1))
   IF mode = 0 THEN printstring(string(ad)) ELSE START
      FOR j = ad+1, 1, ad+byteinteger(ad) CYCLE
         bp = bp+1
         buff(bp) = byteinteger(j)
      REPEAT
   FINISH
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) C
                          ELSE printsymbol(squote)
          ELSE
             printstring("%endof")
             IF progmode >= 0 THEN printstring("program") C
                               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
!IMP80 BUG???     %SIGNAL 15,15 %IF diag&4096 # 0
   STOP
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 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

   SHORTINTEGERNAME 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 <= 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(21):PRINTSTRING("context ");  print ident(this, 0);  ->ps
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(22):PRINTSTRING("format");                           ->ps
fm(20):printsymbol('"');  print ident(x, 0);  printsymbol('"')
miss:  PRINTSTRING(" missing");                         ->nps
psd:   pos1 = 0
ps:    print ss
nps:   NEWLINE
       exit if st = listing
       st = listing
    repeat
    if n >= 0 start
!IMP80 BUG???         %signal 15,15 %if diag&4096 # 0
       stop 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 C
                                             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
      CONTINUE IF ss = 0
      compile
      fault(-5) IF dubious # 0
      flush buffer 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
   REPEAT
   IF list > 0 AND level > 0 START
      write(lines, 5);  spaces(level*3-1)
      printstring("End")
      newline
   FINISH
   delete names(0)
   RETURN

   INTEGERFN gapp;                             !generate app grammar (backwards)
      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, 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 = x'3000', order bit = x'1000'
   CONSTINTEGER escape     = x'1000'
   INTEGER strp, mark, flags, prot err, k, s, c
   OWNINTEGER key = 0
   SHORTINTEGER node
   SHORTINTEGERNAME z
   RECORD(arfm)NAME arp
!emas:   %INTEGER node
!emas:   %INTEGERNAME z
   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 < 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 C
                      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)
   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, nl,  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
!IMP80 BUG???  
!!             char(1) = error sym
               byteinteger(addr(char(0))+1) = error sym
               sym = error sym;  error sym = 0
               ->s5
            FINISH
         FINISH
      FINISH
s2:   symtype = 1
   FINISH
s3:readsymbol(sym)
   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)
      CONSTINTEGER magic = 6700421
      INTEGER new name, vid, k1, k2, form
      RECORD(tagfm)NAME t
!emas:      %LONGINTEGER k0
      INTEGER new

      !first locate the text of the name

      new = addr(dict(dmax+1))

            !******** Machine code to inhibit overflow test ********

!            *LI_1,magic
!            * M_0,hash value
!            *ST_1,K2

            {K2 = hash value*magic}
K2 = hash value*magic ;! requires NOCHECK option
                       ! we could fix this properly by a shift+add loop
            !*******************************************************

      k2 = k2>>(32-2*name bits)!1
!emas:      k0 = magic
!emas:      k1 = (k0*hash value)&X'7FFFFFFF'
!emas:      k2 = k1>>(32-2*name bits)!1
      k1 = k2>>name bits;                      !giving name bits
      CYCLE
         newname = hash(k1)
         EXIT IF newname = 0;                  !not in
         ->in IF string(addr(dict(newname+1))) = string(new)
         k1 = (k1+k2)&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 <= 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 <= 10 AND decl&spec = 0 START

            !procedure definition after spec

            IF (decl!!atom flags)&b'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 <= 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 C
                         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 <= '9'
      FINISH

                                                 !locate atom in fixed dict
      k = key>>2;  read sym
      CYCLE
         j = kdict(k)
         EXIT IF j&x'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)&x'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-stbase)!x'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

text: ->chars IF quote < 0;                        !character consts
      l = strp; n = strp
      j = addr(glink(gmin-1));                     !absolute limit
      k = l+256;                                   !string length limit
      k = j IF j < k;                              !choose lower

      CYCLE
         cont = squote;  quote = 1
         CYCLE
            read sym
            IF sym = squote START;                 !terminator?
               EXIT IF nextsymbol # squote;        !yes ->
               read sym;                           ! skip quote
            FINISH
            l = l+1;  byteinteger(l) = sym
            lines = text line AND abandon(7) IF l >= k;   !too many chars
         REPEAT
         byteinteger(n) = l-n;                            !plug in length
   
         strp = l+1;                                      !ready for next string
         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;  byteinteger(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;  byteinteger(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;  byteinteger(pt) = '.'
          read sym
          type = real;  n = base;  base = 0;  get(n)
       FINISH

       IF sym = '@' START;                          !an exponent
          pt = pt+1;  byteinteger(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;  byteinteger(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
          byteinteger(strp) = pt-strp
          subatom = (strp-stbase)!x'2000';  strp = pt+1
       FINISH ELSE START
          litpool(lp) = n
          lp = lp+1
       FINISH
       RETURN

name: atom1 = 0 AND RETURN IF 27 <= target <= 41
      hash value = 0

      !*****************************
      !*machine dependent for speed*
      !*****************************

      dp = dmax+1
      da = addr(dict(dp));  dbase = da
      CYCLE
         hash value = hash value+(hash value+sym);        !is this good enough?
         da = da+1;  byteinteger(da) = sym
         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' C
         OR hash value = 'O' THEN base = 8 AND ->bxk
         IF hash value = 'B' THEN base = 2 AND ->bxk
         ->err
      FINISH
      n = da-dbase
      byteinteger(dbase) = n
      dp = dp+(n+2)>>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_??????????
      routine octal(integer n)
         integer m
         m = n>>3
         octal(m) if m # 0
         bp = bp+1;  buff(bp) = n&7+'0'
      end
      atom1 = error AND RESULT=0 UNLESS symtype = -2;     !starts with letter
      flush buffer IF bp >= 128
      bp=bp+1 AND buff(bp)='w'
      CYCLE
         bp=bp+1 AND buff(bp)=sym
         read sym
         EXIT IF symtype >= 0;                  !pull in letters and digits
      REPEAT
      bp=bp+1 AND buff(bp)='_'
      IF symtype # 0 START;                     !not terminator
         atom1 = error AND result=0 UNLESS sym = '_'
         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 octal(tag(-subatom)_format) C
                                  ELSE octal(litpool(subatom))
               FINISH ELSE START
                  IF 91 <= atom1 <= 109 START
                     if atom1 = 104 {label} and C
                         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
            FINISH ELSE START
               bp=bp+1 AND buff(bp)=sym;  read sym
            FINISH
         REPEAT
      FINISH
      bp=bp+1 AND buff(bp)=';'
      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
   stbase = addr(glink(gmax+1));  strp = stbase;  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 C
                                   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;       !%FORTEST
         ->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
         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 C
                         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
!IMP80 BUG???           %SIGNAL 13,15
         STOP
       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) = C
                         '[',  ']',  'X',  '/', '&',  '!',  '%',  '+',
                         '-',  '*',  'Q',  'x', '.',  'v'

      CONSTBYTEINTEGERARRAY cc(0 : 7) = '#','=',')','<','(','>', 'k','t'

      CONSTBYTEINTEGERARRAY anyform(0:15) = 1,0,1,1(4),1,0,1,1,0,1,1,1,1

      CONSTSHORTINTEGERARRAY decmap(0:15) = C
         1,             2,
         x'100B',       x'100D',       x'140C',      x'140E',
         3,             4,
         x'1007',       x'1008',       x'1009',      x'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 name = ""
            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
!IMP80 BUG???              %SIGNAL 15,15 %IF p < tbase
            STOP 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)
         bp=bp+1 AND buff(bp)='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)}
         bp=bp+1 AND buff(bp)=';'
         bp=bp+1 AND buff(bp)=';' 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 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&b'1111111');             !type & form
         f = v_format
         f = tag(f)_index IF t&x'70' = record<<4
         f = v_index IF f < 0
         op(',', f);               !format
         f = otype+t>>4&b'1111000'
         f = f!8 IF class = 125;               !add spec from %DUP
         dim = v_app;                          !dimension
         dim = 0 unless 0 < 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 <= 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 <= 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
         bp=bp+1 AND buff(bp)='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


      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&b'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&b'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<=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 <= 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):bp=bp+1 AND buff(bp)='}';  ->top;              !%POUT
c(126):bp=bp+1 AND buff(bp)='{';  ->top;              !%PIN

c(174):set bp;                                        !rangerb
c(171):                                               !fmlb
c(172):                                               !fmrb
c(173):bp=bp+1 AND buff(bp)='~';  bp=bp+1 AND buff(bp)=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):bp=bp+1 and buff(bp)='U' IF x = 36;  ->top;     !sign
c(46):bp=bp+1;  buff(bp)='¬';  ->top;                 !uop
c(47):                                                !mod
c(48):                                                !dot
c(42):                                                !op1
c(43):                                                !op2
c(44):bp=bp+1;  buff(bp)=operator(x);  ->top;         !op3

!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

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) C
                      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 = x'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):bp=bp+1 AND buff(bp)='C';  ->cop;         !acomp

c(49): bp = bp+1
       IF next # 0 START;                       !comparator
          buff(bp)='"';  push(0);               !double sided
       FINISH ELSE START
          buff(bp)='?'
       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):   bp=bp+1 AND buff(bp)=x;  ->top;            !monitor

c(65):   pop lit;  op('e', lit);  ->atop;           !signal

c(51):   bp=bp+1 AND buff(bp)='S';  ->top;          !eq
c(53):   bp=bp+1 AND buff(bp)='j';  ->top;          !jam transfer
c(52):   bp=bp+1 AND buff(bp)='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
      bp=bp+1 AND buff(bp)='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&x'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
      include file = string(x-x'4000'+stbase)
      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&(b'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):bp=bp+1;  buff(bp)='G';  ->pstr;             !aconst (alias)
c(const):                                           !const
       IF x < 0 START;                              !constinteger
          set const(tag(-x)_format);  ->top
       FINISH
       IF x&x'4000' # 0 START;                      !strings
          bp=bp+1 AND buff(bp)=''''
pstr:     x = x-x'4000'+stbase
          k = byteinteger(x)
          bp=bp+1 AND buff(bp)=k
          k = k+x
          CYCLE
             ->top IF x = k
             x = x+1;  bp=bp+1 AND buff(bp)=byteinteger(x)
          REPEAT
       FINISH
       IF x&x'2000' # 0 START;                      !real
          x = x-x'2000'+stbase
          k = byteinteger(x)
          op('D', k);  bp=bp+1 AND buff(bp)=','
          k = k+x
          CYCLE
             ->top IF x = k
             x = x+1;  j = byteinteger(x)
             IF j = '@' START
                op('@', litpool(byteinteger(x+1)));  ->top
             FINISH
             bp=bp+1 AND buff(bp)=j
          REPEAT
       FINISH
       set const(lit pool(x))
       ->top

c(137):bp=bp+1 AND buff(bp)='i';               ->top;          !asep
c(141):bp=bp+1 AND buff(bp)='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 IF bp >= 128
          REPEAT
       FINISH
       inhibit = 1
       RETURN

c(140):bp=bp+1 AND buff(bp)='p';                  ->top;           !psep
c(144):buff(bp+1)='p';  buff(bp+2)='E';  bp=bp+2;  ->top;          !prb

!constant expressions

c(155):                                      !pconst
       IF x < 0 THEN lit = tag(-x)_format c
                 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(10):lit = lit*lit2;   ->setl
litop(12):
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(1):lit = lit<<lit2;   ->setl
litop(2):lit = lit>>lit2;   ->setl
litop(5):lit = lit&lit2;    ->setl
litop(11):
litop(4):IF lit2 = 0 THEN fault(10) ELSE lit = lit//lit2
                            ->setl
litop(8):lit = lit+lit2;    ->setl
litop(9):lit = lit-lit2;    ->setl
litop(6):lit = lit!lit2;    ->setl
litop(7):lit = lit!!lit2

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

impcom_flags = 0
impcom_option = ""

   list = 15 IF Impcom_Flags&x'1000' # 0

   open output(2, "LISTING");
   open input(2, "prims.inc");
   select input(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(version);  newlines(2)
   op('l', 0)
   compile block(0, 0, max dict, 0, 0)
   bp=bp+1 AND buff(bp)=nl                {for bouncing off}
   flush buffer
   Impcom_Statements = stats
   Impcom_Statements = -faulty IF faulty # 0
ENDOFPROGRAM