home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume23 / pascal / part01 / pcom.p < prev    next >
Encoding:
Text File  |  1991-09-27  |  44.8 KB  |  1,588 lines

  1. (*$c+,t-,d-,l-*)
  2.  (***********************************************
  3.   *                        *
  4.   *     Portable Pascal compiler        *
  5.   *     ************************        *
  6.   *                        *
  7.   *        Pascal P4            *
  8.   *                        *
  9.   *     Authors:                *
  10.   *          Urs Ammann            *
  11.   *          Kesav Nori            *
  12.   *          Christian Jacobi            *
  13.   *     Address:                *
  14.   *      Institut Fuer Informatik        *
  15.   *      Eidg. Technische Hochschule        *
  16.   *      CH-8096 Zuerich            *
  17.   *                        *
  18.   *  This code is fully documented in the book    *
  19.   *       "Pascal Implementation"        *
  20.   *   by Steven Pemberton and Martin Daniels    *
  21.   * published by Ellis Horwood, Chichester, UK    *
  22.   *       (also available in Japanese)        *
  23.   *                        *
  24.   * Steven Pemberton, CWI/AA,            *
  25.   * Kruislaan 413, 1098 SJ Amsterdam, NL    *
  26.   * steven@cwi.nl                *
  27.   *                        *
  28.   *                        *
  29.   ***********************************************)
  30.  
  31. program pascalcompiler(input,output,prr);
  32.  
  33. const displimit = 20; maxlevel = 10;
  34.    intsize     =      1;
  35.    intal       =      1;
  36.    realsize    =      1;
  37.    realal      =      1;
  38.    charsize    =      1;
  39.    charal      =      1;
  40.    charmax     =      1;
  41.    boolsize    =      1;
  42.    boolal      =      1;
  43.    ptrsize     =      1;
  44.    adral       =      1;
  45.    setsize     =      1;
  46.    setal       =      1;
  47.    stackal     =      1;
  48.    stackelsize =      1;
  49.    strglgth    =     16;
  50.    sethigh     =     47;
  51.    setlow      =      0;
  52.    ordmaxchar  =     63;
  53.    ordminchar  =      0;
  54.    maxint      =  32767;
  55.    lcaftermarkstack = 5;
  56.    fileal      = charal;
  57.    (* stackelsize = minimum size for 1 stackelement
  58.           = k*stackal
  59.       stackal     = scm(all other al-constants)
  60.       charmax     = scm(charsize,charal)
  61.             scm = smallest common multiple
  62.       lcaftermarkstack >= 4*ptrsize+max(x-size)
  63.             = k1*stackelsize      *)
  64.    maxstack   =       1;
  65.    parmal     = stackal;
  66.    parmsize   = stackelsize;
  67.    recal      = stackal;
  68.    filebuffer =       4;
  69.    maxaddr    =  maxint;
  70.  
  71.  
  72.  
  73. type                            (*describing:*)
  74.                                 (*************)
  75.  
  76.      marktype= ^integer;
  77.                                 (*basic symbols*)
  78.                                 (***************)
  79.  
  80.      symbol = (ident,intconst,realconst,stringconst,notsy,mulop,addop,relop,
  81.            lparent,rparent,lbrack,rbrack,comma,semicolon,period,arrow,
  82.            colon,becomes,labelsy,constsy,typesy,varsy,funcsy,progsy,
  83.            procsy,setsy,packedsy,arraysy,recordsy,filesy,forwardsy,
  84.            beginsy,ifsy,casesy,repeatsy,whilesy,forsy,withsy,
  85.            gotosy,endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,
  86.            thensy,othersy);
  87.      operator = (mul,rdiv,andop,idiv,imod,plus,minus,orop,ltop,leop,geop,gtop,
  88.          neop,eqop,inop,noop);
  89.      setofsys = set of symbol;
  90.      chtp = (letter,number,special,illegal,
  91.          chstrquo,chcolon,chperiod,chlt,chgt,chlparen,chspace);
  92.  
  93.                                 (*constants*)
  94.                                 (***********)
  95.      setty = set of setlow..sethigh;
  96.      cstclass = (reel,pset,strg);
  97.      csp = ^ constant;
  98.      constant = record case cclass: cstclass of
  99.              reel: (rval: packed array [1..strglgth] of char);
  100.              pset: (pval: setty);
  101.              strg: (slgth: 0..strglgth;
  102.                 sval: packed array [1..strglgth] of char)
  103.                end;
  104.  
  105.      valu = record case intval: boolean of  (*intval never set nor tested*)
  106.              true:  (ival: integer);
  107.              false: (valp: csp)
  108.            end;
  109.  
  110.                                (*data structures*)
  111.                                (*****************)
  112.      levrange = 0..maxlevel; addrrange = 0..maxaddr;
  113.      structform = (scalar,subrange,pointer,power,arrays,records,files,
  114.            tagfld,variant);
  115.      declkind = (standard,declared);
  116.      stp = ^ structure; ctp = ^ identifier;
  117.  
  118.      structure = packed record
  119.            marked: boolean;   (*for test phase only*)
  120.            size: addrrange;
  121.            case form: structform of
  122.              scalar:   (case scalkind: declkind of
  123.                   declared: (fconst: ctp); standard: ());
  124.              subrange: (rangetype: stp; min,max: valu);
  125.              pointer:  (eltype: stp);
  126.              power:    (elset: stp);
  127.              arrays:   (aeltype,inxtype: stp);
  128.              records:  (fstfld: ctp; recvar: stp);
  129.              files:    (filtype: stp);
  130.              tagfld:   (tagfieldp: ctp; fstvar: stp);
  131.              variant:  (nxtvar,subvar: stp; varval: valu)
  132.            end;
  133.  
  134.                                 (*names*)
  135.                                 (*******)
  136.  
  137.      idclass = (types,konst,vars,field,proc,func);
  138.      setofids = set of idclass;
  139.      idkind = (actual,formal);
  140.      alpha = packed array [1..8] of char;
  141.  
  142.      identifier = packed record
  143.            name: alpha; llink, rlink: ctp;
  144.            idtype: stp; next: ctp;
  145.            case klass: idclass of
  146.              types: ();
  147.              konst: (values: valu);
  148.              vars:  (vkind: idkind; vlev: levrange; vaddr: addrrange);
  149.              field: (fldaddr: addrrange);
  150.              proc, func:  (case pfdeckind: declkind of
  151.                   standard: (key: 1..15);
  152.                   declared: (pflev: levrange; pfname: integer;
  153.                       case pfkind: idkind of
  154.                        actual: (forwdecl, extern: boolean);
  155.                        formal: ()))
  156.            end;
  157.  
  158.  
  159.      disprange = 0..displimit;
  160.      where = (blck,crec,vrec,rec);
  161.  
  162.                                 (*expressions*)
  163.                                 (*************)
  164.      attrkind = (cst,varbl,expr);
  165.      vaccess = (drct,indrct,inxd);
  166.  
  167.      attr = record typtr: stp;
  168.           case kind: attrkind of
  169.         cst:   (cval: valu);
  170.         varbl: (case access: vaccess of
  171.               drct: (vlevel: levrange; dplmt: addrrange);
  172.               indrct: (idplmt: addrrange))
  173.           end;
  174.  
  175.      testp = ^ testpointer;
  176.      testpointer = packed record
  177.              elt1,elt2 : stp;
  178.              lasttestp : testp
  179.            end;
  180.  
  181.                                  (*labels*)
  182.                                  (********)
  183.      lbp = ^ labl;
  184.      labl = record nextlab: lbp; defined: boolean;
  185.            labval, labname: integer
  186.         end;
  187.  
  188.      extfilep = ^filerec;
  189.      filerec = record filename:alpha; nextfile:extfilep end;
  190.  
  191. (*-------------------------------------------------------------------------*)
  192.  
  193. var
  194. (*    prr: text; (* comment this out when compiling with pcom *)
  195.                     (*returned by source program scanner
  196.                      insymbol:
  197.                      **********)
  198.  
  199.     sy: symbol;             (*last symbol*)
  200.     op: operator;           (*classification of last symbol*)
  201.     val: valu;              (*value of last constant*)
  202.     lgth: integer;          (*length of last string constant*)
  203.     id: alpha;              (*last identifier (possibly truncated)*)
  204.     kk: 1..8;               (*nr of chars in last identifier*)
  205.     ch: char;               (*last character*)
  206.     eol: boolean;           (*end of line flag*)
  207.  
  208.  
  209.                     (*counters:*)
  210.                     (***********)
  211.  
  212.     chcnt: integer;         (*character counter*)
  213.     lc,ic: addrrange;           (*data location and instruction counter*)
  214.     linecount: integer;
  215.  
  216.  
  217.                     (*switches:*)
  218.                     (***********)
  219.  
  220.     dp,                 (*declaration part*)
  221.     prterr,             (*to allow forward references in pointer type
  222.                       declaration by suppressing error message*)
  223.     list,prcode,prtables: boolean;  (*output options for
  224.                     -- source program listing
  225.                     -- printing symbolic code
  226.                     -- displaying ident and struct tables
  227.                     --> procedure option*)
  228.     debug: boolean;
  229.  
  230.  
  231.                     (*pointers:*)
  232.                     (***********)
  233.     parmptr,
  234.     intptr,realptr,charptr,
  235.     boolptr,nilptr,textptr: stp;    (*pointers to entries of standard ids*)
  236.     utypptr,ucstptr,uvarptr,
  237.     ufldptr,uprcptr,ufctptr,    (*pointers to entries for undeclared ids*)
  238.     fwptr: ctp;             (*head of chain of forw decl type ids*)
  239.     fextfilep: extfilep;        (*head of chain of external files*)
  240.     globtestp: testp;           (*last testpointer*)
  241.  
  242.  
  243.                     (*bookkeeping of declaration levels:*)
  244.                     (************************************)
  245.  
  246.     level: levrange;        (*current static level*)
  247.     disx,               (*level of last id searched by searchid*)
  248.     top: disprange;         (*top of display*)
  249.  
  250.     display:            (*where:   means:*)
  251.       array [disprange] of
  252.     packed record           (*=blck:   id is variable id*)
  253.       fname: ctp; flabel: lbp;  (*=crec:   id is field id in record with*)
  254.       case occur: where of      (*     constant address*)
  255.         crec: (clev: levrange;  (*=vrec:   id is field id in record with*)
  256.           cdspl: addrrange);(*     variable address*)
  257.         vrec: (vdspl: addrrange)
  258.       end;              (* --> procedure withstatement*)
  259.  
  260.  
  261.                     (*error messages:*)
  262.                     (*****************)
  263.  
  264.     errinx: 0..10;          (*nr of errors in current source line*)
  265.     errlist:
  266.       array [1..10] of
  267.     packed record pos: integer;
  268.               nmr: 1..400
  269.            end;
  270.  
  271.  
  272.  
  273.                     (*expression compilation:*)
  274.                     (*************************)
  275.  
  276.     gattr: attr;            (*describes the expr currently compiled*)
  277.  
  278.  
  279.                     (*structured constants:*)
  280.                     (***********************)
  281.  
  282.     constbegsys,simptypebegsys,typebegsys,blockbegsys,selectsys,facbegsys,
  283.     statbegsys,typedels: setofsys;
  284.     chartp : array[char] of chtp;
  285.     rw:  array [1..35(*nr. of res. words*)] of alpha;
  286.     frw: array [1..9] of 1..36(*nr. of res. words + 1*);
  287.     rsy: array [1..35(*nr. of res. words*)] of symbol;
  288.     ssy: array [char] of symbol;
  289.     rop: array [1..35(*nr. of res. words*)] of operator;
  290.     sop: array [char] of operator;
  291.     na:  array [1..35] of alpha;
  292.     mn:  array [0..60] of packed array [1..4] of char;
  293.     sna: array [1..23] of packed array [1..4] of char;
  294.     cdx: array [0..60] of -4..+4;
  295.     pdx: array [1..23] of -7..+7;
  296.     ordint: array [char] of integer;
  297.  
  298.     intlabel,mxint10,digmax: integer;
  299. (*-------------------------------------------------------------------------*)
  300.   procedure mark(var p: marktype); begin end;
  301.   procedure release(p: marktype); begin end;
  302.  
  303.   procedure endofline;
  304.     var lastpos,freepos,currpos,currnmr,f,k: integer;
  305.   begin
  306.     if errinx > 0 then   (*output error messages*)
  307.       begin write(output,linecount:6,' ****  ':9);
  308.     lastpos := 0; freepos := 1;
  309.     for k := 1 to errinx do
  310.       begin
  311.         with errlist[k] do
  312.           begin currpos := pos; currnmr := nmr end;
  313.         if currpos = lastpos then write(output,',')
  314.         else
  315.           begin
  316.         while freepos < currpos do
  317.           begin write(output,' '); freepos := freepos + 1 end;
  318.         write(output,'^');
  319.         lastpos := currpos
  320.           end;
  321.         if currnmr < 10 then f := 1
  322.         else if currnmr < 100 then f := 2
  323.           else f := 3;
  324.         write(output,currnmr:f);
  325.         freepos := freepos + f + 1
  326.       end;
  327.     writeln(output); errinx := 0
  328.       end;
  329.     linecount := linecount + 1;
  330.     if list and (not eof(input)) then
  331.       begin write(output,linecount:6,'  ':2);
  332.     if dp then write(output,lc:7) else write(output,ic:7);
  333.     write(output,' ')
  334.       end;
  335.     chcnt := 0
  336.   end  (*endofline*) ;
  337.  
  338.   procedure error(ferrnr: integer);
  339.   begin
  340.     if errinx >= 9 then
  341.       begin errlist[10].nmr := 255; errinx := 10 end
  342.     else
  343.       begin errinx := errinx + 1;
  344.     errlist[errinx].nmr := ferrnr
  345.       end;
  346.     errlist[errinx].pos := chcnt
  347.   end (*error*) ;
  348.  
  349.   procedure insymbol;
  350.     (*read next basic symbol of source program and return its
  351.     description in the global variables sy, op, id, val and lgth*)
  352.     label 1,2,3;
  353.     var i,k: integer;
  354.     digit: packed array [1..strglgth] of char;
  355.     string: packed array [1..strglgth] of char;
  356.     lvp: csp; test: boolean;
  357.  
  358.     procedure nextch;
  359.     begin if eol then
  360.       begin if list then writeln(output); endofline
  361.       end;
  362.       if not eof(input) then
  363.        begin eol := eoln(input); read(input,ch);
  364.     if list then write(output,ch);
  365.     chcnt := chcnt + 1
  366.        end
  367.       else
  368.     begin writeln(output,'   *** eof ','encountered');
  369.       test := false
  370.     end
  371.     end;
  372.  
  373.     procedure options;
  374.     begin
  375.       repeat nextch;
  376.     if ch <> '*' then
  377.       begin
  378.         if ch = 't' then
  379.           begin nextch; prtables := ch = '+' end
  380.         else
  381.           if ch = 'l' then
  382.         begin nextch; list := ch = '+';
  383.           if not list then writeln(output)
  384.         end
  385.           else
  386.          if ch = 'd' then
  387.            begin nextch; debug := ch = '+' end
  388.          else
  389.         if ch = 'c' then
  390.           begin nextch; prcode := ch = '+' end;
  391.         nextch
  392.       end
  393.       until ch <> ','
  394.     end (*options*) ;
  395.  
  396.   begin (*insymbol*)
  397.   1:
  398.     repeat while ((ch = ' ') or (ch = '    ')) and not eol do nextch;
  399.       test := eol;
  400.       if test then nextch
  401.     until not test;
  402.     if chartp[ch] = illegal then
  403.       begin sy := othersy; op := noop;
  404.     error(399); nextch
  405.       end
  406.     else
  407.     case chartp[ch] of
  408.       letter:
  409.     begin k := 0;
  410.       repeat
  411.         if k < 8 then
  412.          begin k := k + 1; id[k] := ch end ;
  413.         nextch
  414.       until chartp[ch] in [special,illegal,chstrquo,chcolon,
  415.                 chperiod,chlt,chgt,chlparen,chspace];
  416.       if k >= kk then kk := k
  417.       else
  418.         repeat id[kk] := ' '; kk := kk - 1
  419.         until kk = k;
  420.       for i := frw[k] to frw[k+1] - 1 do
  421.         if rw[i] = id then
  422.           begin sy := rsy[i]; op := rop[i]; goto 2 end;
  423.         sy := ident; op := noop;
  424.   2:    end;
  425.       number:
  426.     begin op := noop; i := 0;
  427.       repeat i := i+1; if i<= digmax then digit[i] := ch; nextch
  428.       until chartp[ch] <> number;
  429.       if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  430.         begin
  431.           k := i;
  432.           if ch = '.' then
  433.             begin k := k+1; if k <= digmax then digit[k] := ch;
  434.               nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  435.               if chartp[ch] <> number then error(201)
  436.               else
  437.             repeat k := k + 1;
  438.               if k <= digmax then digit[k] := ch; nextch
  439.             until chartp[ch] <>  number
  440.             end;
  441.           if ch = 'e' then
  442.             begin k := k+1; if k <= digmax then digit[k] := ch;
  443.               nextch;
  444.               if (ch = '+') or (ch ='-') then
  445.             begin k := k+1; if k <= digmax then digit[k] := ch;
  446.               nextch
  447.             end;
  448.               if chartp[ch] <> number then error(201)
  449.               else
  450.             repeat k := k+1;
  451.               if k <= digmax then digit[k] := ch; nextch
  452.             until chartp[ch] <> number
  453.              end;
  454.            new(lvp,reel); sy:= realconst; lvp^.cclass := reel;
  455.            with lvp^ do
  456.              begin for i := 1 to strglgth do rval[i] := ' ';
  457.                if k <= digmax then
  458.              for i := 2 to k + 1 do rval[i] := digit[i-1]
  459.                else begin error(203); rval[2] := '0';
  460.                   rval[3] := '.'; rval[4] := '0'
  461.                 end
  462.              end;
  463.            val.valp := lvp
  464.         end
  465.       else
  466.   3:    begin
  467.           if i > digmax then begin error(203); val.ival := 0 end
  468.           else
  469.         with val do
  470.           begin ival := 0;
  471.             for k := 1 to i do
  472.               begin
  473.             if ival <= mxint10 then
  474.               ival := ival*10+ordint[digit[k]]
  475.             else begin error(203); ival := 0 end
  476.               end;
  477.             sy := intconst
  478.           end
  479.         end
  480.     end;
  481.       chstrquo:
  482.     begin lgth := 0; sy := stringconst;  op := noop;
  483.       repeat
  484.         repeat nextch; lgth := lgth + 1;
  485.            if lgth <= strglgth then string[lgth] := ch
  486.         until (eol) or (ch = '''');
  487.         if eol then error(202) else nextch
  488.       until ch <> '''';
  489.       lgth := lgth - 1;   (*now lgth = nr of chars in string*)
  490.       if lgth = 0 then error(205) else
  491.       if lgth = 1 then val.ival := ord(string[1])
  492.       else
  493.         begin new(lvp,strg); lvp^.cclass:=strg;
  494.           if lgth > strglgth then
  495.         begin error(399); lgth := strglgth end;
  496.           with lvp^ do
  497.         begin slgth := lgth;
  498.           for i := 1 to lgth do sval[i] := string[i]
  499.         end;
  500.           val.valp := lvp
  501.         end
  502.     end;
  503.       chcolon:
  504.     begin op := noop; nextch;
  505.       if ch = '=' then
  506.         begin sy := becomes; nextch end
  507.       else sy := colon
  508.     end;
  509.       chperiod:
  510.     begin op := noop; nextch;
  511.       if ch = '.' then
  512.         begin sy := colon; nextch end
  513.       else sy := period
  514.     end;
  515.       chlt:
  516.     begin nextch; sy := relop;
  517.       if ch = '=' then
  518.         begin op := leop; nextch end
  519.       else
  520.         if ch = '>' then
  521.           begin op := neop; nextch end
  522.         else op := ltop
  523.     end;
  524.       chgt:
  525.     begin nextch; sy := relop;
  526.       if ch = '=' then
  527.         begin op := geop; nextch end
  528.       else op := gtop
  529.     end;
  530.       chlparen:
  531.        begin nextch;
  532.      if ch = '*' then
  533.        begin nextch;
  534.          if ch = '$' then options;
  535.          repeat
  536.            while (ch <> '*') and not eof(input) do nextch;
  537.            nextch
  538.          until (ch = ')') or eof(input);
  539.          nextch; goto 1
  540.        end;
  541.      sy := lparent; op := noop
  542.        end;
  543.       special:
  544.     begin sy := ssy[ch]; op := sop[ch];
  545.       nextch
  546.     end;
  547.       chspace: sy := othersy
  548.     end (*case*)
  549.   end (*insymbol*) ;
  550.  
  551.   procedure enterid(fcp: ctp);
  552.     (*enter id pointed at by fcp into the name-table,
  553.      which on each declaration level is organised as
  554.      an unbalanced binary tree*)
  555.     var nam: alpha; lcp, lcp1: ctp; lleft: boolean;
  556.   begin nam := fcp^.name;
  557.     lcp := display[top].fname;
  558.     if lcp = nil then
  559.       display[top].fname := fcp
  560.     else
  561.       begin
  562.     repeat lcp1 := lcp;
  563.       if lcp^.name = nam then   (*name conflict, follow right link*)
  564.         begin error(101); lcp := lcp^.rlink; lleft := false end
  565.       else
  566.         if lcp^.name < nam then
  567.           begin lcp := lcp^.rlink; lleft := false end
  568.         else begin lcp := lcp^.llink; lleft := true end
  569.     until lcp = nil;
  570.     if lleft then lcp1^.llink := fcp else lcp1^.rlink := fcp
  571.       end;
  572.     fcp^.llink := nil; fcp^.rlink := nil
  573.   end (*enterid*) ;
  574.  
  575.   procedure searchsection(fcp: ctp; var fcp1: ctp);
  576.     (*to find record fields and forward declared procedure id's
  577.      --> procedure proceduredeclaration
  578.      --> procedure selector*)
  579.      label 1;
  580.   begin
  581.     while fcp <> nil do
  582.       if fcp^.name = id then goto 1
  583.       else if fcp^.name < id then fcp := fcp^.rlink
  584.     else fcp := fcp^.llink;
  585. 1:  fcp1 := fcp
  586.   end (*searchsection*) ;
  587.  
  588.   procedure searchid(fidcls: setofids; var fcp: ctp);
  589.     label 1;
  590.     var lcp: ctp;
  591.   begin
  592.     for disx := top downto 0 do
  593.       begin lcp := display[disx].fname;
  594.     while lcp <> nil do
  595.       if lcp^.name = id then
  596.         if lcp^.klass in fidcls then goto 1
  597.         else
  598.           begin if prterr then error(103);
  599.         lcp := lcp^.rlink
  600.           end
  601.       else
  602.         if lcp^.name < id then
  603.           lcp := lcp^.rlink
  604.         else lcp := lcp^.llink
  605.       end;
  606.     (*search not successful; suppress error message in case
  607.      of forward referenced type id in pointer type definition
  608.      --> procedure simpletype*)
  609.     if prterr then
  610.       begin error(104);
  611.     (*to avoid returning nil, reference an entry
  612.      for an undeclared id of appropriate class
  613.      --> procedure enterundecl*)
  614.     if types in fidcls then lcp := utypptr
  615.     else
  616.       if vars in fidcls then lcp := uvarptr
  617.       else
  618.         if field in fidcls then lcp := ufldptr
  619.         else
  620.           if konst in fidcls then lcp := ucstptr
  621.           else
  622.         if proc in fidcls then lcp := uprcptr
  623.         else lcp := ufctptr;
  624.       end;
  625. 1:  fcp := lcp
  626.   end (*searchid*) ;
  627.  
  628.   procedure getbounds(fsp: stp; var fmin,fmax: integer);
  629.     (*get internal bounds of subrange or scalar type*)
  630.     (*assume fsp<>intptr and fsp<>realptr*)
  631.   begin
  632.     fmin := 0; fmax := 0;
  633.     if fsp <> nil then
  634.     with fsp^ do
  635.       if form = subrange then
  636.     begin fmin := min.ival; fmax := max.ival end
  637.       else
  638.       if fsp = charptr then
  639.         begin fmin := ordminchar; fmax := ordmaxchar
  640.         end
  641.       else
  642.         if fconst <> nil then
  643.           fmax := fconst^.values.ival
  644.   end (*getbounds*) ;
  645.  
  646.   function alignquot(fsp: stp): integer;
  647.   begin
  648.     alignquot := 1;
  649.     if fsp <> nil then
  650.       with fsp^ do
  651.     case form of
  652.       scalar:   if fsp=intptr then alignquot := intal
  653.             else if fsp=boolptr then alignquot := boolal
  654.             else if scalkind=declared then alignquot := intal
  655.             else if fsp=charptr then alignquot := charal
  656.             else if fsp=realptr then alignquot := realal
  657.             else (*parmptr*) alignquot := parmal;
  658.       subrange: alignquot := alignquot(rangetype);
  659.       pointer:  alignquot := adral;
  660.       power:    alignquot := setal;
  661.       files:    alignquot := fileal;
  662.       arrays:   alignquot := alignquot(aeltype);
  663.       records:  alignquot := recal;
  664.       variant,tagfld: error(501)
  665.     end
  666.   end (*alignquot*);
  667.  
  668.   procedure align(fsp: stp; var flc: addrrange);
  669.     var k,l: integer;
  670.   begin
  671.     k := alignquot(fsp);
  672.     l := flc-1;
  673.     flc := l + k  -  (k+l) mod k
  674.   end (*align*);
  675.  
  676.   procedure printtables(fb: boolean);
  677.     (*print data structure and name table*)
  678.     var i, lim: disprange;
  679.  
  680.     procedure marker;
  681.       (*mark data structure entries to avoid multiple printout*)
  682.       var i: integer;
  683.  
  684.       procedure markctp(fp: ctp); forward;
  685.  
  686.       procedure markstp(fp: stp);
  687.     (*mark data structures, prevent cycles*)
  688.       begin
  689.     if fp <> nil then
  690.       with fp^ do
  691.         begin marked := true;
  692.           case form of
  693.           scalar:   ;
  694.           subrange: markstp(rangetype);
  695.           pointer:  (*don't mark eltype: cycle possible; will be marked
  696.             anyway, if fp = true*) ;
  697.           power:    markstp(elset) ;
  698.           arrays:   begin markstp(aeltype); markstp(inxtype) end;
  699.           records:  begin markctp(fstfld); markstp(recvar) end;
  700.           files:    markstp(filtype);
  701.           tagfld:   markstp(fstvar);
  702.           variant:  begin markstp(nxtvar); markstp(subvar) end
  703.           end (*case*)
  704.         end (*with*)
  705.       end (*markstp*);
  706.  
  707.       procedure markctp;
  708.       begin
  709.     if fp <> nil then
  710.       with fp^ do
  711.         begin markctp(llink); markctp(rlink);
  712.           markstp(idtype)
  713.         end
  714.       end (*markctp*);
  715.  
  716.     begin (*marker*)
  717.       for i := top downto lim do
  718.     markctp(display[i].fname)
  719.     end (*marker*);
  720.  
  721.     procedure followctp(fp: ctp); forward;
  722.  
  723.     procedure followstp(fp: stp);
  724.     begin
  725.       if fp <> nil then
  726.     with fp^ do
  727.       if marked then
  728.         begin marked := false; write(output,' ':4,ord(fp):6,size:10);
  729.           case form of
  730.           scalar:   begin write(output,'scalar':10);
  731.               if scalkind = standard then
  732.                 write(output,'standard':10)
  733.               else write(output,'declared':10,' ':4,ord(fconst):6);
  734.               writeln(output)
  735.             end;
  736.           subrange: begin
  737.               write(output,'subrange':10,' ':4,ord(rangetype):6);
  738.               if rangetype <> realptr then
  739.                 write(output,min.ival,max.ival)
  740.               else
  741.                 if (min.valp <> nil) and (max.valp <> nil) then
  742.                   write(output,' ',min.valp^.rval:9,
  743.                     ' ',max.valp^.rval:9);
  744.               writeln(output); followstp(rangetype);
  745.             end;
  746.           pointer:  writeln(output,'pointer':10,' ':4,ord(eltype):6);
  747.           power:    begin writeln(output,'set':10,' ':4,ord(elset):6);
  748.               followstp(elset)
  749.             end;
  750.           arrays:   begin
  751.               writeln(output,'array':10,' ':4,ord(aeltype):6,' ':4,
  752.                 ord(inxtype):6);
  753.               followstp(aeltype); followstp(inxtype)
  754.             end;
  755.           records:  begin
  756.               writeln(output,'record':10,' ':4,ord(fstfld):6,' ':4,
  757.                 ord(recvar):6); followctp(fstfld);
  758.               followstp(recvar)
  759.             end;
  760.           files:    begin write(output,'file':10,' ':4,ord(filtype):6);
  761.               followstp(filtype)
  762.             end;
  763.           tagfld:   begin writeln(output,'tagfld':10,' ':4,ord(tagfieldp):6,
  764.                 ' ':4,ord(fstvar):6);
  765.               followstp(fstvar)
  766.             end;
  767.           variant:  begin writeln(output,'variant':10,' ':4,ord(nxtvar):6,
  768.                 ' ':4,ord(subvar):6,varval.ival);
  769.               followstp(nxtvar); followstp(subvar)
  770.             end
  771.           end (*case*)
  772.         end (*if marked*)
  773.     end (*followstp*);
  774.  
  775.     procedure followctp;
  776.       var i: integer;
  777.     begin
  778.       if fp <> nil then
  779.     with fp^ do
  780.       begin write(output,' ':4,ord(fp):6,' ',name:9,' ':4,ord(llink):6,
  781.         ' ':4,ord(rlink):6,' ':4,ord(idtype):6);
  782.         case klass of
  783.           types: write(output,'type':10);
  784.           konst: begin write(output,'constant':10,' ':4,ord(next):6);
  785.                if idtype <> nil then
  786.              if idtype = realptr then
  787.                begin
  788.                  if values.valp <> nil then
  789.                    write(output,' ',values.valp^.rval:9)
  790.                end
  791.              else
  792.                if idtype^.form = arrays then  (*stringconst*)
  793.                  begin
  794.                    if values.valp <> nil then
  795.                  begin write(output,' ');
  796.                    with values.valp^ do
  797.                      for i := 1 to slgth do
  798.                        write(output,sval[i])
  799.                  end
  800.                  end
  801.                else write(output,values.ival)
  802.              end;
  803.           vars:  begin write(output,'variable':10);
  804.                if vkind = actual then write(output,'actual':10)
  805.                else write(output,'formal':10);
  806.                write(output,' ':4,ord(next):6,vlev,' ':4,vaddr:6 );
  807.              end;
  808.           field: write(output,'field':10,' ':4,ord(next):6,' ':4,fldaddr:6);
  809.           proc,
  810.           func:  begin
  811.                if klass = proc then write(output,'procedure':10)
  812.                else write(output,'function':10);
  813.                if pfdeckind = standard then
  814.              write(output,'standard':10, key:10)
  815.                else
  816.              begin write(output,'declared':10,' ':4,ord(next):6);
  817.                write(output,pflev,' ':4,pfname:6);
  818.                if pfkind = actual then
  819.                  begin write(output,'actual':10);
  820.                    if forwdecl then write(output,'forward':10)
  821.                    else write(output,'notforward':10);
  822.                    if extern then write(output,'extern':10)
  823.                    else write(output,'not extern':10);
  824.                  end
  825.                else write(output,'formal':10)
  826.              end
  827.              end
  828.         end (*case*);
  829.         writeln(output);
  830.         followctp(llink); followctp(rlink);
  831.         followstp(idtype)
  832.       end (*with*)
  833.     end (*followctp*);
  834.  
  835.   begin (*printtables*)
  836.     writeln(output); writeln(output); writeln(output);
  837.     if fb then lim := 0
  838.     else begin lim := top; write(output,' local') end;
  839.     writeln(output,' tables '); writeln(output);
  840.     marker;
  841.     for i := top downto lim do
  842.       followctp(display[i].fname);
  843.     writeln(output);
  844.     if not eol then write(output,' ':chcnt+16)
  845.   end (*printtables*);
  846.  
  847.   procedure genlabel(var nxtlab: integer);
  848.   begin intlabel := intlabel + 1;
  849.     nxtlab := intlabel
  850.   end (*genlabel*);
  851.  
  852.   procedure block(fsys: setofsys; fsy: symbol; fprocp: ctp);
  853.     var lsy: symbol; test: boolean;
  854.  
  855.     procedure skip(fsys: setofsys);
  856.       (*skip input string until relevant symbol found*)
  857.     begin
  858.       if not eof(input) then
  859.     begin while not(sy in fsys) and (not eof(input)) do insymbol;
  860.       if not (sy in fsys) then insymbol
  861.     end
  862.     end (*skip*) ;
  863.  
  864.     procedure constant(fsys: setofsys; var fsp: stp; var fvalu: valu);
  865.       var lsp: stp; lcp: ctp; sign: (none,pos,neg);
  866.       lvp: csp; i: 2..strglgth;
  867.     begin lsp := nil; fvalu.ival := 0;
  868.       if not(sy in constbegsys) then
  869.     begin error(50); skip(fsys+constbegsys) end;
  870.       if sy in constbegsys then
  871.     begin
  872.       if sy = stringconst then
  873.         begin
  874.           if lgth = 1 then lsp := charptr
  875.           else
  876.         begin
  877.           new(lsp,arrays);
  878.           with lsp^ do
  879.             begin aeltype := charptr; inxtype := nil;
  880.                size := lgth*charsize; form := arrays
  881.             end
  882.         end;
  883.           fvalu := val; insymbol
  884.         end
  885.       else
  886.         begin
  887.           sign := none;
  888.           if (sy = addop) and (op in [plus,minus]) then
  889.         begin if op = plus then sign := pos else sign := neg;
  890.           insymbol
  891.         end;
  892.           if sy = ident then
  893.         begin searchid([konst],lcp);
  894.           with lcp^ do
  895.             begin lsp := idtype; fvalu := values end;
  896.           if sign <> none then
  897.             if lsp = intptr then
  898.               begin if sign = neg then fvalu.ival := -fvalu.ival end
  899.             else
  900.               if lsp = realptr then
  901.             begin
  902.               if sign = neg then
  903.                 begin new(lvp,reel);
  904.                   if fvalu.valp^.rval[1] = '-' then
  905.                 lvp^.rval[1] := '+'
  906.                   else lvp^.rval[1] := '-';
  907.                   for i := 2 to strglgth do
  908.                 lvp^.rval[i] := fvalu.valp^.rval[i];
  909.                   fvalu.valp := lvp;
  910.                 end
  911.               end
  912.             else error(105);
  913.           insymbol;
  914.         end
  915.           else
  916.         if sy = intconst then
  917.           begin if sign = neg then val.ival := -val.ival;
  918.             lsp := intptr; fvalu := val; insymbol
  919.           end
  920.         else
  921.           if sy = realconst then
  922.             begin if sign = neg then val.valp^.rval[1] := '-';
  923.               lsp := realptr; fvalu := val; insymbol
  924.             end
  925.           else
  926.             begin error(106); skip(fsys) end
  927.         end;
  928.       if not (sy in fsys) then
  929.         begin error(6); skip(fsys) end
  930.       end;
  931.       fsp := lsp
  932.     end (*constant*) ;
  933.  
  934.     function equalbounds(fsp1,fsp2: stp): boolean;
  935.       var lmin1,lmin2,lmax1,lmax2: integer;
  936.     begin
  937.       if (fsp1=nil) or (fsp2=nil) then equalbounds := true
  938.       else
  939.     begin
  940.       getbounds(fsp1,lmin1,lmax1);
  941.       getbounds(fsp2,lmin2,lmax2);
  942.       equalbounds := (lmin1=lmin2) and (lmax1=lmax2)
  943.     end
  944.     end (*equalbounds*) ;
  945.  
  946.     function comptypes(fsp1,fsp2: stp) : boolean;
  947.       (*decide whether structures pointed at by fsp1 and fsp2 are compatible*)
  948.       var nxt1,nxt2: ctp; comp: boolean;
  949.     ltestp1,ltestp2 : testp;
  950.     begin
  951.       if fsp1 = fsp2 then comptypes := true
  952.       else
  953.     if (fsp1 <> nil) and (fsp2 <> nil) then
  954.       if fsp1^.form = fsp2^.form then
  955.         case fsp1^.form of
  956.           scalar:
  957.         comptypes := false;
  958.         (* identical scalars declared on different levels are
  959.          not recognized to be compatible*)
  960.           subrange:
  961.         comptypes := comptypes(fsp1^.rangetype,fsp2^.rangetype);
  962.           pointer:
  963.           begin
  964.             comp := false; ltestp1 := globtestp;
  965.             ltestp2 := globtestp;
  966.             while ltestp1 <> nil do
  967.               with ltestp1^ do
  968.             begin
  969.               if (elt1 = fsp1^.eltype) and
  970.                  (elt2 = fsp2^.eltype) then comp := true;
  971.               ltestp1 := lasttestp
  972.             end;
  973.             if not comp then
  974.               begin new(ltestp1);
  975.             with ltestp1^ do
  976.               begin elt1 := fsp1^.eltype;
  977.                 elt2 := fsp2^.eltype;
  978.                 lasttestp := globtestp
  979.               end;
  980.             globtestp := ltestp1;
  981.             comp := comptypes(fsp1^.eltype,fsp2^.eltype)
  982.               end;
  983.             comptypes := comp; globtestp := ltestp2
  984.           end;
  985.           power:
  986.         comptypes := comptypes(fsp1^.elset,fsp2^.elset);
  987.           arrays:
  988.         begin
  989.           comp := comptypes(fsp1^.aeltype,fsp2^.aeltype)
  990.               and comptypes(fsp1^.inxtype,fsp2^.inxtype);
  991.           comptypes := comp and (fsp1^.size = fsp2^.size) and
  992.               equalbounds(fsp1^.inxtype,fsp2^.inxtype)
  993.         end;
  994.           records:
  995.         begin nxt1 := fsp1^.fstfld; nxt2 := fsp2^.fstfld; comp:=true;
  996.           while (nxt1 <> nil) and (nxt2 <> nil) do
  997.             begin comp:=comp and comptypes(nxt1^.idtype,nxt2^.idtype);
  998.               nxt1 := nxt1^.next; nxt2 := nxt2^.next
  999.             end;
  1000.           comptypes := comp and (nxt1 = nil) and (nxt2 = nil)
  1001.                   and(fsp1^.recvar = nil)and(fsp2^.recvar = nil)
  1002.         end;
  1003.         (*identical records are recognized to be compatible
  1004.          iff no variants occur*)
  1005.           files:
  1006.         comptypes := comptypes(fsp1^.filtype,fsp2^.filtype)
  1007.         end (*case*)
  1008.       else (*fsp1^.form <> fsp2^.form*)
  1009.         if fsp1^.form = subrange then
  1010.           comptypes := comptypes(fsp1^.rangetype,fsp2)
  1011.         else
  1012.           if fsp2^.form = subrange then
  1013.         comptypes := comptypes(fsp1,fsp2^.rangetype)
  1014.           else comptypes := false
  1015.     else comptypes := true
  1016.     end (*comptypes*) ;
  1017.  
  1018.     function string(fsp: stp) : boolean;
  1019.     begin string := false;
  1020.       if fsp <> nil then
  1021.     if fsp^.form = arrays then
  1022.       if comptypes(fsp^.aeltype,charptr) then string := true
  1023.     end (*string*) ;
  1024.  
  1025.     procedure typ(fsys: setofsys; var fsp: stp; var fsize: addrrange);
  1026.       var lsp,lsp1,lsp2: stp; oldtop: disprange; lcp: ctp;
  1027.       lsize,displ: addrrange; lmin,lmax: integer;
  1028.  
  1029.       procedure simpletype(fsys:setofsys; var fsp:stp; var fsize:addrrange);
  1030.     var lsp,lsp1: stp; lcp,lcp1: ctp; ttop: disprange;
  1031.         lcnt: integer; lvalu: valu;
  1032.       begin fsize := 1;
  1033.     if not (sy in simptypebegsys) then
  1034.       begin error(1); skip(fsys + simptypebegsys) end;
  1035.     if sy in simptypebegsys then
  1036.       begin
  1037.         if sy = lparent then
  1038.           begin ttop := top;   (*decl. consts local to innermost block*)
  1039.         while display[top].occur <> blck do top := top - 1;
  1040.         new(lsp,scalar,declared);
  1041.         with lsp^ do
  1042.           begin size := intsize; form := scalar;
  1043.             scalkind := declared
  1044.           end;
  1045.         lcp1 := nil; lcnt := 0;
  1046.         repeat insymbol;
  1047.           if sy = ident then
  1048.             begin new(lcp,konst);
  1049.               with lcp^ do
  1050.             begin name := id; idtype := lsp; next := lcp1;
  1051.               values.ival := lcnt; klass := konst
  1052.             end;
  1053.               enterid(lcp);
  1054.               lcnt := lcnt + 1;
  1055.               lcp1 := lcp; insymbol
  1056.             end
  1057.           else error(2);
  1058.           if not (sy in fsys + [comma,rparent]) then
  1059.             begin error(6); skip(fsys + [comma,rparent]) end
  1060.         until sy <> comma;
  1061.         lsp^.fconst := lcp1; top := ttop;
  1062.         if sy = rparent then insymbol else error(4)
  1063.           end
  1064.         else
  1065.           begin
  1066.         if sy = ident then
  1067.           begin searchid([types,konst],lcp);
  1068.             insymbol;
  1069.             if lcp^.klass = konst then
  1070.               begin new(lsp,subrange);
  1071.             with lsp^, lcp^ do
  1072.               begin rangetype := idtype; form := subrange;
  1073.                 if string(rangetype) then
  1074.                   begin error(148); rangetype := nil end;
  1075.                 min := values; size := intsize
  1076.               end;
  1077.             if sy = colon then insymbol else error(5);
  1078.             constant(fsys,lsp1,lvalu);
  1079.             lsp^.max := lvalu;
  1080.             if lsp^.rangetype <> lsp1 then error(107)
  1081.               end
  1082.             else
  1083.               begin lsp := lcp^.idtype;
  1084.             if lsp <> nil then fsize := lsp^.size
  1085.               end
  1086.           end (*sy = ident*)
  1087.         else
  1088.           begin new(lsp,subrange); lsp^.form := subrange;
  1089.             constant(fsys + [colon],lsp1,lvalu);
  1090.             if string(lsp1) then
  1091.               begin error(148); lsp1 := nil end;
  1092.             with lsp^ do
  1093.               begin rangetype:=lsp1; min:=lvalu; size:=intsize end;
  1094.             if sy = colon then insymbol else error(5);
  1095.             constant(fsys,lsp1,lvalu);
  1096.             lsp^.max := lvalu;
  1097.             if lsp^.rangetype <> lsp1 then error(107)
  1098.           end;
  1099.         if lsp <> nil then
  1100.           with lsp^ do
  1101.             if form = subrange then
  1102.               if rangetype <> nil then
  1103.             if rangetype = realptr then error(399)
  1104.             else
  1105.               if min.ival > max.ival then error(102)
  1106.           end;
  1107.         fsp := lsp;
  1108.         if not (sy in fsys) then
  1109.           begin error(6); skip(fsys) end
  1110.       end
  1111.         else fsp := nil
  1112.       end (*simpletype*) ;
  1113.  
  1114.       procedure fieldlist(fsys: setofsys; var frecvar: stp);
  1115.     var lcp,lcp1,nxt,nxt1: ctp; lsp,lsp1,lsp2,lsp3,lsp4: stp;
  1116.         minsize,maxsize,lsize: addrrange; lvalu: valu;
  1117.       begin nxt1 := nil; lsp := nil;
  1118.     if not (sy in (fsys+[ident,casesy])) then
  1119.       begin error(19); skip(fsys + [ident,casesy]) end;
  1120.     while sy = ident do
  1121.       begin nxt := nxt1;
  1122.         repeat
  1123.           if sy = ident then
  1124.         begin new(lcp,field);
  1125.           with lcp^ do
  1126.             begin name := id; idtype := nil; next := nxt;
  1127.               klass := field
  1128.             end;
  1129.           nxt := lcp;
  1130.           enterid(lcp);
  1131.           insymbol
  1132.         end
  1133.           else error(2);
  1134.           if not (sy in [comma,colon]) then
  1135.         begin error(6); skip(fsys + [comma,colon,semicolon,casesy])
  1136.         end;
  1137.           test := sy <> comma;
  1138.           if not test  then insymbol
  1139.         until test;
  1140.         if sy = colon then insymbol else error(5);
  1141.         typ(fsys + [casesy,semicolon],lsp,lsize);
  1142.         while nxt <> nxt1 do
  1143.           with nxt^ do
  1144.         begin align(lsp,displ);
  1145.           idtype := lsp; fldaddr := displ;
  1146.           nxt := next; displ := displ + lsize
  1147.         end;
  1148.         nxt1 := lcp;
  1149.         while sy = semicolon do
  1150.           begin insymbol;
  1151.         if not (sy in fsys + [ident,casesy,semicolon]) then
  1152.           begin error(19); skip(fsys + [ident,casesy]) end
  1153.           end
  1154.       end (*while*);
  1155.     nxt := nil;
  1156.     while nxt1 <> nil do
  1157.       with nxt1^ do
  1158.         begin lcp := next; next := nxt; nxt := nxt1; nxt1 := lcp end;
  1159.     if sy = casesy then
  1160.       begin new(lsp,tagfld);
  1161.         with lsp^ do
  1162.           begin tagfieldp := nil; fstvar := nil; form:=tagfld end;
  1163.         frecvar := lsp;
  1164.         insymbol;
  1165.         if sy = ident then
  1166.           begin new(lcp,field);
  1167.         with lcp^ do
  1168.           begin name := id; idtype := nil; klass:=field;
  1169.             next := nil; fldaddr := displ
  1170.           end;
  1171.         enterid(lcp);
  1172.         insymbol;
  1173.         if sy = colon then insymbol else error(5);
  1174.         if sy = ident then
  1175.           begin searchid([types],lcp1);
  1176.             lsp1 := lcp1^.idtype;
  1177.             if lsp1 <> nil then
  1178.               begin align(lsp1,displ);
  1179.             lcp^.fldaddr := displ;
  1180.             displ := displ+lsp1^.size;
  1181.             if (lsp1^.form <= subrange) or string(lsp1) then
  1182.               begin if comptypes(realptr,lsp1) then error(109)
  1183.                 else if string(lsp1) then error(399);
  1184.                 lcp^.idtype := lsp1; lsp^.tagfieldp := lcp;
  1185.               end
  1186.             else error(110);
  1187.               end;
  1188.             insymbol;
  1189.           end
  1190.         else begin error(2); skip(fsys + [ofsy,lparent]) end
  1191.           end
  1192.         else begin error(2); skip(fsys + [ofsy,lparent]) end;
  1193.         lsp^.size := displ;
  1194.         if sy = ofsy then insymbol else error(8);
  1195.         lsp1 := nil; minsize := displ; maxsize := displ;
  1196.         repeat lsp2 := nil;
  1197.           if not (sy in fsys + [semicolon]) then
  1198.           begin
  1199.         repeat constant(fsys + [comma,colon,lparent],lsp3,lvalu);
  1200.           if lsp^.tagfieldp <> nil then
  1201.            if not comptypes(lsp^.tagfieldp^.idtype,lsp3)then error(111);
  1202.           new(lsp3,variant);
  1203.           with lsp3^ do
  1204.             begin nxtvar := lsp1; subvar := lsp2; varval := lvalu;
  1205.               form := variant
  1206.             end;
  1207.           lsp4 := lsp1;
  1208.           while lsp4 <> nil do
  1209.             with lsp4^ do
  1210.               begin
  1211.             if varval.ival = lvalu.ival then error(178);
  1212.             lsp4 := nxtvar
  1213.               end;
  1214.           lsp1 := lsp3; lsp2 := lsp3;
  1215.           test := sy <> comma;
  1216.           if not test then insymbol
  1217.         until test;
  1218.         if sy = colon then insymbol else error(5);
  1219.         if sy = lparent then insymbol else error(9);
  1220.         fieldlist(fsys + [rparent,semicolon],lsp2);
  1221.         if displ > maxsize then maxsize := displ;
  1222.         while lsp3 <> nil do
  1223.           begin lsp4 := lsp3^.subvar; lsp3^.subvar := lsp2;
  1224.             lsp3^.size := displ;
  1225.             lsp3 := lsp4
  1226.           end;
  1227.         if sy = rparent then
  1228.           begin insymbol;
  1229.             if not (sy in fsys + [semicolon]) then
  1230.               begin error(6); skip(fsys + [semicolon]) end
  1231.           end
  1232.         else error(4);
  1233.           end;
  1234.           test := sy <> semicolon;
  1235.           if not test then
  1236.         begin displ := minsize;
  1237.               insymbol
  1238.         end
  1239.         until test;
  1240.         displ := maxsize;
  1241.         lsp^.fstvar := lsp1;
  1242.       end
  1243.     else frecvar := nil
  1244.       end (*fieldlist*) ;
  1245.  
  1246.     begin (*typ*)
  1247.       if not (sy in typebegsys) then
  1248.      begin error(10); skip(fsys + typebegsys) end;
  1249.       if sy in typebegsys then
  1250.     begin
  1251.       if sy in simptypebegsys then simpletype(fsys,fsp,fsize)
  1252.       else
  1253.     (*^*)     if sy = arrow then
  1254.           begin new(lsp,pointer); fsp := lsp;
  1255.         with lsp^ do
  1256.           begin eltype := nil; size := ptrsize; form:=pointer end;
  1257.         insymbol;
  1258.         if sy = ident then
  1259.           begin prterr := false; (*no error if search not successful*)
  1260.             searchid([types],lcp); prterr := true;
  1261.             if lcp = nil then   (*forward referenced type id*)
  1262.               begin new(lcp,types);
  1263.             with lcp^ do
  1264.               begin name := id; idtype := lsp;
  1265.                 next := fwptr; klass := types
  1266.               end;
  1267.             fwptr := lcp
  1268.               end
  1269.             else
  1270.               begin
  1271.             if lcp^.idtype <> nil then
  1272.               if lcp^.idtype^.form = files then error(108)
  1273.               else lsp^.eltype := lcp^.idtype
  1274.               end;
  1275.             insymbol;
  1276.           end
  1277.         else error(2);
  1278.           end
  1279.         else
  1280.           begin
  1281.         if sy = packedsy then
  1282.           begin insymbol;
  1283.             if not (sy in typedels) then
  1284.               begin
  1285.             error(10); skip(fsys + typedels)
  1286.               end
  1287.           end;
  1288.     (*array*)     if sy = arraysy then
  1289.           begin insymbol;
  1290.             if sy = lbrack then insymbol else error(11);
  1291.             lsp1 := nil;
  1292.             repeat new(lsp,arrays);
  1293.               with lsp^ do
  1294.             begin aeltype := lsp1; inxtype := nil; form:=arrays end;
  1295.               lsp1 := lsp;
  1296.               simpletype(fsys + [comma,rbrack,ofsy],lsp2,lsize);
  1297.               lsp1^.size := lsize;
  1298.               if lsp2 <> nil then
  1299.             if lsp2^.form <= subrange then
  1300.               begin
  1301.                 if lsp2 = realptr then
  1302.                   begin error(109); lsp2 := nil end
  1303.                 else
  1304.                   if lsp2 = intptr then
  1305.                 begin error(149); lsp2 := nil end;
  1306.                 lsp^.inxtype := lsp2
  1307.               end
  1308.             else begin error(113); lsp2 := nil end;
  1309.               test := sy <> comma;
  1310.               if not test then insymbol
  1311.             until test;
  1312.             if sy = rbrack then insymbol else error(12);
  1313.             if sy = ofsy then insymbol else error(8);
  1314.             typ(fsys,lsp,lsize);
  1315.             repeat
  1316.               with lsp1^ do
  1317.             begin lsp2 := aeltype; aeltype := lsp;
  1318.               if inxtype <> nil then
  1319.                 begin getbounds(inxtype,lmin,lmax);
  1320.                   align(lsp,lsize);
  1321.                   lsize := lsize*(lmax - lmin + 1);
  1322.                   size := lsize
  1323.                 end
  1324.             end;
  1325.               lsp := lsp1; lsp1 := lsp2
  1326.             until lsp1 = nil
  1327.           end
  1328.         else
  1329.     (*record*)      if sy = recordsy then
  1330.             begin insymbol;
  1331.               oldtop := top;
  1332.               if top < displimit then
  1333.             begin top := top + 1;
  1334.               with display[top] do
  1335.                 begin fname := nil;
  1336.                   flabel := nil;
  1337.                   occur := rec
  1338.                 end
  1339.             end
  1340.               else error(250);
  1341.               displ := 0;
  1342.               fieldlist(fsys-[semicolon]+[endsy],lsp1);
  1343.               new(lsp,records);
  1344.               with lsp^ do
  1345.             begin fstfld := display[top].fname;
  1346.               recvar := lsp1; size := displ; form := records
  1347.             end;
  1348.               top := oldtop;
  1349.               if sy = endsy then insymbol else error(13)
  1350.             end
  1351.           else
  1352.     (*set*)       if sy = setsy then
  1353.               begin insymbol;
  1354.             if sy = ofsy then insymbol else error(8);
  1355.             simpletype(fsys,lsp1,lsize);
  1356.             if lsp1 <> nil then
  1357.               if lsp1^.form > subrange then
  1358.                 begin error(115); lsp1 := nil end
  1359.               else
  1360.                 if lsp1 = realptr then
  1361.                   begin error(114); lsp1 := nil end
  1362.                 else if lsp1 = intptr then
  1363.                   begin error(169); lsp1 := nil end
  1364.                 else
  1365.                   begin getbounds(lsp1,lmin,lmax);
  1366.                 if (lmin < setlow) or (lmax > sethigh)
  1367.                   then error(169);
  1368.                   end;
  1369.             new(lsp,power);
  1370.             with lsp^ do
  1371.               begin elset:=lsp1; size:=setsize; form:=power end;
  1372.               end
  1373.             else
  1374.     (*file*)        if sy = filesy then
  1375.               begin insymbol;
  1376.                 error(399); skip(fsys); lsp := nil
  1377.               end;
  1378.         fsp := lsp
  1379.           end;
  1380.       if not (sy in fsys) then
  1381.         begin error(6); skip(fsys) end
  1382.     end
  1383.       else fsp := nil;
  1384.       if fsp = nil then fsize := 1 else fsize := fsp^.size
  1385.     end (*typ*) ;
  1386.  
  1387.     procedure labeldeclaration;
  1388.       var llp: lbp; redef: boolean; lbname: integer;
  1389.     begin
  1390.       repeat
  1391.     if sy = intconst then
  1392.       with display[top] do
  1393.         begin llp := flabel; redef := false;
  1394.           while (llp <> nil) and not redef do
  1395.         if llp^.labval <> val.ival then
  1396.           llp := llp^.nextlab
  1397.         else begin redef := true; error(166) end;
  1398.           if not redef then
  1399.         begin new(llp);
  1400.           with llp^ do
  1401.             begin labval := val.ival; genlabel(lbname);
  1402.               defined := false; nextlab := flabel; labname := lbname
  1403.             end;
  1404.           flabel := llp
  1405.         end;
  1406.           insymbol
  1407.         end
  1408.     else error(15);
  1409.     if not ( sy in fsys + [comma, semicolon] ) then
  1410.       begin error(6); skip(fsys+[comma,semicolon]) end;
  1411.     test := sy <> comma;
  1412.     if not test then insymbol
  1413.       until test;
  1414.       if sy = semicolon then insymbol else error(14)
  1415.     end (* labeldeclaration *) ;
  1416.  
  1417.     procedure constdeclaration;
  1418.       var lcp: ctp; lsp: stp; lvalu: valu;
  1419.     begin
  1420.       if sy <> ident then
  1421.     begin error(2); skip(fsys + [ident]) end;
  1422.       while sy = ident do
  1423.     begin new(lcp,konst);
  1424.       with lcp^ do
  1425.         begin name := id; idtype := nil; next := nil; klass:=konst end;
  1426.       insymbol;
  1427.       if (sy = relop) and (op = eqop) then insymbol else error(16);
  1428.       constant(fsys + [semicolon],lsp,lvalu);
  1429.       enterid(lcp);
  1430.       lcp^.idtype := lsp; lcp^.values := lvalu;
  1431.       if sy = semicolon then
  1432.         begin insymbol;
  1433.           if not (sy in fsys + [ident]) then
  1434.         begin error(6); skip(fsys + [ident]) end
  1435.         end
  1436.       else error(14)
  1437.     end
  1438.     end (*constdeclaration*) ;
  1439.  
  1440.     procedure typedeclaration;
  1441.       var lcp,lcp1,lcp2: ctp; lsp: stp; lsize: addrrange;
  1442.     begin
  1443.       if sy <> ident then
  1444.     begin error(2); skip(fsys + [ident]) end;
  1445.       while sy = ident do
  1446.     begin new(lcp,types);
  1447.       with lcp^ do
  1448.         begin name := id; idtype := nil; klass := types end;
  1449.       insymbol;
  1450.       if (sy = relop) and (op = eqop) then insymbol else error(16);
  1451.       typ(fsys + [semicolon],lsp,lsize);
  1452.       enterid(lcp);
  1453.       lcp^.idtype := lsp;
  1454.       (*has any forward reference been satisfied:*)
  1455.       lcp1 := fwptr;
  1456.       while lcp1 <> nil do
  1457.         begin
  1458.           if lcp1^.name = lcp^.name then
  1459.         begin lcp1^.idtype^.eltype := lcp^.idtype;
  1460.           if lcp1 <> fwptr then
  1461.             lcp2^.next := lcp1^.next
  1462.           else fwptr := lcp1^.next;
  1463.         end
  1464.           else lcp2 := lcp1;
  1465.           lcp1 := lcp1^.next
  1466.         end;
  1467.       if sy = semicolon then
  1468.         begin insymbol;
  1469.           if not (sy in fsys + [ident]) then
  1470.         begin error(6); skip(fsys + [ident]) end
  1471.         end
  1472.       else error(14)
  1473.     end;
  1474.       if fwptr <> nil then
  1475.     begin error(117); writeln(output);
  1476.       repeat writeln(output,' type-id ',fwptr^.name);
  1477.         fwptr := fwptr^.next
  1478.       until fwptr = nil;
  1479.       if not eol then write(output,' ': chcnt+16)
  1480.     end
  1481.     end (*typedeclaration*) ;
  1482.  
  1483.     procedure vardeclaration;
  1484.       var lcp,nxt: ctp; lsp: stp; lsize: addrrange;
  1485.     begin nxt := nil;
  1486.       repeat
  1487.     repeat
  1488.       if sy = ident then
  1489.         begin new(lcp,vars);
  1490.           with lcp^ do
  1491.            begin name := id; next := nxt; klass := vars;
  1492.           idtype := nil; vkind := actual; vlev := level
  1493.         end;
  1494.           enterid(lcp);
  1495.           nxt := lcp;
  1496.           insymbol;
  1497.         end
  1498.       else error(2);
  1499.       if not (sy in fsys + [comma,colon] + typedels) then
  1500.         begin error(6); skip(fsys+[comma,colon,semicolon]+typedels) end;
  1501.       test := sy <> comma;
  1502.       if not test then insymbol
  1503.     until test;
  1504.     if sy = colon then insymbol else error(5);
  1505.     typ(fsys + [semicolon] + typedels,lsp,lsize);
  1506.     while nxt <> nil do
  1507.       with  nxt^ do
  1508.         begin align(lsp,lc);
  1509.           idtype := lsp; vaddr := lc;
  1510.           lc := lc + lsize; nxt := next
  1511.         end;
  1512.     if sy = semicolon then
  1513.       begin insymbol;
  1514.         if not (sy in fsys + [ident]) then
  1515.           begin error(6); skip(fsys + [ident]) end
  1516.       end
  1517.     else error(14)
  1518.       until (sy <> ident) and not (sy in typedels);
  1519.       if fwptr <> nil then
  1520.     begin error(117); writeln(output);
  1521.       repeat writeln(output,' type-id ',fwptr^.name);
  1522.         fwptr := fwptr^.next
  1523.       until fwptr = nil;
  1524.       if not eol then write(output,' ': chcnt+16)
  1525.     end
  1526.     end (*vardeclaration*) ;
  1527.  
  1528.     procedure procdeclaration(fsy: symbol);
  1529.       var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp;
  1530.       forw: boolean; oldtop: disprange;
  1531.       llc,lcm: addrrange; lbname: integer; markp: marktype;
  1532.  
  1533.       procedure parameterlist(fsy: setofsys; var fpar: ctp);
  1534.     var lcp,lcp1,lcp2,lcp3: ctp; lsp: stp; lkind: idkind;
  1535.       llc,lsize: addrrange; count: integer;
  1536.       begin lcp1 := nil;
  1537.     if not (sy in fsy + [lparent]) then
  1538.       begin error(7); skip(fsys + fsy + [lparent]) end;
  1539.     if sy = lparent then
  1540.       begin if forw then error(119);
  1541.         insymbol;
  1542.         if not (sy in [ident,varsy,procsy,funcsy]) then
  1543.           begin error(7); skip(fsys + [ident,rparent]) end;
  1544.         while sy in [ident,varsy,procsy,funcsy] do
  1545.           begin
  1546.         if sy = procsy then
  1547.           begin error(399);
  1548.             repeat insymbol;
  1549.               if sy = ident then
  1550.             begin new(lcp,proc,declared,formal);
  1551.               with lcp^ do
  1552.                 begin name := id; idtype := nil; next := lcp1;
  1553.                   pflev := level (*beware of parameter procedures*);
  1554.                   klass:=proc;pfdeckind:=declared;pfkind:=formal
  1555.                 end;
  1556.               enterid(lcp);
  1557.               lcp1 := lcp;
  1558.               align(parmptr,lc);
  1559.               (*lc := lc + some size *)
  1560.               insymbol
  1561.             end
  1562.               else error(2);
  1563.               if not (sy in fsys + [comma,semicolon,rparent]) then
  1564.             begin error(7);skip(fsys+[comma,semicolon,rparent])end
  1565.             until sy <> comma
  1566.           end
  1567.         else
  1568.           begin
  1569.             if sy = funcsy then
  1570.               begin error(399); lcp2 := nil;
  1571.             repeat insymbol;
  1572.               if sy = ident then
  1573.                 begin new(lcp,func,declared,formal);
  1574.                   with lcp^ do
  1575.                 begin name := id; idtype := nil; next := lcp2;
  1576.                   pflev := level (*beware param funcs*);
  1577.                   klass:=func;pfdeckind:=declared;
  1578.                   pfkind:=formal
  1579.                 end;
  1580.                   enterid(lcp);
  1581.                  lcp2 := lcp;
  1582.                  align(parmptr,lc);
  1583.                  (*lc := lc + some size*)
  1584.                   insymbol;
  1585.                 end;
  1586.               if not (sy in [comma,colon] + fsys) then
  1587.                 begin error(7);skip(fsys+[comma,semicolon,rparent])
  1588.