{ Facilis 0.20                                      file: FACILIS.PAS    }
{$R+}
program Facilis;

 { based on the Pascal S compiler of Niklaus Wirth,
      as modified by R.E. Berry }

 { adapted for the IBMPC by John R. Naleszkiewicz }

 { extensions by Anthony M. Marcy }

const
  version = 0.20;
  nkw  =  35;     { no. of key words }
  alng =  10;     { no. of significant chars in identifiers }
  llng = 121;     { input line legnth }
  emax =  38;     { max exponent of real numbers }
  emin = -38;     { min exponent }
  kmax =  11;     { max no. of significant digits }
  tmax = 300;     { size of table }
  bmax =  30;     { size of block-table }
  amax =  30;     { size of array-table }
  c2max=  50;     { size of real constant table }
  csmax=  30;     { max no. of cases }
  cmax =8000;     { size of code }
  lmax =   7;     { maximum level }
  ermax=  61;     { max error no. }
  omax =  255;    { highest order code }
  xmax =  32767;  { maximum array bound }
  nmax =  32767;  { maximum integer }
  lineleng  =   80; {output line length }
  stacksize = 2000;

type
  symbol =
   (intcon,realcon,charcon,stringcon,
    notsy,plus,minus,times,idiv,rdiv,imod,andsy,orsy,insy,
    eql,neq,gtr,geq,lss,leq,
    lparent,rparent,lbrack,rbrack,comma,semicolon,period,twodots,
    colon,becomes,constsy,typesy,varsy,funcsy,nilsy,
    procsy,filesy,arraysy,recordsy,packedsy,setsy,programsy,labelsy,ident,
    withsy,beginsy,ifsy,casesy,repeatsy,whilesy,forsy,gotosy,
    endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,thensy);

  index  = -xmax..+xmax;
  alfa   = packed array [1..alng] of char;
  object = (konstant,vvariable,type1,prozedure,funktion);
  types  = (notyp,ints,reals,bools,chars,strngs,arrays,records);
  symset = set of symbol;
  typset = set of types;
  strng  = string[20];
  order  = packed record
             f: 0..omax;
             x: 0..lmax;
             y: -nmax..+nmax;
           end ;

var
  ch    : char;            { last character read from source program}
  rnum  : real;            { real number from insymbol }
  i,j   : integer;
  inum  : integer;         { integer from insymbol }
  sleng : integer;         { string length }
  cc    : integer;         { character counter }
  lc    : integer;         { program location counter }
  ll    : integer;         { length of current line }
  errpos: integer;
  nul   : integer;         { seg of null string }
  t,a,b,c1,c2: integer; { indices to tables}
  skipflag, stackdump, prtables   : boolean;

  sy      : symbol;        { last symbol read by insymbol }
  errs    : set of 0..ermax;
  id      : alfa;          { identifier from insymbol }
  progname: alfa;
  stantyps: typset;
  constbegsys,typebegsys,blockbegsys,facbegsys,statbegsys: symset;

  line       : array [1..llng] of char;
  key        : array [1..nkw] of alfa;
  ksy        : array [1..nkw] of symbol;
  sps        : array ['!'..'~'] of symbol;
  display    : array [0 .. lmax] of integer;

  tab:     array [0 .. tmax] of     { identifier table }
             record
               name: alfa;        link: index;
               obj : object;       typ: types;
               ref : index;     normal: boolean;
               lev : 0 .. lmax;    adr: integer
             end ;

  atab:    array [1 .. amax] of     { array-table }
             record
               inxtyp, eltyp: types;
               elref, low, high, elsize, size: index
             end ;

  btab:    array [1 .. bmax] of     { block-table }
             record
               last, lastpar, psize, vsize: index
             end ;

  spnt,tpnt: ^char;
  rconst:  array [1 .. c2max] of real;

  code  :  array [0 .. cmax] of order;
  opcode: byte;
       x: byte;      { operand }
       y: integer;   { operand }
      pc: integer;   { program counter }

  psin, psout, prr, prd: text;
  inf, outf, tempstr: strng;

procedure errormsg;

var    k: integer;
     msg: array [0..ermax] of alfa;
     begin
       msg[ 0] := 'undef id  '; msg[ 1] :='multi def ';
       msg[ 2] := 'identifier'; msg[ 3] :='program   ';
       msg[ 4] := ')         '; msg[ 5] :=':         ';
       msg[ 6] := 'syntax    '; msg[ 7] :='ident, var';
       msg[ 8] := 'of        '; msg[ 9] :='(         ';
       msg[10] := 'id, array '; msg[11] :='[         ';
       msg[12] := ']         '; msg[13] :='..        ';
       msg[14] := ';         '; msg[15] :='func. type';
       msg[16] := '=         '; msg[17] :='boolean   ';
       msg[18] := 'convar typ'; msg[19] :='type      ';
       msg[20] := 'prog.param'; msg[21] :='too big   ';
       msg[22] := '.         '; msg[23] :='typ (case)';
       msg[24] := 'character '; msg[25] :='const id  ';
       msg[26] := 'index type'; msg[27] :='indexbound';
       msg[28] := 'no array  '; msg[29] :='type id   ';
       msg[30] := 'undef type'; msg[31] :='no record ';
       msg[32] := 'boole type'; msg[33] :='arith type';
       msg[34] := 'integer   '; msg[35] :='types     ';
       msg[36] := 'param type'; msg[37] :='variab id ';
       msg[38] := 'string    '; msg[39] :='no.of pars';
       msg[40] := 'real numbr'; msg[41] :='type      ';
       msg[42] := 'real type '; msg[43] :='integer   ';
       msg[44] := 'var, const'; msg[45] :='var, proc ';
       msg[46] := 'types (:=)'; msg[47] :='typ (case)';
       msg[48] := 'type      '; msg[49] :='store ovfl';
       msg[50] := 'constant  '; msg[51] :=':=        ';
       msg[52] := 'then      '; msg[53] :='until     ';
       msg[54] := 'do        '; msg[55] :='to downto ';
       msg[56] := 'begin     '; msg[57] :='end       ';
       msg[58] := 'factor    '; msg[59] :='comma     ';
       msg[60] := 'idx string'; msg[61] :='too big   ';

       writeln(psout); writeln(psout,' key words');
       k:=0;
       while errs <> [] do begin
         while not (k in errs) do k := k+1;
         writeln(psout,k,'  ',msg[k]);
         errs := errs - [k]
       end
     end { errormsg } ;

procedure fatal(n: integer);

var    msg: array [1..8] of alfa;
begin
  writeln(psout); errormsg;

  msg[ 1] := 'identifier'; msg[ 2] := 'procedures';
  msg[ 3] := 'reals     '; msg[ 4] := 'arrays    ';
  msg[ 5] := 'levels    '; msg[ 6] := 'code      ';
  msg[ 7] := 'strings   '; msg[ 8] := 'input line';

  writeln(psout,' compiler table for ', msg[n], ' is too small');
  close(psout); halt       {terminate compilation}
end { fatal } ;

function stupcase(st: strng): strng;

var i: integer;

begin
  for i := 1 to length(st) do
    st[i] := upcase(st[i]);
  stupcase := st
end;  { stupcase }

procedure endskip;

begin                { underline skipped part of input }
  while errpos < cc do
  begin
    write(psout,'-'); errpos := errpos + 1
  end ;
  skipflag := false
end { endskip } ;

procedure nextch;   { read next character; process line end }

begin
  if cc = ll
  then begin
    if eof(psin)
    then begin
      writeln(psout);
      writeln(psout,' program incomplete');
      errormsg;
      close(psout); halt;     { abort }
    end ;
    if errpos <> 0
    then begin
      if skipflag then endskip;
      writeln(psout);
      errpos := 0
    end ;
    write(psout,lc:5, '  ');
    ll := 0; cc := 0;
    while not eoln(psin) do
    begin
      if ll > llng-2 then fatal(8);
      read(psin,ch);
      if ch <> chr(10) then begin
        if ord(ch) < 32 then ch := ' ';
        write(psout,ch);
        ll := ll+1;
        line[ll] := ch
      end
    end ;
    ll := ll+1; line[ll] := ' ';
    read(psin,ch); writeln(psout);
  end ;
  cc := cc+1; ch := line[cc];
end { nextch } ;

procedure error(n: integer);

begin
  if errpos = 0 then write(psout,' ****');
  if cc > errpos
  then begin
    write(psout,' ': cc-errpos, '^', n:2);
    errpos := cc+3; errs := errs + [n]
  end
end { error } ;

procedure insymbol;           { reads next symbol }

const dotdot = #31;
label  1,2,3 ;
var    i,j,k,e: integer;
       sbuff: string[132];

  procedure readscale;

  var    s, sign: integer;
  begin
    nextch;
    sign := 1; s := 0;
    if ch = '+'
    then nextch
    else if ch = '-'
         then begin
           nextch; sign := -1
         end ;
    if not ((ch>='0') and (ch<='9'))
    then error(40)
    else repeat
           s := 10*s + ord(ch)-ord('0');
           nextch
         until not ((ch>='0') and (ch<='9'));
    e := s*sign + e
  end { readscale } ;

  procedure adjustscale;

  var    s  : integer;
         d,t: real;
  begin
  if k+e > emax
  then error(21)
  else if k+e < emin
       then rnum := 0
       else begin
         s := abs(e); t := 1.0; d := 10.0;
         repeat
           while not odd(s) do
           begin
             s := s div 2; d := sqr(d)
           end ;
           s := s-1; t := d*t
         until s = 0;

         if e >= 0
         then rnum := rnum*t
         else rnum := rnum/t
       end
  end { adjustscale } ;

procedure options;

  procedure switch(var b: boolean);

  begin
    b:=ch='+';
    if not b
    then if not (ch='-')
         then  begin
           error(6);
           while (ch<>'*') and (ch<>',') and (ch<>'}') do nextch;
         end
         else nextch
    else nextch
  end { switch } ;

  begin      {options}
    repeat
      nextch;
      if (ch <> '*') and (ch <> '}')
      then begin
        if ((ch='t') or (ch='T'))
        then begin
          nextch; switch(prtables)
        end else if ((ch='s') or (ch='S'))
                 then begin
                   nextch; switch(stackdump)
                 end
      end
    until ch<>','
  end  { options } ;

begin    { insymbol }

1: while ch = ' ' do nextch;

  if ch in ['a'..'z','A'..'Z']
  then begin { identifier or wordsymbol }
      k := 0; id := '          ';
      if ch in ['A'..'Z'] then ch := chr(ord(ch)+32);
      repeat
        if k < alng
        then begin
          k := k+1; id[k] := ch
        end ;
        nextch;
        if ch in ['A'..'Z'] then ch := chr(ord(ch)+32)
      until not ( (ch in ['a'..'z']) or (ch in ['0'..'9'])
                  or (ch='_') );
      i := 1; j:= nkw;    { binary search }
      repeat
        k := (i+j) div 2;
        if id <= key[k] then j := k-1;
        if id >= key[k] then i := k+1
      until i > j;
      if i-1 > j then sy := ksy[k] else sy := ident
    end

  else if ch in ['+','-','*','/',')','=',',','[',']',';','&','|','~']
  then begin
      sy := sps[ch]; nextch
    end

  else if ch in ['0'..'9']
  then begin { number }
      k := 0; inum := 0; sy := intcon;
      repeat
        inum := inum*10 + ord(ch) - ord('0');
        k := k+1;
        nextch
      until not ((ch>='0') and (ch<='9'));

      if (k > kmax) or (inum > nmax)
      then begin
        error(21); inum := 0; k := 0
      end ;
      if ch = '.'
      then begin
        nextch;
        if ch = '.'
        then ch := dotdot
        else begin
          sy := realcon; rnum := inum; e := 0;
          while (ch>='0') and (ch<='9') do
          begin
            e := e-1;
            rnum := 10.0*rnum + (ord(ch)-ord('0'));
            nextch
          end ;
          if e = 0 then error(40);
          if ((ch = 'e') or (ch = 'E')) then readscale;
          if e <> 0 then adjustscale
        end
      end else
        if ((ch = 'e') or (ch = 'E'))
        then begin
          sy := realcon; rnum := inum; e := 0;
          readscale;
          if e <> 0 then adjustscale
        end ;
    end

  else case ch of

':' :
    begin
      nextch;
      if ch = '='
      then begin
        sy := becomes; nextch
      end  else sy := colon
    end;

'<' :
    begin
      nextch;
      if ch = '='
      then begin
        sy := leq; nextch
      end else
        if ch = '>'
        then begin
          sy := neq; nextch
        end else sy := lss
    end;

'>' :
    begin
      nextch;
      if ch = '='
      then begin
        sy := geq; nextch
      end else sy := gtr
    end;

'.' :
    begin
      nextch;
      if ch = '.'
      then begin
        sy := twodots; nextch
      end else sy := period
    end;

dotdot:
    begin
      sy := twodots; nextch
    end;

'''' :
    begin
      sbuff := '';
 2:   nextch;
      if ch = ''''
      then  begin
        nextch;
        if ch <> '''' then goto 3
      end ;
      if length(sbuff) < 132
      then sbuff := sbuff + ch
      else error(38);
      if cc = 1
      then error(38)  { end of line }
      else goto 2;

 3:   if length(sbuff) = 1
      then begin
        sy := charcon; inum := ord(sbuff[1])
      end else begin
        sy := stringcon;
        sleng := length(sbuff);
        if sleng=0
        then spnt := ptr(nul,0)
        else begin
          getmem(spnt,((sleng+3) div 16 +1)*16);
          k := seg(spnt^);
          memw[k:0] := sleng;
          memw[k:2] := 0;
          move(sbuff[1],mem[k:4],sleng);
        end;
      end
    end;

'(' :
    begin
      nextch;
      if ch <> '*'
      then sy := lparent
      else begin { comment }
        nextch;
        if ch='$' then options;
        repeat
          while ch <>  '*' do nextch;
          nextch
        until ch = ')';
        nextch; goto 1
      end
    end;

'{' :
    begin { comment }
      nextch;
      if ch='$' then options;
      while ch <> '}' do nextch;
      nextch; goto 1
    end;

  else nextch; error(24); goto 1

  end {case}
end {insymbol } ;

procedure enter(x0: alfa;  x1: object;
                x2: types; x3: integer);

begin
  t := t+1;         { enter standard identifier }
  with tab[t] do
  begin
    name := x0; link := t-1; obj := x1;
    typ := x2; ref := 0; normal := true;
    lev := 0; adr := x3
  end
end { enter } ;

procedure enterarray(tp: types; l,h: integer);

begin
  if l > h then error(27);
  if (abs(l)>xmax) or (abs(h)>xmax)
  then begin
    error(27); l := 0; h := 0;
  end ;
  if a = amax
  then fatal(4)
  else begin
    a := a+1;
    with atab[a] do
    begin
      inxtyp := tp; low := l; high := h
    end
  end
end {enterarray } ;

procedure enterblock;

begin
  if b = bmax
  then fatal(2)
  else begin
    b := b+1; btab[b].last := 0; btab[b].lastpar := 0
  end
end { enterblock } ;

procedure enterreal(x: real);

begin
  if c2 = c2max-1
  then fatal(3)
  else begin
    rconst[c2+1] := x; c1 := 1;
    while rconst[c1] <> x do c1 := c1+1;
    if c1 > c2 then c2 := c1
  end
end { enterreal } ;

procedure emit(fct: integer);

begin
  if lc = cmax then fatal(6);
  code[lc].f := fct; lc := lc+1
end { emit } ;

procedure emit1(fct,b: integer);

begin
  if lc = cmax then fatal(6);
  with code[lc] do
  begin
    f := fct; y := b
  end ;
  lc := lc+1
end { emit1 } ;

procedure emit2(fct,a,b: integer);

begin
  if lc = cmax then fatal(6);
  with code[lc] do
  begin
    f := fct; x := a; y := b
  end ;
  lc := lc+1
end { emit2 } ;

procedure printtables;

var    i:integer;
       o: order;

begin
  writeln(psout); writeln(psout); writeln(psout);
  writeln(psout,'   identifiers link  obj  typ  ref  nrm  lev  adr');
  writeln(psout);
  for i := btab[1].last to t do
    with tab[i] do
      writeln(psout,i,' ',name,link:5, ord(obj):5, ord(typ):5, ref:5,
              ord(normal):5, lev:5, adr:5);

  writeln(psout); writeln(psout); writeln(psout);
  writeln(psout,'blocks    last lpar psze vsze');
  writeln(psout);
  for i := 1 to b do
    with btab[i] do
      writeln(psout,i:4, last:9, lastpar:5, psize:5, vsize:5);

  writeln(psout); writeln(psout); writeln(psout);
  writeln(psout,'arrays    xtyp etyp eref  low high elsz size');
  writeln(psout);

  for i := 1 to a do
    with atab[i] do
      writeln(psout,i:4, ord(inxtyp):9, ord(eltyp):5,
              elref:5, low:5, high:5, elsize:5, size:5);

  writeln(psout); writeln(psout); writeln(psout);
  writeln(psout,' code:'); writeln(psout);

  for i:=0 to lc-1 do
  begin
    write(psout); write(psout,i:5);
    o := code[i]; write(psout,o.f:5);
    if o.f < 100
    then if o.f<4
         then write(psout,o.x:2, o.y:5)
         else write(psout,o.y:7)
    else write(psout,'       ');
    writeln(psout,',')
  end;
  writeln(psout);
  writeln(psout,'Starting address is ',tab[btab[1].last].adr:5)

end { printtables };

procedure block(fsys: symset; isfun: boolean; level: integer); forward;

{$I BLOCK.PAS }

{$I INTERPRT.PAS }

procedure block;

begin
  blockov(fsys,isfun,level)
end;

procedure setup;

begin
  key[ 1] := 'and       '; key[ 2] := 'array     ';
  key[ 3] := 'begin     '; key[ 4] := 'case      ';
  key[ 5] := 'const     '; key[ 6] := 'div       ';
  key[ 7] := 'do        '; key[ 8] := 'downto    ';
  key[ 9] := 'else      '; key[10] := 'end       ';
  key[11] := 'file      '; key[12] := 'for       ';
  key[13] := 'function  '; key[14] := 'goto      ';
  key[15] := 'if        '; key[16] := 'in        ';
  key[17] := 'label     '; key[18] := 'mod       ';
  key[19] := 'nil       '; key[20] := 'not       ';
  key[21] := 'of        '; key[22] := 'or        ';
  key[23] := 'packed    '; key[24] := 'procedure ';
  key[25] := 'program   '; key[26] := 'record    ';
  key[27] := 'repeat    '; key[28] := 'set       ';
  key[29] := 'then      '; key[30] := 'to        ';
  key[31] := 'type      '; key[32] := 'until     ';
  key[33] := 'var       '; key[34] := 'while     ';
  key[35] := 'with      ';
  ksy[ 1] := andsy;        ksy[ 2] := arraysy;
  ksy[ 3] := beginsy;      ksy[ 4] := casesy;
  ksy[ 5] := constsy;      ksy[ 6] := idiv;
  ksy[ 7] := dosy;         ksy[ 8] := downtosy;
  ksy[ 9] := elsesy;       ksy[10] := endsy;
  ksy[11] := filesy;       ksy[12] := forsy;
  ksy[13] := funcsy;       ksy[14] := gotosy;
  ksy[15] := ifsy;         ksy[16] := insy;
  ksy[17] := labelsy;      ksy[18] := imod;
  ksy[19] := nilsy;        ksy[20] := notsy;
  ksy[21] := ofsy;         ksy[22] := orsy;
  ksy[23] := packedsy;     ksy[24] := procsy;
  ksy[25] := programsy;    ksy[26] := recordsy;
  ksy[27] := repeatsy;     ksy[28] := setsy;
  ksy[29] := thensy;       ksy[30] := tosy;
  ksy[31] := typesy;       ksy[32] := untilsy;
  ksy[33] := varsy;        ksy[34] := whilesy;
  ksy[35] := withsy;

  sps['+'] := plus;        sps['-'] := minus;
  sps['*'] := times;       sps['/'] := rdiv;
  sps[')'] := rparent;
  sps['='] := eql;         sps[','] := comma;
  sps['['] := lbrack;      sps[']'] := rbrack;
  sps['~'] := notsy;       sps['&'] := andsy;
  sps[';'] := semicolon;   sps['|'] := orsy;
end { setup } ;

procedure enterids;

begin
  enter('          ', vvariable, notyp, 0);  { sentinel }
  enter('false     ', konstant, bools, 0);
  enter('true      ', konstant, bools, 1);
  enter('real      ', type1, reals, 1);
  enter('char      ', type1, chars, 1);
  enter('boolean   ', type1, bools, 1);
  enter('integer   ', type1, ints , 1);
  enter('string    ', type1, strngs,1);
  enter('abs       ', funktion, reals,0);
  enter('sqr       ', funktion, reals,2);
  enter('odd       ', funktion, bools,4);
  enter('chr       ', funktion, chars,5);
  enter('ord       ', funktion, ints, 6);
  enter('succ      ', funktion, chars,7);
  enter('pred      ', funktion, chars,8);
  enter('round     ', funktion, ints, 9);
  enter('trunc     ', funktion, ints, 10);
  enter('sin       ', funktion, reals, 11);
  enter('cos       ', funktion, reals, 12);
  enter('exp       ', funktion, reals, 13);
  enter('ln        ', funktion, reals, 14);
  enter('sqrt      ', funktion, reals, 15);
  enter('arctan    ', funktion, reals, 16);
  enter('eof       ', funktion, bools, 17);
  enter('eoln      ', funktion, bools, 18);
  enter('maxavail  ', funktion, ints, 19);
  enter('length    ', funktion, ints, 20);
  enter('copy      ', funktion, strngs, 23);
  enter('pos       ', funktion, ints, 26);
  enter('str       ', funktion, strngs, 33);
  enter('val       ', funktion, ints, 35);
  enter('rval      ', funktion, reals, 37);
  enter('read      ', prozedure, notyp, 1);
  enter('readln    ', prozedure, notyp, 2);
  enter('write     ', prozedure, notyp, 3);
  enter('writeln   ', prozedure, notyp, 4);
  enter('          ', prozedure, notyp, 0);
end;  { enterids }

procedure startup;

var
  exists: boolean;

begin
  writeln('                    Facilis   version ', version:4:2);
  writeln;
  repeat
    write('  Source input file [.PAS] ? '); readln(inf);
    inf := stupcase(inf);
    if pos('.',inf) = 0
      then inf := inf + '.PAS';
    assign(psin,inf);
    {$I-} reset(psin) {$I+} ;
    exists := (ioresult = 0);
    if not exists
      then writeln('File ', inf, ' not found');
  until exists;

  tempstr := copy(inf,1,pos('.',inf)) + 'LST';
  repeat
    repeat
      write('Source listing file [',tempstr,'] ? ');
      readln(outf); outf := stupcase(outf);
    until inf <> outf;
    if outf = ''
      then outf := tempstr;
    assign(psout,outf);
    {$I-} rewrite(psout) {$I+} ;
    exists := (ioresult = 0);
    if not exists
      then writeln('can''t open file ',outf);
  until exists;
end;  { startup }

begin { main }

  setup;

  constbegsys := [plus,minus,intcon,realcon,charcon,stringcon,ident];
  typebegsys  := [ident,arraysy,recordsy];
  blockbegsys := [constsy,typesy,varsy,procsy,funcsy,beginsy];
  facbegsys   := [intcon,realcon,charcon,stringcon,ident,lparent,notsy];
  statbegsys  := [beginsy,ifsy,whilesy,repeatsy,forsy,casesy];
  stantyps    := [notyp,ints,reals,bools,chars,strngs];

      lc := 0;             ll := 0;
      cc := 0;             ch := ' ';
  errpos := 0;           errs := [];

  writeln;
  startup;

  assign(prd,'trm:');
  reset(prd);
  assign(prr,'con:');
  rewrite(prr);

         t := -1;                 a := 0;
         b :=  1;
        c2 :=  0;        display[0] := 1;
  skipflag := false;        prtables:= false;
  stackdump:= false;

  getmem(spnt,16);
  if ofs(spnt^) <> 0 then begin
    freemem(spnt,16); getmem(spnt,8);
    getmem(spnt,16); end;
  nul := seg(spnt^);
  memw[nul:0] := 0; memw[nul:2] := 0;

  insymbol;
  if sy <> programsy
  then error(3)
  else begin
    insymbol;
    if sy <> ident
    then error(2)
    else begin
      progname := id;
      insymbol;
      if sy = lparent
      then begin
        repeat
          insymbol;
          if sy<> ident
          then error(2)
          else insymbol
        until sy <> comma;
        if sy = rparent then insymbol else error(4);
      end
    end
  end ;

  enterids;
  with btab[1] do
    begin
      last := t; lastpar := 1; psize := 0; vsize := 0;
    end ;

  block(blockbegsys+statbegsys, false, 1);
  if sy <> period then error(22);
  emit(131);  { halt }

  if prtables then printtables;
  if errs=[]
  then interpret
  else begin
    writeln(psout);
    writeln(psout,'compiled with errors');
    writeln(psout);
    errormsg;
  end;

  writeln(psout);

  close(psout);
  close(prr)

end.                     