//============================================================================
 // IMP77 compiler first pass
 // ###########################################################
 // This program is a Copyright work.  #
 // #
 // Over the last 40+ years a long and distinguished list of #
 // institutions, individuals and other entities have made #
 // contributions to portions of this program and may have a #
 // reasonable claim over rights to certain parts of the #
 // program.  #
 // #
 // This version is therefore provided for education and #
 // demonstration purposes only #
 // ###########################################################
int main (int argc, char **argv)
{
   static char *version = "8.4";

   // configuration parameters
   static int minusone = (-(1));

   // Wee change needed to cross-compile the compiler when going from 16 bit to 32 bit world
   // %owninteger minus one = 16_7fff;
   static int maxint = ((int) (((minusone) >> 1)) / (int) (10));
   static int maxdig = (minusone) >> 1 - maxint * 10;
   static int bytesize = 8;

   // bits per byte
   static int maxtag = 800;

   // max no. of tags
   static int maxdict = 6000;

   // max extent of dictionary
   static int namebits = 11;

   // size of name table as a power of two
   static int maxnames = 1 << namebits - 1;

   // table limit (a mask, eg 255)
   static int sparenames = maxnames;
   static int litmax = 50;

   // max no. of constants/stat.
   static int recsize = 520;

   // size of analysis record
   static int dimlimit = 6;

   // maximum array dimension
   // symbols
   static int ff = 12;

   // form feed
   static int marker = '^';

   // marker for faults
   static int squote = '"';

   // string quote
   static int cquote = '\\';

   // character quote
   // streams
   static int report = 0, source = 1;
   static int object = 1, listing = 2;

   // types
   static int integer = 1;
   static int real = 2;
   static int stringv = 3;
   static int record = 4;

   // forms
   static int iform = integer << 4 + 1;
   static int var = 91;
   static int _const_ = 93;
   static int swit = 105;
   static int comment = 22;
   static int termin = 20;
   static int lab = 3;
   static int jump = 54;
   static int recfm = 4;
   static int proc = 7;

   // class for proc
   // phrase entries
   static int escdec = 252;
   static int escproc = 253;
   static int escarray = 254;
   static int escrec = 255;

   // %recordformat arfm(%shortinteger class,sub,link,ptype,papp,pformat,x,pos);!imp77:
   typedef struct arfm
   {
      int class, sub, link, ptype, papp, pformat, x, pos;
   } arfm;
   typedef struct tagfm
   {
      int app, format;
      int flags, index, text, link;
   } tagfm;

   // 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
   // 
   // 
   static int usedbit = 0b1000000000000000;
   static int closed = 0b0100000000000000;
   static int constbit = 0b0010000000000000;
   static int parameters = 0b0001000000000000;
   static int subname = 0b0000100000000000;
   static int aname = 0b0000010000000000;
   static int ownbit = 0b0000001000000000;
   static int prot = 0b0000000100000000;
   static int spec = 0b0000000010000000;
   static int transbit = 0x4000;
   static int error = 0x8000;
   arfm ar[recsize - 1 + 1];
   static int class = 0;

   // class of atom wanted
   static int x = 0;

   // usually last tag
   static int atom1 = 0;

   // atom class (major)
   static int atom2 = 0;

   // atom class (minor)
   static int subatom = 0;

   // extra info about atom
   static int type = 0;
   static int app = 0;
   static int format = 0;

   // atom info
   int hashvalue;
   static int faulty = 0;

   // fault indicator
   static int faultrate = 0;

   // fault rate count
   static int lines = 0;

   // current line number
   static int textline = 0;

   // starting line for string const
   static int margin = 0;

   // statement start margin
   static int errormargin = 0;
   static int errorsym = 0;
   static int column = 0;
   static int stats = 0;

   // statements compiled
   static int monpos = 0;

   // flag for diagnose
   static int sym = nl;

   // current input symbol
   static int symtype = 0;

   // type of current symbol
   static int quote = 0;

   // >0 strings, <0 chars
   static int endmark = 0;

   // %end flag
   static int cont = ' ';
   static int csym = ' ';

   // listing continuation marker
   static int decl = 0;

   // current declarator flags
   static int dim = 0;

   // arrayname dimension
   static int specgiven = 0;
   static int escapeclass = 0;

   // when and where to escape
   static int protection = 0;
   static int atomflags = 0;
   static int otype = 0;

   // current 'own' type
   static int realsln = 1;

   // =4 for %REALSLONG
   static int last1 = 0;

   // previous atom class
   static int gentype = 0;
   static int ptype = 0;

   // current phrase type
   static int papp = 0;

   // current phrase parameters
   static int pformat = 0;

   // current phrase format
   static int force = 0;

   // force next ptype
   static int g = 0;
   static int gg = 0;
   static int mapgg = 0;

   // grammar entries
   static int fdef = 0;

   // current format definition
   static int this = (-(1));

   // current recordformat tag
   static int nmin = 0;

   // analysis record atom pointer
   static int nmax = 0;

   // analysis record phrase pointer
   static int rbase = 0;

   // record format definition base
   static int dmax = 1;
   static int tmin = maxtag;

   // upper bound on tags
   static int ss = 0;

   // source statement entry
   char includefile[63 + 1];
   static int includelist = 0;
   static int includelevel = 0;
   static int include = 0;

   // =0 unused, #0being used
   static int perm = 1;

   // 1 = compiling perm, 0 = program
   static int progmode = 0;

   // -1 = file, 1 = begin/eop
   static int sstype = 0;

   // -1:exec stat
   // 0: declaration
   // 1: block in
   // 2: block out
   static int specmode = 0;

   // >=0: definition
   // -1: proc spec
   // -2: recordformat
   static int ocount = (-(1));

   // own constants wanted
   static int limit = 0;

   // lookup limit
   static int copy = 0;

   // duplicate name flag
   static int order = 0;

   // out of sequence flag
   static int forwarn = 0;

   // non-local flag
   static int dubious = 0;

   // flag for dubious statements
   static int dp = 1;
   static int pos1 = 0;
   static int pos2 = 0;

   // error position
   static int pos = 0;

   // input line index
   static int dimension = 0;

   // current array dimension
   static int local = 0;

   // search limit for locals
   static int fmbase = 0;

   // entry for format decls
   static int searchbase = 0;

   // entry for record_names
   static int formatlist = 0;

   // size of current format list
   int recid;
   static unsigned char _char_[133 - 0 + 1];
   int litpool[litmax - 0 + 1];
   static int lit = 0;

   // current literal (integer)
   static int lp = 0;

   // literals pointer
   static int blockx = 0;

   // block tag
   static int list = 1;

   // <= to enable
   static int control = 0;
   static int diag = 0;

   // diagnose flags
   int hash[maxnames - 0 + 1];
   tagfm tag[maxtag - 0 + 1];
   int dict[maxdict - 1 + 1];
   unsigned char buff[512 - 1 + 1];
   static int bp = 0;
   static int maxgrammar = 1720;
   static int gmin = maxgrammar;

   // upper bound on grammar
   static int manifest = 120, figurative = 130;
   static int actions = 180, phrasal = 200;
   static unsigned char amap[15 - 0 + 1];

   // ? v n l fm const swit rp fp mp pp a an na nan ?
   static unsigned char atoms[15 - 0 + 1];

   // *** start of generated tables ***
   // *** end of generated tables ***
   auto void flushbuffer (int limit)
   {
      int j;

      if (bp >= limit) {
	 if (faulty == 0) {
	    selectoutput (object);
	    for (j = 1; j <= bp; j += 1) {
	       printsymbol (buff[j]);
	    }
	    selectoutput (listing);
	 }
	 bp = 0;
      }
   }
   auto void addchar (unsigned char ch)
   {
      bp += 1;
      buff[bp] = ch;
   }
   auto void op (int code, int param)
   {
      buff[bp + 1] = code;
      buff[bp + 2] = param >> 8;
      buff[bp + 3] = param;
      bp += 3;
   }
   auto void setconst (int 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 += 5;
   }
   auto void octal (int n)
   {
      int m;

      m = n >> 3;
      if (m != 0)
	 octal (m);
      addchar (n & 7 + '0');
   }
   auto void hexadecimal (int n)
   {
      int m;

      m = n >> 4;
      if (m != 0)
	 hexadecimal (m);
      if (n & 15 > 9)
	 addchar (n & 15 + 'A');
      else
	 addchar (n & 15 + '0');
   }
   auto void printident (int p, int mode)
   {
      auto void putit (int ch)
      {
	 if (mode == 0) {
	    printsymbol (ch);
	 } else {
	    addchar (ch);
	 }
      }
      int k;
      int l;

      p = &tag[p]->text;
      if (p == 0) {
	 putit ('?');
	 return;
      }
      p += 1;
      // advance to name string
      k = dict[p];
      l = k & 255;
      // length
      while (l > 0) {
	 putit (k >> 8);
	 l -= 1;
	 p += 1;
	 k = dict[p];
	 if (l == 0)
	    break;
	 putit (k & 255);
	 l -= 1;
      }
   }
   auto void abandon (int n)
   {
      static void *reason[ /* bounds */ ] = { &&reason_default };
      int stream;

      stream = listing;
      for (;;) {
	 if (sym != nl)
	    newline ();
	 printsymbol ('*');
	 write (lines, 4);
	 space ();
	 goto *reason[n];
       reason_0:		/* 0 */
	 printstring ("compiler error!");
	 goto more;
       reason_1:		/* 1 */
	 printstring ("switch vector too large");
	 goto more;
       reason_2:		/* 2 */
	 printstring ("too many names");
	 goto more;
       reason_3:		/* 3 */
	 printstring ("program too complex");
	 goto more;
       reason_4:		/* 4 */
	 printstring ("feature not implemented");
	 goto more;
       reason_5:		/* 5 */
	 printstring ("input ended: ");
	 if (quote != 0) {
	    if (quote < 0)
	       printsymbol (cquote);
	    else
	       printsymbol (squote);
	 } else {
	    printstring ("%endof");
	    if (progmode >= 0)
	       printstring ("program");
	    else
	       printstring ("file");
	 }
	 printstring (" missing?");
	 goto more;
       reason_6:		/* 6 */
	 printstring ("too many faults!");
	 goto more;
       reason_7:		/* 7 */
	 printstring ("string constant too long");
	 goto more;
       reason_8:		/* 8 */
	 printstring ("dictionary full");
	 goto more;
       reason_9:		/* 9 */
	 printstring (concat ("Included file ", concat (includefile, " does not exist")));
       more:
	 newline ();
	 printstring ("***  compilation abandoned ***");
	 newline ();
	 if (stream == report)
	    break;
	 closeoutput ();
	 stream = report;
	 selectoutput (report);
      }
      // %signal 15,15 %if diag&4096 # 0
      exit (0);
   }
   auto void compileblock (int level, int blocktag, int dmin, int tmax, int id)
   {
      auto int gapp (void);
      auto void deletenames (int quiet);
      auto void analyse (void);
      auto void compile (void);
      int open;

      open = closed;
      // zero if can return from proc
      int dbase;

      dbase = dmax;
      // dictionary base
      int tbase;

      tbase = tmax;
      // tag base
      int tstart;

      tstart = tmax;
      int _label_;

      _label_ = 4;
      // first internal label
      int access;

      access = 1;
      // non-zero if accessible
      int inhibit;

      inhibit = 0;
      // non-zero inhibits declaratons
      int *bflags;

      bflags = &tag[blocktag]->flags /* Pointer assignment */ ;
      int blocktype;

      blocktype = bflags >> 4 & 7;
      int blockform;

      blockform = bflags & 15;
      int blockfm;

      blockfm = &tag[blocktag]->format;
      int blockotype;

      blockotype = otype;
      int *blockapp;

      blockapp = &tag[blocktag]->app /* Pointer assignment */ ;
      int l;
      int newapp;
      auto void fault (int n)
      {
	 // -5 : -1 - warnings
	 // 1 : 22 - errors
	 static void *fm[ /* bounds */ ] = { &&fm_default };
	 int st;
	 auto void printss (void)
	 {
	    int s;
	    int p;

	    if (pos == 0)
	       return;
	    space ();
	    p = 1;
	    for (;;) {
	       if (p == pos1)
		  printsymbol (marker);
	       if (p == pos)
		  break;
	       s = _char_[p];
	       p += 1;
	       if ((s == nl || (s == '%' && p == pos)))
		  break;
	       if (s < ' ') {
		  // beware of tabs
		  if (s == ff)
		     s = nl;
		  else
		     s = ' ';
	       }
	       printsymbol (s);
	    }
	    if (list <= 0)
	       pos = 0;
	 }
	 if (pos2 > pos1)
	    pos1 = pos2;
	 if (sym != nl)
	    newline ();
	 st = report;
	 if (n == (-(3)))
	    st = listing;
	 // don't report unused on the console
	 for (;;) {
	    selectoutput (st);
	    if (n < 0) {
	       printsymbol ('?');
	       pos1 = 0;
	    } else
	       printsymbol ('*');
	    if (st != report) {
	       if ((list <= 0 && pos1 != 0)) {
		  spaces (pos1 + margin);
		  printstring ("      ! ");
	       }
	    } else {
	       if (include != 0)
		  printstring (includefile);
	       write (lines, 4);
	       printsymbol (csym);
	       space ();
	    }
	    if (((-(5)) <= n && n <= 22))
	       goto *fm[n];
	    printstring ("fault");
	    write (n, 2);
	    goto ps;
	  fm_ (-(5)):		/* (-(5)) */
	    printstring ("Dubious statement");
	    dubious = 0;
	    goto psd;
	  fm_ (-(4)):		/* (-(4)) */
	    printstring ("Non-local");
	    pos1 = forwarn;
	    forwarn = 0;
	    goto ps;
	  fm_ (-(3)):		/* (-(3)) */
	    printident (x, 0);
	    printstring (" unused");
	    goto nps;
	  fm_ (-(2)):		/* (-(2)) */
	    printstring ("\"}\"");
	    goto miss;
	  fm_ (-(1)):		/* (-(1)) */
	    printstring ("access");
	    goto psd;
	  fm_0:		/* 0 */
	    printstring ("form");
	    goto ps;
	  fm_1:		/* 1 */
	    printstring ("atom");
	    goto ps;
	  fm_2:		/* 2 */
	    printstring ("not declared");
	    goto ps;
	  fm_3:		/* 3 */
	    printstring ("too complex");
	    goto ps;
	  fm_4:		/* 4 */
	    printstring ("duplicate ");
	    printident (x, 0);
	    goto ps;
	  fm_5:		/* 5 */
	    printstring ("type");
	    goto ps;
	  fm_6:		/* 6 */
	    printstring ("match");
	    goto psd;
	  fm_7:		/* 7 */
	    printstring ("context");
	    goto psd;
	  fm_8:		/* 8 */
	    printstring ("%cycle");
	    goto miss;
	  fm_9:		/* 9 */
	    printstring ("%start");
	    goto miss;
	  fm_10:		/* 10 */
	    printstring ("size");
	    if (pos1 == 0)
	       write (lit, 1);
	    goto ps;
	  fm_11:		/* 11 */
	    printstring ("bounds");
	    if (!(ocount < 0))
	       write (ocount, 1);
	    goto ps;
	  fm_12:		/* 12 */
	    printstring ("index");
	    goto ps;
	  fm_13:		/* 13 */
	    printstring ("order");
	    goto psd;
	  fm_14:		/* 14 */
	    printstring ("not a location");
	    goto ps;
	  fm_15:		/* 15 */
	    printstring ("%begin");
	    goto miss;
	  fm_16:		/* 16 */
	    printstring ("%end");
	    goto miss;
	  fm_17:		/* 17 */
	    printstring ("%repeat");
	    goto miss;
	  fm_18:		/* 18 */
	    printstring ("%finish");
	    goto miss;
	  fm_19:		/* 19 */
	    printstring ("result");
	    goto miss;
	  fm_20:		/* 20 */
	    printsymbol ('"');
	    printident (x, 0);
	    printsymbol ('"');
	    goto miss;
	  fm_21:		/* 21 */
	    printstring ("context ");
	    printident (this, 0);
	    goto ps;
	  fm_22:		/* 22 */
	    printstring ("format");
	    goto ps;
	  miss:
	    printstring (" missing");
	    goto nps;
	  psd:
	    pos1 = 0;
	  ps:
	    printss ();
	  nps:
	    newline ();
	    if (st == listing)
	       break;
	    st = listing;
	 }
	 if (n >= 0) {
	    // %signal 15,15 %if diag&4096 # 0
	    if (n != 13) {
	       // order is fairly safe
	       ocount = (-(1));
	       gg = 0;
	       copy = 0;
	       quote = 0;
	       searchbase = 0;
	       escapeclass = 0;
	       gg = 0;
	    }
	    faulty += 1;
	    // check that there haven't been too many faults
	    faultrate += 3;
	    if (faultrate > 30)
	       abandon (6);
	    if (faultrate <= 0)
	       faultrate = 3;
	 }
	 tbase = tstart;
	 if ((list <= 0 && sym != nl)) {
	    errormargin = column;
	    errorsym = sym;
	    sym = nl;
	 }
      }
      dmin -= 1;
      dict[dmin] = (-(1));
      // end marker for starts & cycles
      if (dmax == dmin)
	 abandon (2);
      if ((list > 0 && level > 0)) {
	 write (lines, 5);
	 spaces (level * 3 - 1);
	 if (blocktag == 0) {
	    printstring ("Begin");
	 } else {
	    printstring ("Procedure ");
	    printident (blocktag, 0);
	 }
	 newline ();
      }
      // deal with procedure definition (parameters)
      if (blocktag != 0) {
	 // proc
	 analyse ();
	 if (ss != 0)
	    compile ();
	 if (blockotype != 0) {
	    // external-ish
	    if (bflags & spec == 0) {
	       // definition
	       if ((progmode <= 0 && level == 1))
		  progmode = (-(1));
	       else
		  fault (7);
	    }
	 }
	 newapp = gapp ();
	 // generate app grammar
	 if (specgiven != 0) {
	    // definition after spec
	    if (newapp != blockapp)
	       fault (6);
	    // different from spec
	 }
	 blockapp = newapp;
	 // use the latest
	 if (level < 0) {
	    // not procedure definition
	    deletenames (0);
	    return;
	 }
      } else {
	 open = 0;
	 // can return from a block?
      }
      for (;;) {
	 analyse ();
	 if (ss != 0) {
	    compile ();
	    if (dubious != 0)
	       fault ((-(5)));
	    flushbuffer (128);
	    // flush if bp >= 128
	    if (sstype > 0) {
	       // block in or out
	       if (sstype == 2)
		  break;	// out
	       compileblock (specmode, blockx, dmin, tmax, id);
	       if (ss < 0)
		  break;	// endofprogram
	    }
	 }
      }
      if ((list > 0 && level > 0)) {
	 write (lines, 5);
	 spaces (level * 3 - 1);
	 printstring ("End");
	 newline ();
      }
      deletenames (0);
      return;			// generate app grammar (backwards)
      auto int gapp (void)
      {
	 static int comma = 140;

	 // psep
	 auto void setcell (int g, int tt);
	 auto void class (tagfm * v);
	 tagfm *v;
	 int p;
	 int link;
	 int tp;
	 int c;
	 int ap;
	 int t;

	 if (tmax == local)
	    return (0);		// no app needed
	 p = gmax1;
	 link = 0;
	 t = tmax;
	 for (;;) {
	    v = &tag[t] /* Pointer assignment */ ;
	    t -= 1;
	    class (v);
	    // deduce class from tag
	    if (c < 0) {
	       // insert %PARAM
	       c = (-(c));
	       setcell (196, tp);
	       tp = (-(1));
	    }
	    setcell (c, tp);
	    if (t == local)
	       break;		// end of parameters
	    setcell (comma, (-(1)));
	    // add the separating comma
	 }
	 if (gmax > gmin)
	    abandon (3);
	 return (link);
	 auto void setcell (int g, int tt)
	 {
	    // add the cell to the grammar, combining common tails
	    while (p != gmax) {
	       p += 1;
	       if ((glink (p) == link && gram (p) == g)) {
		  if ((tt < 0 || (gram (p + 1) == tt && glink (p + 1) == ap))) {
		     link = p;
		     // already there
		     return;
		  }
	       }
	    }
	    // add a new cell
	    gmax += 1;
	    gram (gmax) = g;
	    glink (gmax) = link;
	    link = gmax;
	    if (tt >= 0) {
	       // set type cell
	       gmax += 1;
	       gram (gmax) = tt;
	       glink (gmax) = ap;
	    }
	    p = gmax;
	 }
	 auto void class (tagfm * v)
	 {
	 static int err = 89;
	 static int rtp = 100;
	 static int fnp = 101;
	 static int mapp = 102;
	 static int predp = 103;
	 static int classmap[15 - 0 + 1];
	 int tags;
	 int type;
	 int form;

	    ap = 0;
	    tags = v->flags;
	    type = tags >> 4 & 7;
	    form = tags & 15;
	    tp = v->format << 3 | type;
	    c = classmap[form];
	    if ((type == 0 && form == 2)) {
	       c = 208;
	       tp = 0;
	    }			// %name
	    if (tags & parameters != 0)
	       ap = v->app;
	 }
      }
      auto void deletenames (int quiet)
      {
	 int flags;
	 tagfm *tx;

	 while (tmax > tbase) {
	    x = tmax;
	    tmax -= 1;
	    tx = &tag[x] /* Pointer assignment */ ;
	    flags = tx->flags;
	    if ((flags & spec != 0 && flags & ownbit == 0))
	       fault (20);
	    // {spec with no definition & not external}
	    if ((flags & usedbit == 0 && (level >= 0 && list <= 0))) {
	       if (quiet == 0)
		  fault ((-(3)));
	       // unused
	    }
	    dict[tx->text] = tx->link;
	 }
      }
      auto void analyse (void)
      {
	 static int orderbits = 0x3000, orderbit = 0x1000;
	 static int escape = 0x1000;
	 int strp;
	 int mark;
	 int flags;
	 int proterr;
	 int k;
	 int s;
	 int c;
	 static int key = 0;
	 int node;
	 int *z;
	 arfm *arp;
	 static void *act[ /* bounds */ ] = { &&act_default };
	 auto void traceanalysis (void)
	 {
	    // diagnostic trace routine (diagnose&1 # 0)
	    int a;
	    auto void show (int a)
	    {
	       if ((0 < a && a < 130)) {
		  space ();
		  printstring (text (a));
	       } else
		  write (a, 3);
	    }
	    static int la1 = 0, la2 = 0, lsa = 0, lt = 0;

	    if ((monpos != pos && sym != nl))
	       newline ();
	    monpos = pos;
	    write (g, 3);
	    space ();
	    printstring (text (class));
	    if (gg & transbit != 0)
	       printsymbol ('"');
	    a = gg >> 8 & 15;
	    if (a != 0) {
	       printsymbol ('{');
	       write (a, 0);
	       printsymbol ('}');
	    }
	    if ((atom1 != la1 || (atom2 != la2 || (lsa != subatom || lt != type)))) {
	       printstring (" [");
	       la1 = atom1;
	       show (la1);
	       la2 = atom2;
	       show (la2);
	       lsa = subatom;
	       write (lsa, 3);
	       lt = type;
	       write (lt, 5);
	       printsymbol (']');
	    }
	    newline ();
	 }
	 auto void getsym (void)
	 {
	    readsymbol (sym);
	    if (sym < 0)
	       abandon (5);
	    if (pos != 133)
	       pos += 1;
	    _char_[pos] = sym;
	    if (list <= 0)
	       printsymbol (sym);
	    column += 1;
	 }
	 auto void readsym (void)
	 {
	    static int last = 0;
	    static unsigned char mapped[127 - 0 + 1];

	    // ! 0 = space
	    // ! 1 = %
	    // ! 2 = {
	    // ! 3 = ff
	    // ! other values represent themselves
	    if (sym == nl) {
	     s1:
	       lines += 1;
	       if (endmark != 0)
		  printsymbol (endmark);
	     s11:
	       pos = 0;
	       pos1 = 0;
	       pos2 = 0;
	       margin = 0;
	       column = 0;
	       last = 0;
	       endmark = 0;
	       if (list <= 0) {
		  if (include != 0) {
		     printstring (" &");
		     write (lines, (-(4)));
		  } else
		     write (lines, 5);
		  csym = cont;
		  printsymbol (csym);
		  space ();
		  if (errormargin != 0) {
		     lines -= 1;
		     spaces (errormargin);
		     errormargin = 0;
		     if (errorsym != 0) {
			printsymbol (errorsym);
			pos = 1;
			_char_[1] = errorsym;
			sym = errorsym;
			errorsym = 0;
			goto s5;
		     }
		  }
	       }
	     s2:
	       symtype = 1;
	    }
	  s3:
	    readsymbol (sym);
	    if (sym < 0)
	       abandon (5);
	    if (pos != 133)
	       pos += 1;
	    _char_[pos] = sym;
	    if (list <= 0)
	       printsymbol (sym);
	    column += 1;
	  s5:
	    if (sym != nl) {
	       last = sym;
	       if (quote != 0)
		  return;	// dont alter strings
	       sym = mapped[sym & 127];
	       if (sym <= 3) {
		  // special symbol
		  if (sym == 0)
		     goto s2;
		  // space (or dubious control)
		  if (sym == 1) {
		     symtype = 2;
		     goto s3;
		  }		// %
		  if (sym == 3) {
		     cont = '+';
		     goto s11;
		  }		// ff
		  // must be {...
		  for (;;) {
		     getsym ();
		     if (sym == '}')
			goto s3;
		     if (sym == nl)
			goto s4;
		  }
	       }
	       key = kdict (sym);
	       if ((key & 3 == 0 && symtype == 2)) {
		  // keyword
		  if ((sym == 'C' && nextsymbol == nl)) {
		     // %c...
		     getsym ();
		     cont = '+';
		     goto s1;
		  }
	       } else {
		  symtype = key & 3 - 2;
	       }
	       return;
	    }
	  s4:
	    symtype = quote;
	    if ((last == 0 && quote == 0))
	       goto s1;
	    cont = '+';
	 }
	 auto int formatselected (void)
	 {
	    formatlist = &tag[format]->app;
	    // number of names
	    if (formatlist < 0) {
	       // forward ref
	       atom1 = error + 22;
	       return (0);
	    }
	    if (sym == '_') {
	       escapeclass = escrec;
	       searchbase = &tag[format]->format;
	    }
	    return (1);
	 }
	 auto void codeatom (int target)
	 {
	    int dbase;
	    int da;
	    int base;
	    int n;
	    int mul;
	    int pendquote;
	    int j;
	    int k;
	    int l;
	    int pt;
	    auto void lookup (int d)
	    {
	       int newname;
	       int vid;
	       int k1;
	       int k2;
	       int form;
	       tagfm *t;
	       int new;

	       // twee little function because SKIMP86 can't do string compare properly
	       // returns 1 if the two names are the same, else zero
	       auto int dictmatch (int ptr1, int ptr2)
	       {
		  int len;

		  // start with a cheap check of the length and first character
		  if (dict[ptr1] != dict[ptr2])
		     return (0);
		  len = dict[ptr1] & 255;
		  ptr1 += 1;
		  ptr2 += 1;
		  len -= 1;
		  while (len >= 2) {
		     if (dict[ptr1] != dict[ptr2])
			return (0);
		     ptr1 += 1;
		     ptr2 += 1;
		     len -= 2;
		  }
		  // if the string was odd length, we might need one last byte checked
		  if (len == 1) {
		     if (dict[ptr1] & 255 != dict[ptr2] & 255)
			return (0);
		  }
		  return (1);
	       }
	       // first locate the text of the name
	       new = dmax + 1;
	       // points to text of string in dictionary
	       k1 = hashvalue & maxnames;
	       // rather crude hash!
	       for (;;) {
		  newname = hash[k1];
		  if (newname == 0)
		     break;	// not in
		  if (dictmatch (newname + 1, new) == 1)
		     goto in;
		  k1 = (k1 + 1) & maxnames;
	       }
	       // not found
	       sparenames -= 1;
	       if (sparenames <= 0)
		  abandon (2);
	       hash[k1] = dmax;
	       // put it in
	       dict[dmax] = (-(1));
	       newname = dmax;
	       dmax = dp;
	       goto notin;
	     in:
	       if ((this >= 0 && d != 0))
		  searchbase = rbase;
	       // record elem defn
	       if (searchbase != 0) {
		  // record subname
		  new = (-(1));
		  x = searchbase;
		  for (;;) {
		     if (x < formatlist)
			goto notin;
		     if (&tag[x]->text == newname)
			break;
		     x -= 1;
		  }
	       } else {
		  // hash in for normal names
		  x = dict[newname];
		  if (x <= limit)
		     goto notin;
		  // wrong level
	       }
	       subatom = x;
	       // name found, extract info
	       t = &tag[x] /* Pointer assignment */ ;
	       atomflags = t->flags;
	       format = t->format;
	       app = t->app;
	       protection = atomflags & prot;
	       type = atomflags >> 4 & 7;
	       atom1 = amap[atomflags & 15];
	       if (diag & 8 != 0) {
		  printstring ("lookup:");
		  write (atom1, 3);
		  write (type, 1);
		  write (app, 3);
		  write (format, 5);
		  write (atomflags, 3);
		  newline ();
	       }
	       if (d == 0) {
		  // old name wanted
		  t->flags = t->flags | usedbit;
		  searchbase = 0;
		  if ((atomflags & subname != 0 && format != 0)) {
		     // a record
		     if (formatselected () == 0)
			return;
		  }
		  if (atomflags & parameters != 0) {
		     // proc or array
		     if (app == 0) {
			// no parameters needed
			atom2 = atom1;
			atom1 -= 4;
			if ((97 <= atom1 && atom1 <= 98)) {
			   mapgg = atom1;
			   atom1 = var;
			}
		     } else {
			if (sym == '(') {
			   searchbase = 0;
			   // ignore format for now
			   if (atom1 >= 106) {
			      // arrays
			      app = phrase (app + 200);
			      escapeclass = escarray;
			      atom1 = (atom1 - 106) >> 1 + 91;
			      // a,an->v na,nan->n
			   } else {
			      // procedures
			      escapeclass = escproc;
			      atom1 -= 4;
			   }
			   phrase (200) = app;
			}
		     }
		     pos2 = pos;
		     return;
		  }
		  // deal with constintegers etc
		  if ((atomflags & constbit != 0 && atom1 == var)) {
		     mapgg = _const_;
		     atom2 = _const_;
		     if (type == integer)
			subatom = (-(subatom));
		  }
		  return;
	       }
	       // new name wanted
	       if (tbase != tstart)
		  goto notin;
	       // don't fault proc parm-parm
	       if (d == lab + spec + usedbit) {
		  t->flags = t->flags | usedbit;
		  return;
	       }
	       if (atomflags & spec != 0) {
		  // a spec has been given
		  if (d == lab) {
		     // define label
		     t->flags = t->flags - spec;
		     return;
		  }
		  if ((7 <= decl & 15 && (decl & 15 <= 10 && decl & spec == 0))) {
		     // procedure definition after spec
		     if ((decl ^ atomflags) & 0b1111111 == 0) {
			// correct type?
			t->flags = t->flags - spec;
			specgiven = 1;
			return;
		     }
		     // note that an external procedure must be speced as a
		     // non-external procedure.
		  }
		  if (decl & 15 == recfm) {
		     // recordformat
		     t->flags = record << 4 + recfm;
		     t->format = fdef;
		     return;
		  }
	       }
	       if ((last1 == jump && atom1 == swit))
		  return;
	       if (copy == 0)
		  copy = x;
	     notin:
	       app = 0;
	       vid = 0;
	       atom1 = error + 2;
	       if (d == 0)
		  return;	// old name wanted
	       type = d >> 4 & 7;
	       form = d & 15;
	       atom1 = amap[form];
	       if (this < 0) {
		  // normal scope
		  new = newname;
		  tmax += 1;
		  x = tmax;
	       } else {
		  // recordformat scope
		  new = (-(1));
		  recid -= 1;
		  vid = recid;
		  tmin -= 1;
		  x = tmin;
		  formatlist = tmin;
	       }
	       if ((11 <= form && form <= 14)) {
		  // arrays
		  if (dim == 0)
		     dim = 1;
		  // set dim for owns
		  app = dim;
	       }
	       if (((otype > 2 && d & spec == 0) || (perm != 0 || level == includelevel)))
		  d = d | usedbit;
	       // external definitions need not be used in the file in which
	       // they are defined, so inhibit a useless unused warning.
	       t = &tag[x] /* Pointer assignment */ ;
	       if (form == lab) {
		  id += 1;
		  vid = id;
	       }
	       t->index = vid;
	       t->text = newname;
	       t->flags = d;
	       t->app = app;
	       t->format = fdef;
	       format = fdef;
	       subatom = x;
	       if (new >= 0) {
		  // insert into hash table
		  t->link = dict[new];
		  dict[new] = x;
		  if (gmin == maxgrammar) {
		     // proc param params
		     tmin -= 1;
		     subatom = tmin;
		     &tag[tmin] = t;
		  }
	       }
	       if (tmax >= tmin)
		  abandon (3);
	    }
	  top:
	    pos1 = pos;
	    subatom = 0;
	    pendquote = 0;
	    atomflags = 0;
	    // app and format must be left for assigning to papp & pformat
	    if (symtype == (-(2)))
	       goto name;
	    // letter
	    if (symtype < 0)
	       goto number;
	    // digit
	    if (symtype == 0) {
	       atom1 = termin;
	       atom2 = 0;
	       return;
	    }
	    if (symtype != 2) {
	       // catch keywords here
	       if (quote != 0)
		  goto text;
	       // completion of text
	       if (sym == squote)
		  goto strings;
	       // start of string
	       if (sym == cquote)
		  goto symbols;
	       // start of symbol
	       if ((sym == '.' && ('0' <= nextsymbol && nextsymbol <= '9')))
		  goto number;
	    }
	    // locate atom in fixed dict
	    k = key >> 2;
	    readsym ();
	    for (;;) {
	       j = kdict (k);
	       if (j & 0x4000 != 0)
		  break;
	       if ((j & 127 != sym || symtype < 0)) {
		  if (!(j < 0))
		     goto err;
		  k += 1;
	       } else {
		  l = j >> 7 & 127;
		  readsym ();
		  if (j > 0) {
		     if (l != 0) {
			if ((l != sym || symtype < 0))
			   goto err;
			readsym ();
		     }
		     l = 1;
		  }
		  k += l;
	       }
	    }
	    atom1 = j & 127;
	    if (atom1 == 0) {
	       // comma
	       atom1 = 19;
	       subatom = 19;
	       atom2 = 0;
	       if (sym == nl) {
		  if (ocount >= 0)
		     return;	// special action needs to be taken with <comma nl> as
		  // const array lists can be enormous
		  readsym ();
	       }
	       return;
	    }
	    atom2 = j >> 7 & 127;
	    subatom = kdict (k + 1) & 0x3FFF;
	    // !!!!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;
	    if (pos - pos1 > 2)
	       pos1 = pos;
	    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;
	    mapgg = _const_;
	    protection = prot;
	    subatom = lp;
	    if (lp >= litmax)
	       abandon (3);
	    quote = (~(pendquote));
	    return;		// an integer constant is acceptable so get it in and
	    // get the next atom
	  chars:
	    n = 0;
	    cont = cquote;
	    for (;;) {
	       readsym ();
	       if (sym == cquote) {
		  if (nextsymbol != cquote)
		     break;
		  readsym ();
	       }
	       if (n & ((~((((-(1))) >> bytesize)))) != 0) {
		  // overflow
		  pos1 = pos;
		  atom1 = error + 10;
		  return;
	       }
	       if (quote == 0)
		  goto err;
	       n = n << bytesize + sym;
	       quote += 1;
	    }
	    quote = 0;
	    cont = ' ';
	    if (sym != nl)
	       readsym ();
	    litpool[lp] = n;
	    lp += 1;
	    goto top;
	    // sniff the grammar before getting the string
	  strings:
	    atom1 = var;
	    atom2 = _const_;
	    type = stringv;
	    subatom = strp | 0x4000;
	    mapgg = _const_;
	    protection = prot;
	    quote = subatom;
	    textline = lines;
	    // in case of errors
	    return;		// a string constant is ok here, so pull it in and get
	    // the next atom
	    // ABD - temp variable to help pack bytes into words
	    int flipflop;

	  text:
	    if (quote < 0)
	       goto chars;
	    // character consts
	    l = strp;
	    // point to beginning
	    k = 0;
	    // length so far
	    flipflop = 0;
	    // space for the length is up the spout
	    for (;;) {
	       cont = squote;
	       quote = 1;
	       for (;;) {
		  readsym ();
		  if (sym == squote) {
		     // terminator?
		     if (nextsymbol != squote)
			break;	// yes ->
		     readsym ();
		     // skip quote
		  }
		  if (flipflop >= 0) {
		     glink (strp) = sym << 8 + flipflop;
		     strp += 1;
		     flipflop = (-(1));
		  } else {
		     flipflop = sym;
		  }
		  k += 1;
		  if (k > 255) {
		     lines = textline;
		     abandon (7);
		  }		// too many chars
	       }
	       if (flipflop >= 0) {
		  // tail-end charlie
		  glink (strp) = flipflop;
		  strp += 1;
	       }
	       glink (l) = glink (l) | k;
	       // plug in length
	       quote = 0;
	       cont = ' ';
	       readsym ();
	       codeatom (target);
	       if (!((atom1 == 48 && sym == squote)))
		  return;	// fold "???"."+++"
	    }
	    auto void get (int limit)
	    {
	       int s;
	       int shift;

	       shift = 0;
	       if (base != 10) {
		  if (base == 16) {
		     shift = 4;
		  } else {
		     if (base == 8) {
			shift = 3;
		     } else {
			if (base == 2) {
			   shift = 1;
			}
		     }
		  }
	       }
	       n = 0;
	       for (;;) {
		  if (symtype == (-(1))) {
		     // digit
		     s = sym - '0';
		  } else {
		     if (symtype < 0) {
			// letter
			s = sym - 'A' + 10;
		     } else {
			return;
		     }
		  }
		  if (s >= limit)
		     return;
		  pt += 1;
		  glink (pt) = sym;
		  if (base == 10) {
		     // check overflow
		     if ((n >= maxint && (s > maxdig || n > maxint))) {
			// too big for an integer,
			// so call it a real
			base = 0;
			type = real;
			n = 0;
		     }
		  }
		  if (shift == 0) {
		     n = n * base + s;
		  } else {
		     n = n << shift + s;
		  }
		  readsym ();
	       }
	    }
	  number:
	    base = 10;
	  bxk:
	    atom1 = var;
	    atom2 = _const_;
	    type = integer;
	    subatom = lp;
	    mapgg = _const_;
	    protection = prot;
	    if (lp >= litmax)
	       abandon (3);
	    pt = strp;
	    mul = 0;
	    for (;;) {
	       get (base);
	       if (!((sym == '_' && (base != 0 && pendquote == 0))))
		  break;	// change of base
	       pt += 1;
	       glink (pt) = '_';
	       readsym ();
	       base = n;
	    }
	    if (pendquote != 0) {
	       if (sym != cquote)
		  goto err;
	       readsym ();
	    }
	    if (sym == '.') {
	       // a real constant
	       pt += 1;
	       glink (pt) = '.';
	       readsym ();
	       type = real;
	       n = base;
	       base = 0;
	       get (n);
	    }
	    if (sym == '@') {
	       // an exponent
	       pt += 1;
	       glink (pt) = '@';
	       k = pt;
	       readsym ();
	       type = integer;
	       base = 10;
	       if (sym == '-') {
		  readsym ();
		  get (10);
		  n = (-(n));
	       } else {
		  get (10);
	       }
	       pt = k + 1;
	       glink (pt) = lp;
	       litpool[lp] = n;
	       lp += 1;
	       if (base == 0)
		  atom1 = error + 10;
	       type = real;
	       // exponents force the type
	    }
	    if (type == real) {
	       glink (strp) = pt - strp;
	       // store the length (difference)
	       subatom = (strp) | 0x2000;
	       strp = pt + 1;
	    } else {
	       litpool[lp] = n;
	       lp += 1;
	    }
	    return;
	  name:
	    if ((27 <= target && target <= 41)) {
	       atom1 = 0;
	       return;
	    }
	    hashvalue = 0;
	    // ABD changed to remove dependency on direct addressing
	    dp = dmax + 1;
	    dbase = dp;
	    n = 0;
	    dict[dp] = 0;
	    for (;;) {
	       hashvalue += (hashvalue + sym);
	       // is this good enough?
	       dict[dp] = dict[dp] | (sym << 8);
	       n += 1;
	       dp += 1;
	       readsym ();
	       if (symtype >= 0)
		  break;
	       dict[dp] = sym;
	       n += 1;
	       readsym ();
	       if (symtype >= 0)
		  break;
	    }
	    if (sym == cquote) {
	       pendquote = 100;
	       if (hashvalue == 'M')
		  goto symbols;
	       readsym ();
	       if (hashvalue == 'X') {
		  base = 16;
		  goto bxk;
	       }
	       if ((hashvalue == 'K' || hashvalue == 'O')) {
		  base = 8;
		  goto bxk;
	       }
	       if (hashvalue == 'B') {
		  base = 2;
		  goto bxk;
	       }
	       goto err;
	    }
	    dict[dbase] = dict[dbase] | n;
	    if (n & 1 == 0)
	       dp += 1;
	    if (dp >= dmin)
	       abandon (8);
	    atom2 = 90;
	    // ident
	    if ((last1 == 0 && sym == ':')) {
	       // label
	       limit = local;
	       lookup (lab);
	       return;
	    }
	    if (last1 == jump) {
	       // ->label
	       limit = local;
	       lookup (lab + spec + usedbit);
	       return;
	    }
	    if ((decl != 0 && target == 90)) {
	       // identifier
	       searchbase = fmbase;
	       limit = local;
	       lookup (decl);
	       searchbase = 0;
	    } else {
	       limit = 0;
	       lookup (0);
	    }
	 }
	 auto int parsedmachinecode (void)
	 {
	    // *opcode_??????????
	    if (!(symtype == (-(2)))) {
	       atom1 = error;
	       return (0);
	    }			// starts with letter
	    flushbuffer (128);
	    // flush if bp >= 128
	    addchar ('w');
	    for (;;) {
	       addchar (sym);
	       readsym ();
	       if ((sym == '_' || symtype == 0))
		  break;
	    }
	    // pull in letters and digits
	    addchar ('_');
	    if (symtype != 0) {
	       // not terminator
	       readsym ();
	       while (symtype != 0) {
		  if (symtype < 0) {
		     // complex
		     codeatom (0);
		     if (atom1 & error != 0)
			return (0);
		     if ((atom2 == _const_ && type == integer)) {
			if (subatom < 0)
			   setconst (&tag[(-(subatom))]->format);
			else
			   setconst (litpool[subatom]);
		     } else if ((91 <= atom1 && atom1 <= 109)) {
			if ((atom1 == 104 && &tag[subatom]->flags & closed == 0)) {
			   this = subatom;
			   atom1 = error + 21;
			   return (0);
			}
			op (' ', &tag[subatom]->index);
		     } else {
			atom1 = error;
			return (0);
		     }
		  } else {
		     if (symtype == 2)
			sym = sym | 128;
		     addchar (sym);
		     readsym ();
		  }
	       }
	    }
	    addchar (';');
	    return (1);
	 }
	 if (gg == 0)
	    cont = ' ';
	 last1 = 0;
	 mapgg = 0;
	 s = 0;
	 ss = 0;
	 sstype = (-(1));
	 fdef = 0;
	 fmbase = 0;
	 app = 0;
	 // deal with alignment following an error in one statement
	 // of several on a line
	 margin = column;
	 // start of statement
	 pos = 0;
	 strp = gmax + 1;
	 lp = 0;
	 tbase = tstart;
	 // ??????????????
	 local = tbase;
	 if ((gg == 0 || ocount >= 0)) {
	    // data or not continuation(z)
	  again:
	    while (symtype == 0) {
	       // skip redundant terminators
	       c = cont;
	       cont = ' ';
	       if (ocount >= 0)
		  cont = '+';
	       readsym ();
	       cont = c;
	    }
	    if (sym == '!')
	       goto skip;
	    // comment
	    this = (-(1));
	    codeatom (0);
	    if (atom1 == comment) {
	     skip:
	       quote = 1;
	       c = cont;
	       while (sym != nl) {
		  readsym ();
		  cont = c;
	       }		// skip to end of line
	       quote = 0;
	       symtype = 0;
	       goto again;
	    }
	 }
	 decl = 0;
	 mark = 0;
	 gentype = 0;
	 force = 0;
	 dim = 0;
	 proterr = 0;
	 node = 0;
	 nmax = 0;
	 nmin = recsize + 1;
	 order = 1;
	 gmin = maxgrammar + 1;
	 if (gg != 0) {
	    sstype = 0;
	    goto more;
	 }			// continuation
	 ptype = 0;
	 specgiven = 0;
	 stats += 1;
	 if (perm == 0)
	    op ('O', lines);
	 if (atom1 & error != 0)
	    goto fail1;
	 // first atom faulty
	 if (escapeclass != 0) {
	    // enter the hard way after
	    g = impphrase;
	    sstype = (-(1));
	    goto a3;
	 }
	 g = initial (atom1);
	 // pick up entry point
	 if (g == 0) {
	    // invalid first atom
	    g = initial (0);
	    sstype = 0;
	    goto a3;
	    // declarator?
	 }
	 if (g < 0) {
	    // phrase imp
	    g = g & 255;
	    nmax = 1;
	    &ar[1]->class = 0;
	    &ar[1]->link = 0;
	    &ar[1]->sub = impphrase;
	 }
	 gg = gram (g);
	 class = gg & 255;
	 sstype = gg >> 12 & 3 - 1;
	 goto a1;
       act_194:		/* 194 */
	 ptype = type;
	 papp = app;
	 pformat = format;
	 goto more;
       act_196:		/* 196 */
	 k = g + 1;
	 goto a610;
       act_188:		/* 188 */
	 k = &ar[nmax]->sub + 1;
       a610:
	 papp = glink (k);
	 k = gram (k);
	 if (k == 0)
	    goto more;
	 // %name
	 ptype = k & 7;
	 pformat = k >> 3;
       act_183:		/* 183 */
	 k = type;
	 if ((gentype == 0 || k == real))
	    gentype = k;
	 if (pformat < 0) {
	    // general type
	    app = papp;
	    format = pformat;
	    if ((ptype == real && type == integer))
	       k = real;
	    if (force != 0) {
	       k = force;
	       force = 0;
	    }
	 }
	 if (!((papp == app && (ptype == k || ptype == 0))))
	    goto fail2;
	 if ((pformat == format || (pformat == 0 || format == 0)))
	    goto more;
	 goto fail2;
       act_197:		/* 197 */
	 arp = &ar[nmin] /* Pointer assignment */ ;
	 k = arp->sub;
	 if (!(blockform == k & 15))
	    goto fail3;
	 arp->sub = k >> 4;
	 type = blocktype;
	 ptype = blocktype;
	 pformat = blockfm;
	 papp = app;
	 if (ptype != record)
	    pformat = (-(1));
	 goto more;
       act_195:		/* 195 */
	 if ((type != 0 && (type != integer && type != real)))
	    goto fail2;
	 arp = &ar[nmin] /* Pointer assignment */ ;
	 k = arp->sub;
	 arp->sub = k >> 2;
	 k = k & 3;
	 // 1 = check integer
	 // 2 = check real
	 // 3 = check real + int
	 if (k == 0)
	    goto more;
	 // 0 = no action
	 if (k == 1) {
	    force = integer;
	    if ((type == integer || type == 0))
	       goto more;
	    goto fail2;
	 }
	 if (!((ptype == real || ptype == 0)))
	    goto fail2;
	 // {or added?}
	 if (k == 3)
	    force = integer;
	 goto more;
       act_198:		/* 198 */
	 // %OTHER
	 k = gg >> 8 & 15;
	 if (k == 0) {
	    // restore atom
	    atom1 = last1;
	    goto more;
	 }
	 if (k == 1) {
	    // test string
	    if (!(type == stringv))
	       goto fail2;
	    goto more;
	 }
	 if (k == 2) {
	    // {fault record comparisons}
	    if (type == record)
	       goto fail2;
	    goto more;
	 }
	 if (k == 3) {
	    // check OWN variable coming
	    codeatom (0);
	    if (atomflags & ownbit == 0)
	       goto a7;
	    goto more;
	 }
	 if (x <= local)
	    forwarn = pos1;
	 // %for TEST
	 goto more;
       paction_1:		/* 1 */
	 if (type == record)
	    g = phrase (242);
	 else
	    pformat = (-(1));
	 goto a3;
       paction_2:		/* 2 */
	 ptype = real;
	 pformat = (-(1));
	 goto a3;
       paction_3:		/* 3 */
	 ptype = stringv;
	 pformat = (-(1));
	 goto a3;
       paction_4:		/* 4 */
	 ptype = integer;
	 pformat = (-(1));
	 goto a3;
       paction_5:		/* 5 */
	 if (ptype == integer)
	    goto a3;
	 if (ptype == real) {
	    g = phrase (212);
	    pformat = (-(1));
	 }
	 if (ptype == stringv)
	    g = phrase (213);
	 goto a3;
       paction_6:		/* 6 */
	 ptype = gram (&ar[nmax]->sub + 1) & 7;
	 pformat = (-(1));
	 goto a3;
       paction_7:		/* 7 */
	 if (ptype == integer)
	    ptype = real;
	 pformat = (-(1));
	 goto a3;
       a1:
	 last1 = class;
	 atom1 = 0;
	 s = subatom;
       a2:
	 if (gg & transbit == 0) {
	    // insert into analysis record
	    z = node /* Pointer assignment */ ;
	    for (;;) {
	       // insert cell in order
	       k = z;
	       if ((gg & orderbits == 0 || k == 0))
		  break;
	       gg -= orderbit;
	       z = &ar[k]->link /* Pointer assignment */ ;
	    }
	    if ((mapgg != 0 && gg & 255 == var))
	       gg = mapgg;
	    nmin -= 1;
	    if (nmin == nmax)
	       goto fail0;
	    z = nmin;
	    arp = &ar[nmin] /* Pointer assignment */ ;
	    arp->sub = s;
	    arp->class = (gg & 255) | mark;
	    arp->link = k;
	 }
	 mark = 0;
	 mapgg = 0;
       more:
	 g = glink (g);
	 // chain down the grammar
       paction_0:		/* 0 */
       a3:
	 gg = gram (g);
	 class = gg & 255;
	 if (diag & 1 != 0)
	    traceanalysis ();
	 if (class == 0)
	    goto a5;
	 // end of phrase
	 if (class < actions) {
	    // not a phrase or an action
	    if (class >= figurative)
	       class = atomic (class);
	    if (class >= manifest)
	       goto a2;
	    if (atom1 == 0)
	       codeatom (class);
	    if (escapeclass != 0) {
	       // escape to new grammar
	       class = escapeclass;
	       escapeclass = 0;
	       g += escape;
	       // note that following an escape the next item is
	       // forced to be transparent!
	     esc:
	       gg = 0;
	       arp = &ar[nmax + 1] /* Pointer assignment */ ;
	       arp->papp = papp;
	       arp->x = x;
	       goto a4;
	    }
	    if ((class == atom1 || class == atom2))
	       goto a1;
	  a7:
	    if (gg >= 0)
	       goto fail1;
	    // no alternative
	    g += 1;
	    goto a3;
	 }
	 if (class >= phrasal) {
	    // a phrase
	  a4:
	    nmax += 1;
	    if (nmax == nmin)
	       goto fail0;
	    arp = &ar[nmax] /* Pointer assignment */ ;
	    arp->ptype = ptype;
	    arp->pos = pos1;
	    arp->pformat = pformat;
	    arp->link = gentype;
	    arp->class = node;
	    arp->sub = g;
	    node = 0;
	    g = phrase (class);
	    if (force != 0) {
	       ptype = force;
	       force = 0;
	    }
	    gentype = 0;
	    goto *paction[gg >> 8 & 15];
	 }
	 goto *act[class];
	 // only actions left
       a5:
	 // REVERSELINKS
	 s = 0;
	 while (node != 0) {
	    z = &ar[node]->link /* Pointer assignment */ ;
	    k = z;
	    z = s;
	    s = node;
	    node = k;
	 }
	 ss = s;
       a6:
	 if (nmax != 0) {
	    k = gentype;
	    // type of phrase
	    arp = &ar[nmax] /* Pointer assignment */ ;
	    nmax -= 1;
	    node = arp->class;
	    gentype = arp->link;
	    ptype = arp->ptype;
	    pformat = arp->pformat;
	    g = arp->sub;
	    if (g & escape != 0) {
	       g -= escape;
	       papp = arp->papp;
	       mark = 255;
	       subatom = s;
	       goto a3;
	    }
	    if ((gentype == 0 || k == real))
	       gentype = k;
	    type = gentype;
	    k = gg;
	    // exit-point code
	    for (;;) {
	       gg = gram (g);
	       if (k == 0)
		  goto a2;
	       if (gg >= 0)
		  goto fail1;
	       // no alternative phrase
	       k -= orderbit;
	       g += 1;
	       // sideways step
	    }
	 }
	 if (copy != 0)
	    fault (4);
	 if (order == 0)
	    fault (13);
	 if (forwarn != 0)
	    fault ((-(4)));
	 pos1 = 0;
	 faultrate -= 1;
	 return;
       act_193:		/* 193 */
	 if (!((sym == '=' || sym == '<'))) {
	    gg = 0;
	    goto a5;
	 }			// cdummy
       act_181:		/* 181 */
	 atom1 = amap[decl & 15];
	 // dummy
	 goto more;
       act_182:		/* 182 */
	 class = escdec;
	 g = glink (g) | escape;
	 decl = 0;
	 otype = 0;
	 goto esc;
	 // decl
       act_199:		/* 199 */
	 // COMPILE
	 s = 0;
	 while (node != 0) {
	    z = &ar[node]->link /* Pointer assignment */ ;
	    k = z;
	    z = s;
	    s = node;
	    node = k;
	 }
	 ss = s;
	 if (quote != 0)
	    codeatom (28);
	 // expend
	 compile ();
	 if (atom1 & error == 0)
	    goto more;
	 goto fail1;
       act_184:		/* 184 */
	 if (!(type == integer))
	    goto fail4;
	 if (subatom < 0)
	    lit = &tag[(-(subatom))]->format;
	 else
	    lit = litpool[subatom];
	 if (lit != 0)
	    goto fail4;
	 goto more;
       act_185:		/* 185 */
	 // APPLYPARAMETERS
	 s = 0;
	 while (node != 0) {
	    z = &ar[node]->link /* Pointer assignment */ ;
	    k = z;
	    z = s;
	    s = node;
	    node = k;
	 }
	 ss = s;
	 atom1 = &ar[s]->class;
	 atom2 = 0;
	 if ((atom1 == 97 || atom1 == 98))
	    atom1 = var;
	 arp = &ar[nmax] /* Pointer assignment */ ;
	 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;
	 if (flags & aname != 0)
	    protection = 0;
	 if ((flags & subname != 0 && format != 0)) {
	    if (formatselected () == 0)
	       goto fail1;
	 }
	 goto a6;
       act_187:		/* 187 */
	 protection = prot;
	 goto more;
	 // %SETPROT
       act_186:		/* 186 */
	 if (protection & prot == 0)
	    goto more;
	 proterr = nmin;
	 goto a7;
       act_191:		/* 191 */
	 k = protection;
	 // %GUARD
	 codeatom (0);
	 if (atomflags & aname == 0)
	    protection = k;
	 goto more;
       act_192:		/* 192 */
	 if (parsedmachinecode () == 0)
	    goto fail1;
	 goto more;
       act_189:		/* 189 */
	 k = gapp ();
	 // %GAPP
	 deletenames (1);
	 tmax = tbase;
	 tbase = gram (gmin);
	 // restore tmax
	 local = tbase;
	 gmin += 1;
	 x = &ar[&ar[nmax]->class]->sub;
	 &tag[x]->app = k;
	 // update app
	 goto more;
       act_190:		/* 190 */
	 gmin -= 1;
	 // %LOCAL
	 if (gmin <= gmax)
	    abandon (2);
	 gram (gmin) = tbase;
	 tbase = tmax;
	 local = tbase;
	 goto more;
	 // errors
       fail4:
	 k = error + 10;
	 goto failed;
	 // *size
       fail3:
	 k = error + 7;
	 goto failed;
	 // *context
       fail2:
	 k = error + 5;
	 pos2 = 0;
	 goto failed;
	 // *type
       fail0:
	 k = error + 3;
	 goto failed;
	 // *too complex
       fail1:
	 k = atom1;
	 pos2 = 0;
       failed:
	 if (diag & 32 != 0) {
	    printstring ("Atom1 =");
	    write (atom1, 3);
	    printstring ("  Atom2 =");
	    write (atom2, 3);
	    printstring ("  subatom =");
	    write (subatom, 3);
	    newline ();
	    printstring ("Type =");
	    write (type, 1);
	    printstring ("   Ptype =");
	    write (ptype, 1);
	    newline ();
	    printstring ("App =");
	    write (app, 1);
	    printstring ("   Papp =");
	    write (papp, 1);
	    newline ();
	    printstring ("Format =");
	    write (format, 1);
	    printstring ("   Pformat =");
	    write (pformat, 1);
	    newline ();
	    // %signal 13,15
	 }
	 while ((sym != nl && sym != ';')) {
	    quote = 0;
	    readsym ();
	 }
	 if (k & error != 0) {
	    fault (k & 255);
	 } else {
	    if (proterr == nmin)
	       fault (14);
	    else
	       fault (0);
	 }
	 gg = 0;
	 ss = 0;
	 symtype = 0;
      }
      // of analyse
      auto void compile (void)
      {
	 static int then = 4, else_ = 8, loop = 16;
	 static void *c[ /* bounds */ ] = { &&c_default };
	 static unsigned char operator[14 - 1 + 1];
	 static unsigned char cc[7 - 0 + 1];
	 static unsigned char anyform[15 - 0 + 1];
	 static int decmap[15 - 0 + 1];
	 static unsigned char cnest[15 - 0 + 1];
	 int lmode;
	 int clab;
	 int dupid;
	 int resln;
	 static int lastdef = 0;
	 static int lb, ub;
	 int cp;
	 int ord;
	 int next;
	 int link;
	 int j;
	 int k;
	 int n;
	 int done;
	 int class;
	 int lit2;
	 int defs;
	 int decs;
	 int cident;
	 int pending;
	 static int pstack[40 - 1 + 1];
	 static char *name = "";
	 static int count = 0;
	 auto void deflab (int l)
	 {
	    op (':', l);
	    access = 1;
	 }
	 auto void getnext (void)
	 {
	    arfm *p;

	  gn:
	    if (next == 0) {
	       // end of phrase
	       if (link == 0) {
		  class = 0;
		  return;
	       }		// end of statement
	       p = &ar[link] /* Pointer assignment */ ;
	       next = p->link;
	       link = p->sub;
	    }
	    for (;;) {
	       p = &ar[next] /* Pointer assignment */ ;
	       x = p->sub;
	       class = p->class;
	       if (class < actions)
		  break;	// an atom
	       if (x == 0) {
		  // null phrase
		  next = p->link;
		  goto gn;
	       }
	       if (p->link != 0) {
		  // follow a phrase
		  p->sub = link;
		  link = next;
	       }
	       next = x;
	    }
	    next = p->link;
	    if (diag & 2 != 0) {
	       if (!(strlen (name) == 0))
		  spaces (8 - strlen (name));
	       name = text (class);
	       write (x, 2);
	       space ();
	       printstring (name);
	       space ();
	       count -= 1;
	       if (count <= 0) {
		  count = 5;
		  strcpy (name, "");
		  newline ();
	       }
	    }
	 }
	 auto void setsubs (int n)
	 {
	    // update the app field in n array descriptors
	    int p;

	    p = tmax;
	    while (n > 0) {
	       // %signal 15,15 %if p < tbase
	       &tag[p]->app = dimension;
	       p -= 1;
	       n -= 1;
	    }
	 }
	 auto void setbp (void)
	 {
	    // define a constant bound pair from the last stacked constants
	    pending -= 2;
	    lb = pstack[pending + 1];
	    ub = pstack[pending + 2];
	    if (ub - lb + 1 < 0) {
	       pos1 = 0;
	       next = link;
	       fault (11);
	       ub = lb;
	    }
	    setconst (lb);
	    setconst (ub);
	    if (!(class == 146))
	       addchar ('b');
	 }
	 auto void compileend (int type)
	 {
	    // type = 0:eof, 1:eop, 2:end
	    if (access != 0) {
	       open = 0;
	       if (blockform > proc)
		  fault (19);
	       // can reach end
	    }
	    while (dict[dmin] >= 0) {
	       // finishes & repeats
	       fault (17 + dict[dmin] & 1);
	       dmin += 1;
	    }
	    // {delete names(0)}
	    addchar (';');
	    if (type == 1)
	       addchar (';');
	    // endofprogram
	    bflags = bflags | open;
	    // show if it returns
	    if ((blocktag != 0 && level != 1))
	       deflab (0);
	    // for jump around
	    if (type != 2) {
	       // eop, eof
	       if (level != type)
		  fault (16);
	       // end missing
	    } else {
	       if (level == 0) {
		  fault (15);
		  // spurious end
	       }
	    }
	    endmark = 11;
	    // ******Mouses specific******
	 }
	 auto void def (int p)
	 {
	    // dump a descriptor
	    int t;
	    int f;
	    int type;
	    tagfm *v;

	    flushbuffer (1);
	    // flush if bp > 0
	    defs += 1;
	    v = &tag[p] /* Pointer assignment */ ;
	    t = 0;
	    if (!(v->index < 0)) {
	       // no index for subnames
	       if (v->index == 0) {
		  id += 1;
		  v->index = id;
	       }
	       lastdef = v->index;
	       t = lastdef;
	    }
	    op ('$', t);
	    printident (p, 1);
	    // output the name
	    t = v->flags;
	    type = t;
	    if (type & (7 << 4) >= 6 << 4)
	       type = type & ((~((7 << 4))));
	    // routine & pred
	    op (',', type & 0b1111111);
	    // type & form
	    f = v->format;
	    if (t & 0x70 == record << 4)
	       f = &tag[f]->index;
	    if (f < 0)
	       f = v->index;
	    op (',', f);
	    // format
	    f = otype + t >> 4 & 0b1111000;
	    if (class == 125)
	       f = f | 8;
	    // add spec from %DUP
	    dim = v->app;
	    // dimension
	    if (!((0 < dim && dim <= dimlimit)))
	       dim = 0;
	    op (',', f + dim << 8);
	    // otype & spec & prot
	    if (t & parameters == 0)
	       defs = 0;
	    f = t & 15;
	    if (v->flags & spec != 0) {
	       if (!((3 <= f && f <= 10)))
		  v->flags = v->flags & ((~(spec)));
	       ocount = (-(1));
	       // external specs have no constants
	    }
	    dimension = 0;
	    if ((otype == 2 && (f == 2 || (f == 12 || f == 14)))) {
	       v->flags = v->flags - 1;
	       // convert to simple
	    }
	 }
	 auto void defslab (int n)
	 {
	    // define a switch label, x defines the switch tag
	    int p;
	    int l;
	    int b;
	    int w;
	    int bit;

	    p = &tag[x]->format;
	    // pointer to table
	    l = dict[p];
	    // lower bound
	    if ((l <= n && n <= dict[p + 1])) {
	       b = n - l;
	       w = b >> 4 + p;
	       bit = 1 << (b & 15);
	       if (dict[w + 2] & bit != 0) {
		  // already set
		  if (pending != 0)
		     fault (4);
		  return;
	       }
	       if (pending != 0)
		  dict[w + 2] = dict[w + 2] | bit;
	       setconst (n);
	       op ('_', &tag[x]->index);
	    } else {
	       fault (12);
	    }
	    access = 1;
	 }
	 auto void call (void)
	 {
	    tagfm *t;

	    t = &tag[x] /* Pointer assignment */ ;
	    op ('@', t->index);
	    if (t->flags & closed != 0)
	       access = 0;
	    // never comes back
	    if (t->app == 0)
	       addchar ('E');
	    // no parameters
	 }
	 auto void popdef (void)
	 {
	    setconst (pstack[pending]);
	    pending -= 1;
	 }
	 auto void poplit (void)
	 {
	    if (pending == 0)
	       lit = 0;
	    else {
	       lit = pstack[pending];
	       pending -= 1;
	    }
	 }
	 // conditions & jumps
	 auto void push (int x)
	 {
	    if (cnest[cp] & 2 != x) {
	       cnest[cp] = cnest[cp] | 1;
	       x += 4;
	    }
	    if (cnest[cp] & 1 != 0)
	       clab += 1;
	    cnest[cp + 1] = x;
	    cp += 1;
	 }
	 auto void poplabel (int mode)
	 {
	    lmode = dict[dmin];
	    if ((lmode < 0 || lmode & 1 != mode)) {
	       fault (mode + 8);
	    } else {
	       dmin += 1;
	       _label_ -= 3;
	    }
	 }
	 if (sstype < 0) {
	    // executable statement
	    if (level == 0) {
	       // outermost level
	       fault (13);
	       // *order
	    } else {
	       if (access == 0) {
		  access = 1;
		  fault ((-(1)));
		  // only a warning
	       }
	    }
	 }
	 if (diag & 2 != 0) {
	    if (sym != nl)
	       newline ();
	    printstring ("ss =");
	    write (ss, 1);
	    newline ();
	    count = 5;
	    strcpy (name, "");
	 }
	 next = ss;
	 pending = 0;
	 lmode = 0;
	 link = 0;
	 decs = 0;
	 defs = 0;
	 resln = 0;
	 done = 0;
	 ord = level;
	 if (this >= 0)
	    ord = 1;
	 // recordformat declarations
       c_0:			/* 0 */
       top:
	 if (next != link) {
	    getnext ();
	    goto *c[class];
	 }
	 // all done, tidy up declarations and jumps
	 if ((diag & 2 != 0 && count != 5))
	    newline ();
	 if (lmode & (loop | then | else_) != 0) {
	    // pending labels and jumps
	    if (lmode & loop != 0)
	       op ('B', _label_ - 1);
	    // repeat
	    if (lmode & then != 0)
	       deflab (_label_);
	    // entry from then
	    if (lmode & else_ != 0)
	       deflab (_label_ - 1);
	    // entry from else
	 }
	 if (decs == 0)
	    return;
	 if (atom1 != 0) {
	    atom1 = error;
	    return;
	 }			// %integerroutine
	 order = ord;
	 decl = decl & ((~(15))) + decmap[decl & 15];
	 // construct declarator flags
	 atom1 = atoms[decl & 15];
	 // generate class
	 if (otype != 0) {
	    // own, const etc.
	    if (atom1 != proc)
	       atom1 += 1;
	    if (otype == 2) {
	       // const
	       n = decl & 15;
	       if (n & 1 != 0) {
		  decl = decl | prot;
		  if (decl & 0b1111111 == iform)
		     decl = decl | constbit;
	       }
	    } else {
	       decl = decl | ownbit;
	    }
	 }
	 if ((sstype == 0 && atom1 == proc))
	    sstype = 1;
	 if (decl & spec != 0)
	    atom1 += 1;
	 // onto spec variant
	 if (atom1 == 5) {
	    ocount = 0;
	    cont = '+';
	 }			// own array
	 if (anyform[decl & 15] == 0) {
	    // check meaningful
	    if (decl >> 4 & 7 == record) {
	       if (&tag[fdef]->flags & spec != 0)
		  this = fdef;
	       if (fdef == this)
		  atom1 = error + 21;
	       // *context for format
	    }
	    if (fdef == 0)
	       atom1 = error + 10;
	    // *size
	 }
	 return;
       atop:
	 access = 0;
	 goto top;
	 // declarators
       c_88:			/* 88 */
	 // RTYPE
       c_28:			/* 28 */
	 decl = x & ((~(7)));
	 // stype
	 fdef = x & 7;
	 // precision
	 if (x & 0b1110001 == real << 4 + 1)
	    fdef = realsln;
	 // convert to long
	 decs = 1;
	 goto top;
       c_34:			/* 34 */
	 // OWN
       c_35:			/* 35 */
	 otype = x;
	 ord = 1;
	 goto top;
	 // external
       c_152:			/* 152 */
	 decl = decl + x << 1;
	 goto top;
	 // xname
       c_31:			/* 31 */
	 // PROC
       c_32:			/* 32 */
	 specmode = level + 1;
	 // fn/map
	 if (x == 9)
	    decl = decl | prot;
	 // function
       c_29:			/* 29 */
	 ord = 1;
	 // array
	 dim = 0;
       c_30:			/* 30 */
	 decl += x;
	 // name
	 decs = 1;
	 goto top;
       c_27:			/* 27 */
	 lit = 0;
	 // arrayd
	 if (pending != 0) {
	    poplit ();
	    if (!((0 < lit && lit <= dimlimit))) {
	       atom1 = error + 11;
	       return;
	    }
	 }
	 dim = lit;
	 decl += x;
	 decs = 1;
	 goto top;
       c_37:			/* 37 */
	 x = x | subname;
	 // record
       c_36:			/* 36 */
	 lit = 0;
	 // string
	 if (pending != 0) {
	    poplit ();
	    if (!((0 < lit && lit <= 255))) {
	       // max length wrong
	       atom1 = error + 10;
	       return;
	    }
	 }
	 fdef = lit;
	 // format or length
       c_33:			/* 33 */
	 decl = x;
	 // switch
	 decs = 1;
	 goto top;
       c_39:			/* 39 */
	 decl = decl | spec;
	 // spec
	 ocount = (-(1));
	 // no initialisation
	 specmode = (-(1));
	 goto top;
       c_38:			/* 38 */
	 decl = 64 + 4;
	 // recordformat (spec)
	 order = 1;
	 atom1 = x;
	 if (atom1 == 12)
	    decl = decl | spec;
	 // formatspec
	 fdef = tmax + 1;
	 // format tag
	 return;
       c_175:			/* 175 */
	 id += 1;
	 &tag[x]->index = id;
	 return;		// FSID
       c_41:			/* 41 */
	 decs = 1;
	 decl = x | spec | closed;
	 goto top;
	 // label
       c_133:			/* 133 */
	 recid = 0;
	 rbase = tmin - 1;
	 // fname
	 this = x;
	 fmbase = fdef;
	 formatlist = tmin;
	 def (this);
	 goto top;
       c_148:			/* 148 */
	 if (next == 0) {
	    fdef = 0;
	    goto top;
	 }			// reclb
	 getnext ();
	 // skip name
	 fdef = x;
	 goto top;
       c_127:			/* 127 */
	 addchar ('}');
	 goto top;
	 // %POUT
       c_126:			/* 126 */
	 addchar ('{');
	 goto top;
	 // %PIN
       c_174:			/* 174 */
	 setbp ();
	 // rangerb
       c_171:			/* 171 */
	 // FMLB
       c_172:			/* 172 */
	 // FMRB
       c_173:			/* 173 */
	 addchar ('~');
	 addchar (class - 171 + 'A');
	 goto top;
	 // fmor
       c_168:			/* 168 */
	 rbase = (-(rbase));
	 // orrb
	 sstype = 0;
	 specmode = 0;
       c_147:			/* 147 */
	 searchbase = 0;
	 // recrb
	 &tag[this]->app = tmin;
	 &tag[this]->format = rbase;
	 goto top;
       c_45:			/* 45 */
	 if (x == 36)
	    addchar ('U');
	 goto top;
	 // sign
       c_46:			/* 46 */
	 addchar ('\\');
	 goto top;
	 // uop
       c_47:			/* 47 */
	 // MOD
       c_48:			/* 48 */
	 // DOT
       c_42:			/* 42 */
	 // OP1
       c_43:			/* 43 */
	 // OP2
       c_44:			/* 44 */
	 addchar (operator[x]);
	 goto top;
	 // op3
       c_56:			/* 56 */
	 // AND
       c_57:			/* 57 */
	 push (x);
	 goto top;
	 // or
       c_58:			/* 58 */
	 cnest[cp] = cnest[cp] ^ 2;
	 goto top;
	 // not
       c_138:			/* 138 */
	 x = 128 + 32 + 16 + 4;
	 // csep: treat like %while
       c_59:			/* 59 */
	 // WHILE
       c_60:			/* 60 */
	 if (class == 138)
	    op ('f', _label_ - 1);
	 else
	    deflab (_label_ - 1);
	 // until
       c_166:			/* 166 */
	 // RUNTIL
       c_62:			/* 62 */
	 lmode = (lmode & (else_ | loop)) | (x >> 3);
	 // cword
	 clab = _label_;
	 cp = 1;
	 cnest[1] = x & 7;
	 goto top;
       c_72:			/* 72 */
	 poplabel (0);
	 // repeat
	 if (lmode & 32 != 0)
	    deflab (_label_ + 1);
	 goto atop;
       c_69:			/* 69 */
	 poplabel (1);
	 goto top;
	 // finish
       c_163:			/* 163 */
	 // XELSE
       c_70:			/* 70 */
	 poplabel (1);
	 // finish else ...
	 if (lmode & 3 == 3)
	    fault (7);
	 // dangling else
       c_68:			/* 68 */
	 lmode = (lmode & else_) | 3;
	 // ...else...
	 if (access != 0) {
	    op ('F', _label_ - 1);
	    lmode = else_ | 3;
	 }
	 deflab (_label_);
	 if (next != 0)
	    goto top;
       c_120:			/* 120 */
	 // mstart
       c_67:			/* 67 */
	 // START
       c_71:			/* 71 */
	 // CYCLE
       stcy:
	 if (lmode == 0) {
	    deflab (_label_ - 1);
	    lmode = loop;
	 }			// cycle
	 dmin -= 1;
	 if (dmin <= dmax)
	    abandon (3);
	 dict[dmin] = lmode;
	 _label_ += 3;
	 return;
       c_64:			/* 64 */
	 if ((dict[dmin] >= 0 || inhibit != 0))
	    fault (13);
	 // on event
	 inhibit = 1;
	 n = 0;
	 if (pending == 0)
	    n = 0xFFFF;
	 // * = all events
	 while (pending > 0) {
	    poplit ();
	    if (lit & ((~(15))) != 0)
	       fault (10);
	    // too big
	    j = 1 << lit;
	    if (n & j != 0)
	       dubious = 1;
	    n = n | j;
	    // construct bit mask
	 }
	 op ('o', n);
	 op (',', _label_);
	 lmode = then | 1;
	 goto stcy;
       c_104:			/* 104 */
	 op ('J', &tag[x]->index);
	 // l
	 inhibit = 1;
	 goto atop;
       c_149:			/* 149 */
	 stats -= 1;
	 // lab
	 access = 1;
	 inhibit = 1;
	 op ('L', &tag[x]->index);
	 goto top;
       c_63:			/* 63 */
	 j = dmin;
	 l = _label_ - 3;
	 // exit, continue
	 for (;;) {
	    if (dict[j] < 0) {
	       fault (7);
	       goto top;
	    }
	    if (dict[j] & 1 == 0)
	       break;
	    j += 1;
	    l -= 3;
	 }
	 if (x == 32)
	    l += 1;
	 // continue
	 op ('F', l);
	 dict[j] = dict[j] | x;
	 // show given
	 goto atop;
       c_50:			/* 50 */
	 addchar ('C');
	 goto cop;
	 // acomp
       c_49:			/* 49 */
	 if (next != 0) {
	    // comparator
	    addchar ('"');
	    push (0);
	    // double sided
	 } else {
	    addchar ('?');
	 }
       cop:
	 if (cnest[cp] & 2 != 0)
	    x = x ^ 1;
	 // invert the condition
	 j = cp;
	 l = clab;
	 while (cnest[j] & 4 == 0) {
	    j -= 1;
	    l = l - cnest[j] & 1;
	 }
	 op (cc[x], l);
	 if (cnest[cp] & 1 != 0)
	    deflab (clab + 1);
	 cp -= 1;
	 clab = clab - cnest[cp] & 1;
	 goto top;
       c_78:			/* 78 */
	 // FRESULT
       c_79:			/* 79 */
	 // MRESULT
       c_80:			/* 80 */
	 open = 0;
	 // return, true, false
       c_82:			/* 82 */
	 access = 0;
	 // stop
       c_89:			/* 89 */
	 // ADDOP
       c_81:			/* 81 */
	 addchar (x);
	 goto top;
	 // monitor
       c_65:			/* 65 */
	 poplit ();
	 op ('e', lit);
	 goto atop;
	 // signal
       c_51:			/* 51 */
	 addchar ('S');
	 goto top;
	 // eq
       c_53:			/* 53 */
	 addchar ('j');
	 goto top;
	 // jam transfer
       c_52:			/* 52 */
	 addchar ('Z');
	 goto top;
	 // eqeq
       c_74:			/* 74 */
	 if (level == 0) {
	    // begin
	    if (progmode <= 0)
	       progmode = 1;
	    else
	       fault (7);
	    // {Permit BEGIN after external defs}
	 }
	 specmode = level + 1;
	 blockx = 0;
	 addchar ('H');
	 return;
       c_77:			/* 77 */
	 perm = 0;
	 lines = 0;
	 stats = 0;
	 // endofperm
	 closeinput ();
	 selectinput (source);
	 list -= 1;
	 tbase = tmax;
	 tstart = tmax;
	 return;
       c_76:			/* 76 */
	 if ((include != 0 && x == 0)) {
	    // end of ...
	    lines = include;
	    sstype = 0;
	    // include
	    closeinput ();
	    list = includelist;
	    includelevel = 0;
	    include = 0;
	    selectinput (source);
	    return;
	 }
	 ss = (-(1));
	 // prog/file
       c_75:			/* 75 */
	 compileend (x);
	 return;		// %end
       c_85:			/* 85 */
	 if (x == 0)
	    control = lit;
	 else {			// control
	    if (lit >> 14 & 3 == 1)
	       diag = lit & 0x3FFF;
	 }
	 op ('z' - x, lit);
	 goto top;
       c_83:			/* 83 */
	 list = list + x - 2;
	 goto top;
	 // %LIST/%endoflist
       c_84:			/* 84 */
	 realsln = x;
	 goto top;
	 // %REALS long/normal
       c_86:			/* 86 */
	 if (include != 0) {
	    // include "file"
	    fault (7);
	    return;
	 }
	 getnext ();
	 // sconst
	 x -= 0x4000;
	 j = glink (x);
	 k = j & 255;
	 // ABD - another little copy loop because SKIMP can't do the string map
	 strcpy (includefile, "");
	 for (;;) {
	    k -= 1;
	    if (k < 0)
	       break;
	    strcat (includefile, tostring (j >> 8));
	    x += 1;
	    j = glink (x);
	    k -= 1;
	    if (k < 0)
	       break;
	    strcat (includefile, tostring (j & 255));
	 }
	 // include file = string(x-16_4000+stbase)
	 // remove this event block for SKIMP or pre-event IMP versions
	 auto inline void block_1 (void)
	 {
	    auto inline void signal_event (int event, int subevent, int extra)
	    {
	       abandon (9);
	    }
	    openinput (3, includefile);
	 }
	 block_1 ();
	 include = lines;
	 lines = 0;
	 includelist = list;
	 includelevel = level;
	 selectinput (3);
	 goto top;
       c_154:			/* 154 */
	 dimension += 1;
	 // dbsep
	 if (dimension == dimlimit + 1)
	    fault (11);
	 goto top;
       c_145:			/* 145 */
	 setbp ();
	 goto top;
	 // crb
       c_146:			/* 146 */
	 setbp ();
	 // rcrb
       c_142:			/* 142 */
	 // BPLRB
	 if (dimension == 0)
	    dimension = 1;
	 op ('d', dimension);
	 op (',', defs);
	 if (class != 146) {
	    setsubs (defs);
	    if ((dict[dmin] >= 0 || (inhibit != 0 || level == 0)))
	       fault (13);
	 }
	 dimension = 0;
	 defs = 0;
	 goto top;
       c_128:			/* 128 */
	 id = dupid;
	 goto top;
	 // EDUP
       c_130:			/* 130 */
	 blockx = x;
	 if ((decl & spec == 0 && level != 0))
	    op ('F', 0);
	 // jump round proc
       c_125:			/* 125 */
	 dupid = id;
	 // %DUP
	 if (level < 0)
	    return;		// {spec about}
       c_90:			/* 90 */
	 def (x);
	 goto top;
	 // ident
       c_131:			/* 131 */
	 // CIDENT
	 if (&tag[x]->flags & (0b1111111 + constbit) == iform + constbit) {
	    &tag[x]->format = lit;
	 } else {
	    if (pending != 0)
	       setconst (lit);
	    def (x);
	    op ('A', 1);
	 }
	 cident = x;
	 goto top;
       c_124:			/* 124 */
	 if (&tag[cident]->flags & prot != 0)
	    dubious = 1;
	 // %DUBIOUS
	 goto top;
       c_97:			/* 97 */
	 // F
       c_98:			/* 98 */
	 // M
       c_99:			/* 99 */
	 // P
       c_96:			/* 96 */
	 call ();
	 goto top;
	 // r
       c_165:			/* 165 */
	 // NLAB
       c_100:			/* 100 */
	 // RP
       c_101:			/* 101 */
	 // FP
       c_102:			/* 102 */
	 // MP
       c_103:			/* 103 */
	 // PP
       c_91:			/* 91 */
	 // V
       c_92:			/* 92 */
	 // N
       c_106:			/* 106 */
	 // A
       c_107:			/* 107 */
	 // AN
       c_108:			/* 108 */
	 // NA
       c_109:			/* 109 */
	 // NAN
	 k = &tag[x]->index;
	 if (k < 0)
	    op ('n', (-(k)));
	 else
	    op ('@', k);
	 goto top;
       c_121:			/* 121 */
	 setconst (0);
	 goto top;
	 // special for zero
       c_167:			/* 167 */
	 addchar ('G');
	 goto pstr;
	 // aconst (alias)
       c__const_:		/* _const_ */
	 // CONST
	 if (x < 0) {
	    // constinteger
	    setconst (&tag[(-(x))]->format);
	    goto top;
	 }
	 if (x & 0x4000 != 0) {
	    // strings
	    addchar ('\\');
	  pstr:
	    x -= 0x4000;
	    j = glink (x);
	    k = j & 255;
	    addchar (k);
	    for (;;) {
	       k -= 1;
	       if (k < 0)
		  goto top;
	       addchar (j >> 8);
	       x += 1;
	       j = glink (x);
	       k -= 1;
	       if (k < 0)
		  goto top;
	       addchar (j & 255);
	    }
	 }
	 if (x & 0x2000 != 0) {
	    // real - ABD also string-like, but NOT packed
	    x -= 0x2000;
	    k = glink (x);
	    op ('D', k);
	    addchar (',');
	    for (;;) {
	       if (k == 0)
		  goto top;
	       k -= 1;
	       x += 1;
	       j = glink (x);
	       if (j == '@') {
		  op ('@', litpool[glink (x + 1)]);
		  goto top;
	       }
	       addchar (j);
	    }
	 }
	 setconst (litpool[x]);
	 goto top;
       c_137:			/* 137 */
	 addchar ('i');
	 goto top;
	 // asep
       c_141:			/* 141 */
	 addchar ('a');
	 goto top;
	 // arb
	 // own arrays
       c_132:			/* 132 */
	 ocount = ub - lb + 1;
	 def (x);
	 // oident
	 dimension = 1;
	 setsubs (1);
	 if (next == 0) {
	    // no initialisation
	    if (ocount > 0)
	       op ('A', ocount);
	    ocount = (-(1));
	 } else {
	    // initialisation given
	    getnext ();
	 }
	 goto top;
       c_162:			/* 162 */
	 lit = ocount;
	 goto ins;
	 // indef
       c_143:			/* 143 */
	 poplit ();
	 // orb
       ins:
	 if (lit < 0) {
	    fault (10);
	    lit = 0;
	 }
	 getnext ();
	 goto inst;
       c_139:			/* 139 */
	 // OSEP(X=19)
       c_153:			/* 153 */
	 lit = 1;
       inst:
	 if (pending != 0)
	    popdef ();
	 // ownt (x=0)
	 op ('A', lit);
	 ocount -= lit;
	 if (ocount >= 0) {
	    if (x != 0)
	       goto top;
	    // more coming
	    if (ocount == 0) {
	       ocount = (-(1));
	       return;
	    }			// all done
	 }
	 fault (11);
	 return;
       c_swit:			/* swit */
	 op ('W', &tag[x]->index);
	 inhibit = 1;
	 goto atop;
       c_134:			/* 134 */
	 def (x);
	 // swid
	 n = ub - lb + 1;
	 n = (n + 15) >> 4;
	 // slots needed (includes zero)
	 j = dmax;
	 dmax = dmax + n + 2;
	 if (dmax >= dmin)
	    abandon (1);
	 &tag[x]->format = j;
	 dict[j] = lb;
	 dict[j + 1] = ub;
	 for (;;) {
	    n -= 1;
	    if (n < 0)
	       goto top;
	    j += 1;
	    dict[j + 1] = 0;
	 }
       c_151:			/* 151 */
	 stats -= 1;
	 // slab
	 if (x < tbase) {
	    fault (7);
	    return;
	 }
	 if (pending != 0) {
	    // explicit label
	    defslab (pstack[1]);
	 } else {
	    if (&tag[x]->app != 0) {
	       fault (4);
	       return;
	    }
	    &tag[x]->app = 1;
	    n = &tag[x]->format;
	    for (j = dict[n]; j <= dict[n + 1]; j += 1) {
	       defslab (j);
	       flushbuffer (128);
	       // flush if bp >= 128
	    }
	 }
	 inhibit = 1;
	 return;
       c_140:			/* 140 */
	 addchar ('p');
	 goto top;
	 // psep
       c_144:			/* 144 */
	 // PRB
	 addchar ('p');
	 addchar ('E');
	 goto top;
	 // constant expressions
       c_155:			/* 155 */
	 // PCONST
	 if (x < 0)
	    lit = &tag[(-(x))]->format;
	 else
	    lit = litpool[x];
	 pending += 1;
	 pstack[pending] = lit;
	 goto top;
       c_156:			/* 156 */
	 lit = pstack[pending];
	 if (lit < 0)
	    lit = (-(lit));
	 pstack[pending] = lit;
	 goto top;
	 // cmod
       c_157:			/* 157 */
	 lit = (-(pstack[pending]));
	 pstack[pending] = lit;
	 goto top;
	 // csign
       c_158:			/* 158 */
	 lit = (~(pstack[pending]));
	 pstack[pending] = lit;
	 goto top;
	 // cuop
       c_159:			/* 159 */
	 // COP1
       c_160:			/* 160 */
	 // COP2
       c_161:			/* 161 */
	 pending -= 1;
	 // cop3
	 lit2 = pstack[pending + 1];
	 lit = pstack[pending];
	 goto *litop[x >> 2];
       litop_1:		/* 1 */
	 lit = lit << lit2;
	 goto setl;
       litop_2:		/* 2 */
	 lit = lit >> lit2;
	 goto setl;
       litop_3:		/* 3 */
	 n = 1;
	 // lit = lit\\lit2
	 if (lit2 < 0)
	    fault (10);
	 while (lit2 > 0) {
	    lit2 -= 1;
	    n = n * lit;
	 }
	 lit = n;
	 goto setl;
       litop_4:		/* 4 */
	 if (lit2 == 0)
	    fault (10);
	 else
	    lit = ((int) (lit) / (int) (lit2));
	 goto setl;
       litop_5:		/* 5 */
	 lit = lit & lit2;
	 goto setl;
       litop_6:		/* 6 */
	 lit = lit | lit2;
	 goto setl;
       litop_7:		/* 7 */
	 lit = lit ^ lit2;
	 goto setl;
       litop_8:		/* 8 */
	 lit += lit2;
	 goto setl;
       litop_9:		/* 9 */
	 lit -= lit2;
	 goto setl;
       litop_10:		/* 10 */
	 lit = lit * lit2;
	 goto setl;
       litop_11:		/* 11 */
	 lit += lit2;
	 goto setl;
       litop_12:		/* 12 */
	 n = 1;
	 // lit = lit\\lit2
	 if (lit2 < 0)
	    fault (10);
	 while (lit2 > 0) {
	    lit2 -= 1;
	    n = n * lit;
	 }
	 lit = n;
	 goto setl;
       setl:
	 pstack[pending] = lit;
	 goto top;
       c_170:			/* 170 */
	 // Fault(4) %if IMPCOM_Option # ""
	 // IMPCOM_Option = String(x-x'4000'+Stbase); ! Option string
	 goto top;
	 // string resolution
       c_135:			/* 135 */
	 resln = 2;
	 goto top;
	 // dotl
       c_136:			/* 136 */
	 resln += 1;
	 goto top;
	 // dotr
       c_55:			/* 55 */
	 op ('r', resln);
	 resln = 0;
	 goto top;
	 // resop
       c_164:			/* 164 */
	 op ('r', resln + 4);
	 resln = 0;
	 // cresop
       c_122:			/* 122 */
	 x = 6;
	 goto cop;
	 // %PRED
       c_87:			/* 87 */
	 setconst (pstack[1]);
	 // mass
	 {
	    bp += 1;
	    buff[bp] = 'P';
	 }
	 goto top;
      }
   }
   // of compile block
   auto inline void signal_event (int event, int subevent, int extra)
   {
      abandon (5);
   }
   selectinput (2);
   selectoutput (listing);
   &tag[maxtag] = 0;
   // %begin defn
   &tag[0] = 0;
   &tag[0]->flags = 7;
   // %begin tag!
   for (x = 0; x <= maxnames; x += 1)
      hash[x] = 0;
   printstring ("         Edinburgh IMP77 Compiler - Version ");
   // printstring(" Preston IMP2020 Compiler - Version ")
   printstring (version);
   newlines (2);
   op ('l', 0);
   compileblock (0, 0, maxdict, 0, 0);
   addchar (nl);
   // {for bouncing off}
   flushbuffer (0);
   // flush if bp >= 0
   x = listing;
   newline ();
   for (;;) {
      if (faulty == 0) {
	 write (stats, 5);
	 printstring (" Statements compiled");
      } else {
	 printstring (" Program contains ");
	 write (faulty, 1);
	 printstring (" fault");
	 if (!(faulty == 1))
	    printsymbol ('s');
      }
      newline ();
      if (x == report)
	 break;
      x = report;
      selectoutput (report);
   }
   if (faulty != 0)
      exit (0);			// try to flag to shell that we failed
}