  (*$p**************************************************************************)
  (*                                                                           *)
  (*                           File: DUMP.TEXT                                 *)
  (*                                                                           *)
  (*              (C) Copyright 1981 Silicon Valley Software, Inc.             *)
  (*                            1983, 1984 Apple Computer, Inc.                *)
  (*                                                                           *)
  (*                            All rights reserved.               28-Jul-82   *)
  (*                                                                           *)
  (*  5-24-83 Selector: evaluate '^' using Expression instead of Selector      *)
  (* 12-20-83 CallingUnits added to control casing of unit init name calls     *)
  (* 12-27-83 DumpMethod changed to generate special I-code calling of methods *)
  (* 12-27-83 DumpUCall changed to handle new method calling sequences         *)
  (* 01-07-84 ThisClass and InClass standard functions added to DumpSfCall     *)
  (* 02-06-84 DumpInline: added to generate INLINE code                        *)
  (* 02-17-84 Changes to 205 i-code for code gen asm listing                   *)
  (* 03-29-84 DumpCCall and additions to call C code                           *)
  (*****************************************************************************)
  {[j=0/0/80!,@=11,i=1]}

  {$S DUMP}

  PROCEDURE Dump(ProcTree: pStmt; ProcN: pN; CallingUnits: Boolean);           {!12-20-83}

    CONST
      MAXLBUFF = 8192;

    TYPE
      pExtRec = ^ExtRec;
      ExtRec = RECORD
                 Next: pExtRec;
                 LinkName, UserName: Alfa;
                 ExtNo: Integer;
               END;

    VAR
      i, LabNo, WithLevel, lLc, lSize: Integer;
      Father,                                                                  {!C}
      lName, uName: Alfa;
      lpN: pN;
      lpLabel: pLabRec;
      NextExtNo: Integer;
      ExtList: pExtRec;
      GlobalLabels: Boolean;
      lByteNo: Integer;
      lBuff: PACKED ARRAY [0..MAXLBUFF] OF Char;
      UnitSet, IntrinSet: SET OF 0..MAXUNITS;                                  {!IU!}

    PROCEDURE Lout(fVal: Integer);

      BEGIN {LOut}
        IF lByteNo < MAXLBUFF THEN
          BEGIN
          lBuff[lByteNo] := Chr(fVal); lByteNo := lByteNo + 1;
          END
        ELSE
          BEGIN
          Error(350); lByteNo := 0;
          END;
      END; {LOut}

    PROCEDURE Lout2(fVal: Integer);

      VAR
        c: PACKED ARRAY [0..1] OF Char;

      BEGIN {Lout2}
        MoveLeft(fVal, c, 2);
        IF FlipBytes THEN
          BEGIN
          Lout(Ord(c[1])); Lout(Ord(c[0]));
          END
        ELSE
          BEGIN
          Lout(Ord(c[0])); Lout(Ord(c[1]));
          END;
      END; {Lout2}

    FUNCTION NextLabel: Integer;

      BEGIN
        NextLabel := LabNo;
        LabNo := LabNo + 1;
      END; {nextlabel}

    PROCEDURE MakeLName(VAR FName: Alfa; N: Integer);

      VAR
        i: Integer;

      BEGIN {MakeLName}
        FName[1] := '$';
        FOR i := 2 TO 8 DO
          BEGIN
          FName[i] := Chr(Ord('0') + N MOD 10); N := N DIV 10;
          END;
      END; {MakeLName}

    FUNCTION FindExt(fUserName: Alfa; RtnNo, fLev: Integer): pExtRec;

      VAR
        lExt: pExtRec;
        i: Integer;
        MatchFlag: Boolean;
        lLinkName: Alfa;

      FUNCTION NewExt: pExtRec;

        CONST
          MAXEXT = 200; {Same const appears in CODE.TEXT}

        VAR
          lExt: pExtRec;
          i: Integer;
          Ch: Char;
          UserName: Alfa;

        BEGIN {NewExt}
          IF NextExtNo <= MAXEXT THEN
            BEGIN
            Out(241);
            FOR i := 1 TO 8 DO Out(Ord(lLinkName[i]));
            FOR i := 1 TO 8 DO Out(Ord(fUserName[i]));
            Out2(NextExtNo); Out(fLev);
            END
          ELSE
            Error(309);
          New(lExt);
          WITH lExt^ DO
            BEGIN
            Next := NIL; LinkName := lLinkName;
            UserName := fUserName; ExtNo := NextExtNo;
            END;
          NextExtNo := NextExtNo + 1;
          NewExt := lExt;
        END; {NewExt}

      BEGIN {FindExt}
        IF RtnNo < 0 THEN
          BEGIN
          lLinkName := fUserName;
          IF CallingUnits THEN                                                 {!12-20-83}
            FOR i := 1 TO 8 DO                                                 {!12-20-83}
              IF fUserName[i] >= 'a' THEN                                      {!12-20-83}
                IF fUserName[i] <= 'z' THEN                                    {!12-20-83}
                  fUserName[i] := Chr(Ord(fUserName[i]) - 32);                 {!12-20-83}
          END                                                                  {!12-20-83}
        ELSE
          MakeLName(lLinkName, RtnNo);
        IF ExtList = NIL THEN
          BEGIN
          lExt := NewExt; ExtList := lExt;
          END
        ELSE
          BEGIN
          lExt := ExtList; MatchFlag := False;
          REPEAT
            WITH lExt^ DO
              IF LinkName = lLinkName THEN
                MatchFlag := True
              ELSE
                BEGIN
                IF Next = NIL THEN
                  BEGIN
                  Next := NewExt;
                  MatchFlag := True;
                  END;
                lExt := Next;
                END;
          UNTIL MatchFlag;
          END;
        FindExt := lExt;
      END; {FindExt}

    FUNCTION UnitIsRegular(fLev: Integer): Boolean;                            {!IU!}

      VAR
        lpN: pN;
        i: Integer;

      BEGIN {UnitIsRegular - returns true iff flev corresponds to a regular unit}
        IF fLev >= 0 THEN
          UnitIsRegular := False
        ELSE
          BEGIN
          lpN := UnitList;
          WHILE lpN <> NIL DO
            WITH lpN^ DO
              IF fLev = - Ulev THEN
                BEGIN
                UnitIsRegular := Ukind = REGUNIT;
                lpN := NIL;
                END
              ELSE
                lpN := Next;
          END;
      END; {UnitIsRegular}                                                     {!IU!}

    PROCEDURE FindUnit(fLev: Integer);

      VAR
        lpN: pN;
        i: Integer;

      BEGIN {FindUnit}
        IF NOT (fLev IN UnitSet) THEN
          BEGIN
          lpN := UnitList;
          WHILE lpN <> NIL DO
            WITH lpN^ DO
              IF fLev = - Ulev THEN
                BEGIN
                Out(242);
                FOR i := 1 TO 8 DO Out(Ord(Name[i]));
                Out(fLev);
                Out(Ord(Ukind));                                               {!IU!}
                IF Ukind <> REGUNIT THEN IntrinSet := IntrinSet + [fLev];      {!IU!}
                lpN := NIL; UnitSet := UnitSet + [fLev];
                END
              ELSE
                lpN := Next;
          END;
      END; {FindUnit}

    PROCEDURE DumpJSR(fOp, fLev, RtnNo: Integer; fUserName: Alfa);

      VAR
        lExt: pExtRec;

      BEGIN {DumpJSR}
        lExt := FindExt(fUserName, RtnNo, fLev);
        Lout(fOp); Lout2(lExt^.ExtNo);
      END; {DumpJSR}

    PROCEDURE OutIntCnst(fValue: LongInt; fSize: Integer);

      VAR
        Ch: Char;
        c: PACKED ARRAY [0..3] OF Char;

      BEGIN {OutIntCnst}
        MoveLeft(fValue, c, 4);
        IF FlipBytes THEN
          BEGIN
          Ch := c[0]; c[0] := c[1]; c[1] := Ch;
          Ch := c[2]; c[2] := c[3]; c[3] := Ch;
          END;
        IF fSize > 2 THEN
          BEGIN
          Lout(26 {CNST4} ); Lout(Ord(c[0])); Lout(Ord(c[1]));
          END
        ELSE
          Lout(24 {CNST1} + Ord(fSize > 1));
        IF fSize > 1 THEN Lout(Ord(c[2]));
        Lout(Ord(c[3]));
      END; {OutIntCns}

    PROCEDURE DumpMethod(fOp, MethodNumber, MethodLevel: Integer);             {!C}

      BEGIN {DumpMethod}
        Lout(253 {METHCALL} );                                                 {!12-27-83}
        Lout(Ord(fOp = 176 {UFUNCALL} ));                                      {!12-27-83}
        Lout(MethodLevel); Lout(MethodNumber);                                 {!12-27-83}
      END; {DumpMethod}

    PROCEDURE DumpInline(fOp: Integer; InlineCode: InlinePtr);                 {!02-06-84 start}

      VAR
         N: Integer;
         p: InlinePtr;

      BEGIN {DumpInline}
        Lout(252 {INLINE} );
        Lout(Ord(fOp = 176 {UFUNCALL} ));

        N := 0; p := InlineCode;
        WHILE p <> NIL DO {count number of words}
          BEGIN {count number of words}
          N := N + 1; p := p^.NextInlineWord;
          END; {counting}

        Lout2(N); {nbr of words to follow}

        WHILE InlineCode <> NIL DO
          BEGIN
          Lout2(InlineCode^.InlineWord);
          InlineCode := InlineCode^.NextInlineWord;
          END;
      END; {DumpInline}                                                        {!02-06-84 end}

    PROCEDURE DumpCCall(StackSpace: Integer; IdType: pT;                       {!03-29-84}
                        fOp, fLev, RtnNo: Integer; fUserName: Alfa);

      VAR
        lExt: pExtRec;

      BEGIN {DumpCCall}
        Lout(251 {CCALL} );
        IF fOp <> 176 {UFUNCALL} THEN
          Lout(0)
        ELSE IF IdType = RealPtr THEN
          Lout(8)
        ELSE
          Lout(4);
        lExt := FindExt(fUserName, RtnNo, fLev);
        Lout2(lExt^.ExtNo);
        Lout2(StackSpace);
      END; {DumpCCall}                                                         {!03-29-84}

    PROCEDURE DumpSuper(fOp: Integer);

      VAR
        lExt: pExtRec;
        CallName: Alfa;
        i: Integer;

      BEGIN {DumpSuper}
        CallName := '%_SUPER ';
        lExt := FindExt(CallName, - 1, 1);
        Lout(fOp);
        Lout2(lExt^.ExtNo);
      END; {DumpSuper}                                                        {!C}

    PROCEDURE OutCnst(fValu: Valu; FType: pT);

      VAR
        i, lSize, j, Len, k, Bit, Bits: Integer;
        lStr: StrValType;
        lSet: SetValType;
        c: PACKED ARRAY [0..7] OF Char;

      BEGIN {OutCnst}
        lSize := FullBytes(FType);
        CASE FType^.Form OF
          SCALAR, SUBRANGE:
                     BEGIN
                     IF CompTypes(FType, RealPtr) THEN
                       BEGIN
                       MoveLeft(fValu.Rvalu, c, 4);
                       Lout(26 {CNST4} );
                       FOR i := 0 TO 3 DO Lout(Ord(c[i]));
                       END
                     ELSE
                       OutIntCnst(fValu.Ivalu, lSize);
                     END;
          ARRAYS, STRINGS, SCONST:
                     BEGIN
                     IF FType^.Form = ARRAYS THEN
                       Lout(29 {PAOCNST} )
                     ELSE
                       Lout(28 {STRCNST} );
                     Len := fValu.SvaluLen; Lout(Len); j := 0;
                     lStr := fValu.Svalu;
                     FOR i := 1 TO Len DO
                       BEGIN
                       IF j = 8 THEN
                         BEGIN
                         lStr := lStr^.Next; j := 0;
                         END;
                       j := j + 1; Lout(Ord(lStr^.StrPart[j]));
                       END;
                     END;
          SETS:      BEGIN
                     Lout(30 {SETCNST} ); Len := (fValu.MaxSetEl DIV 16 + 1) * 2;
                     Lout(Len);
                     j := 0; lSet := fValu.SetValu;
                     FOR i := 1 TO Len DO
                       BEGIN
                       IF j = 32 THEN
                         BEGIN
                         lSet := lSet^.NextSet; j := 0;
                         END;
                       Bits := 0; Bit := 1;
                       FOR k := j TO j + 7 DO
                         BEGIN
                         IF k IN lSet^.SetVal THEN Bits := Bits + Bit;
                         Bit := Bit + Bit;
                         END;
                       j := j + 8; Lout(Bits);
                       END;
                     END;
        END;
      END; {OutCnst}

    PROCEDURE LocalName(VAR FName: Alfa; N: Integer);

      VAR
        i: Integer;

      BEGIN {LocalName}
        FName[1] := '$';
        FOR i := 2 TO 8 DO
          BEGIN
          FName[i] := Chr(Ord('0') + N MOD 10); N := N DIV 10;
          END;
      END; {LocalName}

    PROCEDURE Expression(fExpr: pN);
      FORWARD;

    PROCEDURE DumpUCall(fProc, FArgs, fClVar, OrigfClVar: pN; SuperpT: pT);    {!12-27-83}
      FORWARD;                                                                 {!C}

    PROCEDURE DumpSfCall(fProc, pArgs: pN);
      FORWARD;

    PROCEDURE Selector(fVarb: pN);

      VAR
        Op, lLev, lOffset, lSize, Lo, Hi: Integer;
        Ch: Char;
        lExt: pExtRec;
        WasVarParm: Boolean;                                                   {!OPT!}
        LocArg: pN;                                                            {!OPT!}
        c: PACKED ARRAY [0..7] OF Char;

      BEGIN {Selector}
        WITH fVarb^ DO
          CASE Node OF
            IDENTNODE: CASE Class OF
                         CONSTS:    OutCnst(ValueOf, IdType);
                         FUNC, {For formal procedure and}
                         PROC, {function parameters only}
                         VARS:      BEGIN
                                    IF Class = VARS THEN
                                      BEGIN
                                      lOffset := Voff; lLev := Vlev;
                                      IF Vkind = INDRCT THEN Lout(12 {UPARROW} );
                                      END
                                    ELSE IF PFdecl = FORMAL THEN
                                      BEGIN
                                      lOffset := PFOff; lLev := PFlev;
                                      END
                                    ELSE
                                      BEGIN
                                      lOffset := ParmBytes; lLev := PFlev + 1;
                                      END;
                                    IF lLev = 1 THEN
                                      Op := 1 {GLOBAL}
                                    ELSE IF lLev = Level THEN
                                      Op := 2 {LOCAL}
                                    ELSE IF lLev < 0 THEN
                                      BEGIN
                                      Op := - lLev;                            {!IU!}
                                      FindUnit(Op);                            {!IU!}
                                      IF Op IN IntrinSet THEN                  {!IU!}
                                        BEGIN                                  {!IU!}
                                        Lout(15 {Record Field} );              {!IU!}
                                        Lout2(lOffset);                        {!IU!}
                                        Lout(12 {Dereference} );               {!IU!}
                                        Lout(4 {COMMON} );                     {!IU!}
                                        lOffset := 0;                          {!IU!}
                                        END                                    {!IU!}
                                      ELSE                                     {!IU!}
                                        Lout(4 {COMMON} );                     {!IU!}
                                      END
                                    ELSE
                                      BEGIN
                                      Lout(3 {INTERM} ); Op := Level - lLev;
                                      END;
                                    Lout(Op); Lout2(lOffset);
                                    END;
                         FIELD: {Error!} ;
                       END; {case}
            REGISTER:  BEGIN                                                   {!OPT!}
                       Lout(5 {REGISTER} );                                    {!OPT!}
                       Lout(Reg);                                              {!OPT!}
                       Lout(Load);                                             {!OPT!}
                       Lout(LoadSize);                                         {!OPT!}
                       IF LoadSize <> 0 THEN Expression(LoadExpr);             {!OPT!}
                       END;                                                    {!OPT!}
            UNNODE:    BEGIN                                                   {!OPT!}
                       IF UnOp = 4 {INTRINSIC UNIT BASE} THEN                  {!OPT!}
                         BEGIN                                                 {!OPT!}
                         FindUnit(UnSubOp);                                    {!OPT!}
                         Lout(4 {COMMON} );                                    {!OPT!}
                         Lout(UnSubOp); Lout2(0);                              {!OPT!}
                         END                                                   {!OPT!}
                       ELSE                                                    {!OPT!}
                         BEGIN                                                 {!OPT!}
                         IF UnOp <> 22 {ADDRESS} THEN Lout(UnOp);              {!OPT!}
                         IF (UnOp = 62 {EXTUFLD} ) OR                          {!OPT!}
                            (UnOp = 63 {EXTSFLD} ) OR                          {!OPT!}
                            (UnOp = 43 {WITHREC} ) THEN                        {!OPT!}
                           Lout(UnSubOp);                                      {!OPT!}
                         IF UnOp = 22 {ADDRESS} THEN                           {!OPT!}
                           IF UnSubOp = 0 THEN                                 {!OPT!}
                             BEGIN {remove @...^}                              {!OPT!}
                             WasVarParm := False;                              {!OPT!}
                             LocArg := UnArg;                                  {!OPT!}
                             IF UnArg^.Node = UNNODE THEN                      {!OPT!}
                               BEGIN                                           {!OPT!}
                               IF UnArg^.UnOp = 12 {^} THEN                    {!OPT!}
                                 LocArg := UnArg^.UnArg                        {!OPT!}
                               ELSE                                            {!OPT!}
                                 Lout(22);                                     {!OPT!}
                               END                                             {!OPT!}
                             ELSE IF (UnArg^.Node = IDENTNODE) AND             {!OPT!}
                                     (UnArg^.Class = VARS) AND                 {!OPT!}
                                     (UnArg^.Vkind = INDRCT) THEN              {!OPT!}
                               BEGIN                                           {!OPT!}
                               WasVarParm := True;                             {!OPT!}
                               UnArg^.Vkind := DRCT;                           {!OPT!}
                               END                                             {!OPT!}
                             ELSE                                              {!OPT!}
                               Lout(22);                                       {!OPT!}
                             Selector(LocArg);                                 {!OPT!}
                             IF WasVarParm THEN UnArg^.Vkind := INDRCT;        {!OPT!}
                             END                                               {!OPT!}
                           ELSE                                                {!OPT!}
                             BEGIN                                             {!OPT!}
                             IF UnArg^.PFdecl = FORMAL THEN                    {!OPT!}
                               BEGIN {parametric routine!}                     {!OPT!}
                               {PFOFF+4(A6)}                                   {!OPT!}
                               Lout(2); {local}                                {!OPT!}
                               Lout2(UnArg^.PFOff + 4);                        {!OPT!}
                               END                                             {!OPT!}
                             ELSE                                              {!OPT!}
                               BEGIN                                           {!OPT!}
                               Lout(UnOp);                                     {!OPT!}
                               lExt := FindExt(UnArg^.Name, UnArg^.RtnNo,      {!OPT!}
                                               UnArg^.PFlev);                  {!OPT!}
                               Lout(UnSubOp); Lout2(lExt^.ExtNo);              {!OPT!}
                               END;                                            {!OPT!}
                             END                                               {!OPT!}
                         ELSE IF (UnOp = 12 {^} ) THEN                         {!OPT!}
                           Expression(UnArg)                                   {!5-24-83,func^}
                         ELSE IF (UnOp <> 43 {WITHREC} ) THEN Selector(UnArg);
                         END;                                                  {!OPT!}
                       END;
            BINNODE:   BEGIN
                       IF BinOp = 15 {FIELD} THEN
                         BEGIN
                         Lout(15); Lout2(RightArg^.FOff); Selector(LeftArg);
                         END
                       ELSE IF BinOp = 12 {Binary ^} THEN                      {!OPT!}
                         BEGIN                                                 {!OPT!}
                         Lout(15 {.} );                                        {!OPT!}
                         Lout2(BinSubOp {offset} );                            {!OPT!}
                         Lout(12 {^} );                                        {!OPT!}
                         Expression(LeftArg {address base} );                  {!OPT!}
                         END                                                   {!OPT!}
                       ELSE IF (BinOp >= 32) and (Binop <= 34) {inline assign} THEN
                         BEGIN
                         Lout(Binop); Lout(BinSubop);
                         Expression(Leftarg); Expression(Rightarg);
                         END;
                       END;
            TRINODE:   BEGIN
                       IF TriOp = 16 {INDEX} THEN
                         BEGIN
                         IF TriPt^.Form = ARRAYS THEN
                           BEGIN
                           lSize := FullBytes(TriPt^.ArrayOf);
                           GetBounds(TriPt^.IndexedBy, Lo, Hi);
                           IF TriPt^.BitPacked THEN
                             Op := 21
                           ELSE IF lSize = 1 THEN
                             Op := 16
                           ELSE IF lSize = 2 THEN
                             Op := 17
                           ELSE IF lSize = 4 THEN
                             Op := 18
                           ELSE IF lSize = 8 THEN
                             Op := 19
                           ELSE
                             Op := 20;
                           Lout(Op);
                           IF Op = 20 THEN
                             Lout2(lSize)
                           ELSE IF Op = 21 THEN Lout(TriPt^.BitsPerEl);
                           END
                         ELSE
                           BEGIN {form = STRINGS}
                           Lo := 0; Lout(21); Lout(8);
                           END;
                         Lout2(Lo); Selector(Tri1); Expression(Tri2);
                         END
                       ELSE IF TriOp = 184 {METHODCALL} THEN                   {!C}
                         DumpUCall(TripN, Tri2, Tri1, OrigTri1, TriSuper);
                       END;
            CSTNODE:   OutCnst(CstValu, CstType);
            ASGNNODE:  BEGIN
                       Lout(AsgnOp); Lout(3);
                       Expression(AsgnpN); Selector(AsgnVar); Expression(AsgnExpr);
                       END;
          END; {case}
      END; {Selector}

    PROCEDURE Expression{fExpr: pN};

      VAR
        Lo, Hi: Integer;

      BEGIN {Expression}
        WITH fExpr^ DO
          CASE Node OF
            REGISTER,                                                          {!OPT!}
            IDENTNODE: Selector(fExpr);
            UNNODE:    IF UnOp IN [4 {INTRINSIC BASE} , 12..14 {Up Arrows} ,
                          22 {ADDRESS} ,                                      {!OPT!}
                          43 {WITHREC} , 62 {EXTUFLD} , 63 {EXTSFLD} ] THEN
                         Selector(fExpr)
                       ELSE
                         BEGIN
                         Lout(UnOp);
                         IF (UnOp <> 23 {NIL} ) AND (UnOp <> 31 {NULLSET} ) THEN
                           BEGIN
                           IF UnOp = 168 {SING} THEN
                             Lout(UnSubOp)
                           ELSE IF UnOp = 170 {AJDSET} THEN Lout2(UnSubOp);
                           Expression(UnArg);
                           END;
                         END;
            BINNODE:   IF BinOp IN [12 {Binary ^} , 15 {RFIELD} , 16..21 {Array
                            Indexing} ] THEN                                  {!OPT!}
                         Selector(fExpr)                                       {!OPT!}
                       ELSE IF BinOp = 176 {UFCALL} THEN
                         DumpUCall(LeftArg, RightArg, NIL, NIL, NIL)           {!C}
                       ELSE IF BinOp = 178 {SFCALL} THEN
                         DumpSfCall(LeftArg, RightArg)
                       ELSE
                         BEGIN
                         Lout(BinOp);
                         IF (BinOp >= 150 {PAOCLT} ) AND (BinOp <=
                            155 {PAOCNE} ) THEN
                           BEGIN
                           Lout(BinSubOp); Lout(BinSubOp);
                           END
                         ELSE IF (BinOp >= 160 {UNION} ) AND (BinOp <= 169 {SETRANGE} )
                                 OR (BinOp >= 32) AND (BinOp <= 34) {inline assign} THEN
                           Lout(BinSubOp);
                         IF BinOp = 46 {RNGCHK} THEN
                           BEGIN
                           GetBounds(LeftPt, Lo, Hi);
                           Lout2(Lo); Lout2(Hi);
                           END
                         ELSE IF BinOp = 47 {SRNGCHK} THEN
                           Lout(BinSubOp)
                         ELSE
                           Expression(LeftArg);
                         Expression(RightArg);
                         END;
            TRINODE:   Selector(fExpr);
            CSTNODE:   OutCnst(CstValu, CstType);
            ASGNNODE:  Selector(fExpr);
          END; {case}
      END; {Expression}

    PROCEDURE ArgAddr(VAR ArgList: pN);

      BEGIN {ArgAddr}
        IF ArgList <> NIL THEN
          BEGIN
          Lout(183 {REFPARM} ); Expression(ArgList^.LeftArg);
          {Would be selector except for COPY and CONCAT!}
          ArgList := ArgList^.RightArg;
          END
        ELSE
          Error(1000);
      END; {ArgAddr}

    PROCEDURE ArgVal2(VAR ArgList: pN);

      BEGIN {ArgVal2}
        IF ArgList <> NIL THEN
          BEGIN
          Lout(185 {VALPRM2} ); Expression(ArgList^.LeftArg);
          ArgList := ArgList^.RightArg;
          END
        ELSE
          Error(1001);
      END; {ArgVal2}

    PROCEDURE ArgVal4(VAR ArgList: pN);

      BEGIN {ArgVal4}
        IF ArgList <> NIL THEN
          BEGIN
          Lout(186 {VALPRM4} ); Expression(ArgList^.LeftArg);
          ArgList := ArgList^.RightArg;
          END
        ELSE
          Error(1002);
      END; {ArgVal4}

    PROCEDURE DumpSfCall{fproc,pargs: pn};

      VAR
        Key, lSize, N, lOp: Integer;
        lpN: pN;

      BEGIN {DumpSfCall}
        Key := fProc^.Key;
        IF Key IN [2, 4..8, 12..13, 15, 17, 20..25, 27..31, 33, 34] THEN
          BEGIN
          IF Key IN [2, 4, 7..8, 13, 15] THEN
            lSize := 4
          ELSE IF Key IN [5, 6, 34] THEN
            lSize := 129
          ELSE IF Key IN [20, 23..25, 28..30, 33] THEN
            lSize := 130
          ELSE IF Key IN [12, 17, 27, 31] THEN
            lSize := 132
          ELSE
            lSize := 0;
          Lout(190 {PRMLIST} ); Lout(182 {FCTNRES} ); Lout(lSize);
          END;
        CASE Key OF                                                            {!}{[@=4]}
          01, {ABS}
          14: {SQR}
              BEGIN
              Lout(pArgs^.BinOp); Expression(pArgs^.LeftArg);
              END;
          02, {ARCTAN}
          04, {COS}
          07, {EXP}
          08, {LN}
          12, {ROUND}
          13, {SIN}
          15, {SQRT}
          17: {TRUNC}
              ArgVal4(pArgs);
          05, {EOF}
          06, {EOLN}
          34: {KEYPRESS}
              ArgAddr(pArgs);
          09: {ODD}
              BEGIN
              Lout(111 {ODD} ); Expression(pArgs^.LeftArg);
              END;
          11, {PRED}
          16: {SUCC}
              BEGIN
              IF Key = 16 THEN
                lOp := 64 {ADD2}
              ELSE
                lOp := 66; {ADD4}
              lSize := pArgs^.BinSubOp;
              IF lSize > 2 THEN lOp := lOp + 1; {2-->4}
              Lout(lOp); Expression(pArgs^.LeftArg); OutIntCnst(1, lSize);
              END;
          03, {CHR}
          10, {ORD}
          18, {POINTER}
          26, {SIZEOF}
          32, {ORD4}
          35: {THISCLASS}                                                      {!01-07-84}
              Expression(pArgs^.LeftArg);
          19: {LENGTH}
              IF pArgs^.LeftArg^.Node = CSTNODE THEN
                OutIntCnst(pArgs^.LeftArg^.CstValu.SvaluLen, 2)
              ELSE
                BEGIN
                Lout(62 {EXTSFLD} ); Lout(136 {8-bits:8-bit-offset} );
                Expression(pArgs^.LeftArg);
                END;
          20: {POS}
              BEGIN
              ArgAddr(pArgs); ArgAddr(pArgs);
              END;
          21: {CONCAT}
              BEGIN
              N := 0;
              WHILE pArgs <> NIL DO
                BEGIN
                lpN := pArgs^.LeftArg; ArgAddr(pArgs); N := N + 1;
                END;
              Lout(185 {VALPRM2} ); OutIntCnst(N - 1, 2);
              Lout(178 {STDFCAL} ); Lout(21);
              {Location of the result - Should be first ref parameter}
              Expression(lpN);
              END;
          22: {COPY}
              BEGIN
              ArgAddr(pArgs); ArgVal2(pArgs); ArgVal2(pArgs);
              lpN := pArgs^.LeftArg; ArgAddr(pArgs);
              Lout(178 {STDFCAL} ); Lout(22);
              {Location of the result - Should be first ref parameter}
              Expression(lpN);
              END;
          23, {BLOCKREAD}
          24: {BLOCKWRITE}
              BEGIN
              ArgAddr(pArgs); ArgAddr(pArgs); ArgVal2(pArgs);
              IF pArgs <> NIL THEN
                ArgVal2(pArgs)
              ELSE
                BEGIN
                Lout(185 {VALPRM2} ); OutIntCnst( - 1, 2);
                END;
              END;
          25, {IORESULT}
          31, {MEMAVAIL}
          33: {HEAPRESULT} ;
          27: {PWROFTEN}
              ArgVal2(pArgs);
          28, {SCANEQ}
          29: {SCANNE}
              BEGIN
              ArgVal2(pArgs); ArgVal2(pArgs); ArgAddr(pArgs);
              END;
          30: {UNITBUSY}
              ArgVal2(pArgs);
          36: {INCLASS}                                                        {!01-07-84}
              BEGIN
              fProc := NIL;
              IF pArgs <> NIL THEN
                IF pArgs^.RightArg <> NIL THEN
                  IF pArgs^.RightArg^.BinSubOp = Ord(IDENTNODE) THEN
                    fProc := InObCpPtr {%_INOBCP}
                  ELSE
                    fProc := InObCnPtr; {%_INOBCN}
              IF fProc <> NIL THEN DumpUCall(fProc, pArgs, NIL, NIL, NIL);
              END;
        END; {case}
        IF Key IN [2, 4..8, 12..13, 15, 17, 20, 23..25, 27..31, 33, 34] THEN
          BEGIN
          Lout(178 {STDFCAL} ); Lout(Key);
          END;
      END; {DumpSfCall}
                                                                               {!}{[f-]}
    PROCEDURE DumpUCall{fProc: pN; proc to be called
                        fArgs: pN; its arguments
                        fClVar: pN; SELF of calling class (NIL for Create)
                        OrigfClVar: pN; original fClVar uneffected by opt
                        SuperpT: pT target class};                             {!12-27-83}{[f+]}

      VAR
        Formals, Actuals: pN;
        N, lOp, lOff, lLen, StackSpace: Integer;
        Op, lOffset: Integer;                                                  {!C}
        Ccall: Boolean;                                                        {!03-29-84}
        lName: Alfa;                                                           {!12-27-83}

      PROCEDURE ReversePtrs(VAR Formals, Actuals: pN);                         {!03-29-84}

        VAR
          Curr, Nxt: pN;

        BEGIN {ReversePtrs - params for C calls are generated last first}
          Curr := Formals; Formals := NIL;
          WHILE Curr <> NIL DO
            BEGIN
            Nxt := Curr^.Next; Curr^.Next := Formals;
            Formals := Curr; Curr := Nxt;
            END;

          Curr := Actuals; Actuals := NIL;
          WHILE Curr <> NIL DO
            BEGIN
            Nxt := Curr^.RightArg; Curr^.RightArg := Actuals;
            Actuals := Curr; Curr := Nxt;
            END;
        END; {ReversePtrs}                                                     {!03-29-84}

      BEGIN {DumpUCall}
        Lout(190); {BPARMLST}
        WITH fProc^ DO
          BEGIN
          Ccall := (PFdecl = CDECL);                                           {!03-29-84}
          IF Class = FUNC THEN
            BEGIN
            IF NOT Ccall THEN                                                      {!03-29-84}
              BEGIN
              Lout(182 {FCTNRES} ); Lout(FullBytes(IdType));
              END;
            lOp := 176; {UFUNCALL}
            END
          ELSE
            lOp := 177; {UPROCALL}
          IF Ccall THEN ReversePtrs(PFarglist, FArgs);                         {!03-29-84}
          Formals := PFargList; Actuals := FArgs; StackSpace := 0;             {!03-29-84}
          WHILE Formals <> NIL DO
            BEGIN
            IF Formals^.Class = VARS THEN
              BEGIN
              IF Formals^.Vkind <> DRCT THEN
                Lout(183 {REFPARM} )
              ELSE
                BEGIN {DRCT}
                N := FullBytes(Formals^.IdType);
                IF Formals^.IdType^.Form = SETS THEN
                  IF Ccall THEN                                                {!03-29-84}
                    BEGIN                                                      {!03-29-84}
                    Lout(188 {LRGVPRM} ); Lout2(N);                            {!03-29-84}
                    END                                                        {!03-29-84}
                  ELSE                                                         {!03-29-84}
                    BEGIN
                    Lout(189 {SETVPRM} ); Lout(N);
                    END
                ELSE IF N > 4 THEN
                  BEGIN
                  Lout(188 {LRGVPRM} ); Lout2(N);
                  END
                ELSE
                  BEGIN
                  IF Ccall THEN                                                {!03-29-84}
                    IF Formals^.IdType <> RealPtr THEN                         {!03-29-84}
                      Lout(186 {VPARAM4} ) {C wants all LongInt integers}      {!03-29-84}
                    ELSE                                                       {!03-29-84}
                      BEGIN {C wants all dbl prec. reals}                      {!03-29-84}
                      Lout(187 {VPARAM8} );                                    {!03-29-84}
                      StackSpace := StackSpace + 4;                            {!03-29-84}
                      END                                                      {!03-29-84}
                  ELSE IF N = 1 THEN
                    Lout(184 {VPARAM1} )
                  ELSE IF N = 2 THEN
                    Lout(185 {VPARAM2} )
                  ELSE
                    Lout(186 {VPARAM4} );
                  END;
                END; {DRCT}
              Expression(Actuals^.LeftArg);
              END
            ELSE
              WITH Actuals^.LeftArg^ DO
                IF PFdecl = FORMAL THEN {Passing formal as formal}
                  BEGIN
                  Lout(187 {VPARAM8} ); Selector(Actuals^.LeftArg);
                  END
                ELSE
                  DumpJSR(191 {PFPARM} , PFlev + 1, RtnNo, Name);
            Formals := Formals^.Next; Actuals := Actuals^.RightArg;
            StackSpace := StackSpace + 4;                                      {!03-29-84}
            END; {while}
          IF Ccall THEN ReversePtrs(PFarglist, FArgs);                         {!03-29-84}
          IF PFdecl = FORMAL THEN
            BEGIN
            IF Class = PROC THEN
              lOp := 181 {PPCALL}
            ELSE
              lOp := 180; {PFCALL}
            Lout(lOp); Selector(fProc);
            END
          ELSE IF (PFdecl = METHDECL) OR (PFdecl = FORWMETHDECL) THEN          {!C}
            BEGIN
            IF fClVar <> NIL THEN
              BEGIN
              Lout(186 {VALPRM4} );
              Expression(fClVar);
              END;
            IF SuperpT = NIL THEN {regular method call}                        {!12-27-83}
              DumpMethod(lOp, MethodNo, MethodLevel)                           {!12-27-83}
            ELSE IF MethodNo = 0 {CREATE} THEN                                 {!12-27-83}
              BEGIN                                                            {!12-27-83}
              IF SuperpT^.ItsId = NIL THEN                                     {!12-27-83}
                lName := 'No Name!'                                            {!12-27-83}
              ELSE                                                             {!12-27-83}
                lName := SuperpT^.ItsId^.Name;                                 {!12-27-83}
              DumpJSR(lOp, PFlev + 1, RtnNo, lName);                           {!12-27-83}
              END                                                              {!12-27-83}
            ELSE                                                               {!12-27-83}
              BEGIN
              Lout(183 {REFPARM} );
              Op := - OrigfClVar^.IdType^.MethodLev;                           {!IU! 12-27-83}
              lOffset := OrigfClVar^.IdType^.MethodOff;                        {!IU! 12-27-83}
              FindUnit(Op);                                                    {!IU!}
              IF Op IN IntrinSet THEN                                          {!IU!}
                BEGIN                                                          {!IU!}
                Lout(15 {Record Field} );                                      {!IU!}
                Lout2(lOffset);                                                {!IU!}
                Lout(12 {Dereference} );                                       {!IU!}
                Lout(4 {COMMON} );                                             {!IU!}
                lOffset := 0;                                                  {!IU!}
                END                                                            {!IU!}
              ELSE                                                             {!IU!}
                Lout(4 {COMMON} );                                             {!IU!}
              Lout(Op);
              Lout2(lOffset);
              Lout(185 {VPARAM2} );
              OutIntCnst((OrigfClVar^.IdType^.ClassLevel - SuperpT^.ClassLevel)
                          DIV 2, WORD);                                        {!01-03-84}
              Lout(185 {VPARAM2} );                                            {!12-27-83}
              OutIntCnst(MethodLevel * 256 + MethodNo, WORD);                  {!12-27-83}
              DumpSuper(lOp);                                                  {!12-27-83}
              END;
            END                                                                {!C}
          ELSE IF PFdecl = INLINEDECL THEN                                     {!02-06-84}
            DumpInline(lOp, InlineCode)                                        {!02-06-84}
          ELSE IF Ccall THEN                                                   {!03-29-84}
            DumpCCall(StackSpace, IdType, lOp, 2, RtnNo, Name)                 {!03-29-84}
          ELSE
            DumpJSR(lOp, PFlev + 1, RtnNo, Name);
          END; {with}
      END; {DumpUCall}

    PROCEDURE DumpStmt(fStmt: pStmt);

      VAR
        g: Boolean;
        IsPtr, Lo, Hi, Lab1, Lab2, lOp, ThisLabNo, ExitLabNo, ElseLabNo, USED,
        Unused, i, Len: Integer;
        TrueLn: LongInt;
        Stmt1, Stmt2: pStmt;

      PROCEDURE OutGoto(fLabLev: Integer; pLab: pLabRec);

        BEGIN {OutGoto}
          IF fLabLev = Level THEN
            BEGIN
            Lout(198 {JMPLULB} ); Lout2(pLab^.LabelNo);
            Lout2(pLab^.ILabelNo);
            END
          ELSE
            BEGIN
            Lout(199 {JMPGULB} ); Lout(fLabLev);
            IF pLab^.GlobRefNo < 0 THEN
              BEGIN
              pLab^.GlobRefNo := LocProcNo;
              LocProcNo := LocProcNo + 1;
              END;
            Lout2(pLab^.GlobRefNo);
            END;
        END; {OutGoto}

      PROCEDURE DumpCallStmt(fStmt: pStmt);

        PROCEDURE ReadWrite(fStmt: pStmt);

          VAR
            pArgs, FileArg, Colon1, Colon2, Arg: pN;
            lOp, lOp2, lSubOp, lSize: Integer;

          BEGIN {ReadWrite}
            WITH fStmt^, ProcpN^ DO
              BEGIN
              pArgs := pArgList;
              CASE Key OF
                8, {read}
                9: {readln}
                    BEGIN
                    FileArg := pArgs^.LeftArg; pArgs := pArgs^.RightArg;
                    WHILE pArgs <> NIL DO
                      BEGIN
                      lOp := pArgs^.BinOp; Arg := pArgs^.LeftArg;
                      IF lOp <= 2 THEN
                        BEGIN
                        lSubOp := pArgs^.BinSubOp;
                        Lout(lSubOp);
                        Lout(0); {not flippable}                               {!OPT!}
                        {ASS1/2/4}
                        Selector(Arg);
                        IF (lOp = 1) AND (lSubOp <> 34 {ASS4} ) THEN
                          IF lSubOp = 33 {ASS2} THEN
                            Lout(52 {INT42} )
                          ELSE
                            Lout(53 {INT41} );
                        END;

                       {  Binop Proc. Params: Res:
                           ----- ----- -------
                             0   $R_C  ------- Val2
                             1   $R_I  ------- Val4
                             2   $R_R  ------- Val4
                             3   $R_S  Adr Siz2
                             4   $R_P  Adr Siz2     }

                      Lout(190); {BPRMLIST}
                      Lout(183 {REFPARAM} );
                      Selector(FileArg);
                      IF lOp > 2 THEN
                        BEGIN
                        Lout(183 {REFPARM} ); Selector(Arg);
                        Lout(185 {VARPRM2} );
                        OutIntCnst(pArgs^.BinSubOp, 2); {BinSubOp is actual
                                                         length}
                        END;
                      Lout(179 {STDPCAL} ); Lout(110 + lOp);
                      pArgs := pArgs^.RightArg;
                      END;
                    IF Key = 9 THEN
                      BEGIN
                      Lout(190); {BPRMLIST}
                      Lout(183 {REFPARAM} ); Selector(FileArg);
                      Lout(179 {STDPCAL} ); Lout(115 {READLN} );
                      END;
                    END;
                10, {write}
                11: {writeln}
                    BEGIN
                    FileArg := pArgs^.LeftArg; pArgs := pArgs^.RightArg;
                    WHILE pArgs <> NIL DO
                      BEGIN
                      Lout(190); {BPRMLIST}
                      Lout(183 {REFPARAM} ); Selector(FileArg);

                      {  Binop Proc. Kind Size
                          ----- ----- ---- ----
                            0   $W_C  Val.  1.
                            1   $W_B  Val.  1.
                            2   $W_I  Val.  4.
                            3   $W_E  Val.  4.
                            4   $W_F  Val.  4.
                            5   $W_S  Ref.  -
                            6   $W_P  Ref.  -   }

                      lOp := pArgs^.BinOp; Colon1 := NIL; Colon2 := NIL;
                      Arg := pArgs^.LeftArg;
                      IF (Arg^.Node = BINNODE) AND (Arg^.BinOp = 0 {COLON} ) THEN
                        BEGIN
                        Colon1 := Arg^.RightArg; Arg := Arg^.LeftArg;
                        IF (Arg^.Node = BINNODE) AND (Arg^.BinOp =
                           0 {COLON} ) THEN
                          BEGIN
                          Colon2 := Colon1; Colon1 := Arg^.RightArg;
                          Arg := Arg^.LeftArg;
                          END;
                        END;
                      IF lOp <= 4 THEN
                        BEGIN
                        CASE lOp OF
                          0:  BEGIN
                              lOp2 := 184 {VALPRM1} ; lSize := 1;
                              END;
                          1:  BEGIN
                              lOp2 := 184 {VALPRM1} ; lSize := 5;
                              END;
                          2:  BEGIN
                              lOp2 := 186 {VALPRM4} ; lSize := 8;
                              END;
                          3:  BEGIN
                              lOp2 := 186 {VALPRM4} ; lSize := 12;
                              END;
                          4:  BEGIN
                              lOp2 := 186 {VALPRM4} ; lSize := 12;
                              END;
                        END;
                        Lout(lOp2); Expression(Arg);
                        END
                      ELSE
                        BEGIN
                        Lout(183 {REFPARM} ); Expression(Arg);
                        lSize := 0;
                        {Would be selector except for COPY and CONCAT!}
                        IF lOp = 6 THEN
                          BEGIN
                          {For $W_PAOC colon1 is actual length}
                          Lout(185 {VALPRM2} );
                          Expression(Colon1); Colon1 := Colon2;
                          END;
                        END;
                      Lout(185 {VALPRM2} );
                      IF Colon1 = NIL THEN
                        OutIntCnst(lSize, 2)
                      ELSE
                        Expression(Colon1);
                      IF lOp = 4 THEN
                        BEGIN
                        Lout(185 {VALPRM2} );
                        IF Colon2 = NIL THEN
                          OutIntCnst(6, 2)
                        ELSE
                          Expression(Colon2);
                        END;
                      Lout(179 {STDPCAL} ); Lout(100 + lOp);
                      pArgs := pArgs^.RightArg;
                      END;
                    IF Key = 11 THEN
                      BEGIN
                      Lout(190); {BPRMLIST}
                      Lout(183 {REFPARAM} ); Selector(FileArg);
                      Lout(179 {STDPCAL} ); Lout(107 {WRITELN} );
                      END;
                    END;
              END;
              END; {with}
          END; {ReadWrite}

        PROCEDURE DumpStdProc(fStmt: pStmt);

          VAR
            pArgs: pN;
            SubOp, lLev: Integer;

          BEGIN {DumpStdProc}
            WITH fStmt^, ProcpN^ DO
              IF Key = 29 {EXIT} THEN
                BEGIN
                lLev := pArgList^.LeftArg^.PFlev + 1;
                OutGoto(lLev, Display[lLev].ExitLabel);
                END
              ELSE
                BEGIN
                pArgs := pArgList;
                Lout(190 {PRMLIST} );
                CASE Key OF
                  01, {NEW}
                  15, {CLOSE}
                  20, {SEEK}
                  27: {DISPOSE}
                      BEGIN
                      ArgAddr(pArgs); ArgVal2(pArgs);
                      END;
                  02, {MARK}
                  03, {RELEASE}
                  04, {GET}
                  05, {PUT}
                  12: {PAGE}
                      BEGIN
                      ArgAddr(pArgs);
                      END;
                  06, {RESET}
                  07: {REWRITE}
                      BEGIN
                      SubOp := pArgs^.BinSubOp; ArgAddr(pArgs);
                      IF pArgs <> NIL THEN
                        ArgAddr(pArgs)
                      ELSE
                        BEGIN
                        Lout(186 {VALPRM4} ); Lout(23 {NIL} );
                        END;
                      Lout(185 {VALPRM2} ); OutIntCnst(SubOp, 2);
                      END;
                  16, {DELETE}
                  24: {FILLCHAR}
                      BEGIN
                      ArgAddr(pArgs); ArgVal2(pArgs); ArgVal2(pArgs);
                      END;
                  17, {INSERT}
                  22, {MOVELEFT}
                  23: {MOVERIGHT}
                      BEGIN
                      ArgAddr(pArgs); ArgAddr(pArgs); ArgVal2(pArgs);
                      END;
                  18, {UNITREAD}
                  19, {UNITWRITE}
                  28: {UNITSTATUS}
                      BEGIN
                      ArgVal2(pArgs); ArgAddr(pArgs); ArgVal2(pArgs);
                      IF Key <= 19 THEN
                        BEGIN
                        IF pArgs = NIL THEN
                          BEGIN
                          Lout(185 {VALPRM2} ); OutIntCnst(0, 2);
                          END
                        ELSE
                          ArgVal2(pArgs);
                        IF pArgs = NIL THEN
                          BEGIN
                          Lout(185 {VALPRM2} ); OutIntCnst(0, 2);
                          END
                        ELSE
                          ArgVal2(pArgs);
                        END;
                      END;
                  21: {HALT} ;
                  25: {UNITCLEAR}
                      BEGIN
                      ArgVal2(pArgs);
                      END;
                  26: {GOTOXY}
                      BEGIN
                      ArgVal2(pArgs); ArgVal2(pArgs);
                      END;
                END; {case}
                Lout(179 {STDPCAL} ); Lout(Key);
                END;
          END; {DumpStdProc}

        BEGIN {DumpCallStmt}
          WITH fStmt^, ProcpN^ DO
            IF PFdeclKind = STANDARD THEN
              IF (Key >= 8) AND (Key <= 11) THEN
                ReadWrite(fStmt)
              ELSE
                DumpStdProc(fStmt)
            ELSE
              DumpUCall(ProcpN, pArgList, NIL, NIL, NIL);                      {!12-27-83}
        END; {DumpCallStmt}

      PROCEDURE FindLoHi(fStmt: pStmt);

        VAR
          i: Integer;
          lStmt: pStmt;
          lpInt: pIntList;

        BEGIN {FindLoHi}
          Lo := 32767; Hi := - 32767 - 1; lStmt := fStmt^.CStmtList;
          ExitLabNo := NextLabel; ElseLabNo := NextLabel;
          WHILE lStmt <> NIL DO
            WITH lStmt^ DO
              BEGIN
              lpInt := CaseVals; ThisLabNo := NextLabel;
              WHILE lpInt <> NIL DO
                WITH lpInt^ DO
                  BEGIN
                  IF IntVal > Hi THEN Hi := IntVal;
                  IF IntVal < Lo THEN Lo := IntVal;
                  lpInt := NextInt;
                  END;
              lStmt := NextStmt;
              END;
        END; {FindLoHi}

      FUNCTION CaseIsSmaller(fStmt: pStmt): Boolean;

        LABEL 1;

        VAR
          i: Integer;
          lStmt: pStmt;
          lpInt: pIntList;

        BEGIN {CaseIsSmaller}
          USED := 0; Unused := 0;
          FOR i := Lo TO Hi DO
            BEGIN
            lStmt := fStmt^.CStmtList;
            WHILE lStmt <> NIL DO
              WITH lStmt^ DO
                BEGIN
                lpInt := CaseVals;
                WHILE lpInt <> NIL DO
                  WITH lpInt^ DO
                    IF IntVal = i THEN
                      BEGIN
                      USED := USED + 1;
                      GOTO 1;
                      END
                    ELSE
                      lpInt := NextInt;
                lStmt := NextStmt;
                END;
            Unused := Unused + 1;
          1:
            END;
          {*********************************************************}
          {IF 24+6*used+2*unused < 4+10*used THEN use_case_statement}
          {*********************************************************}
          CaseIsSmaller := Unused < 2 * USED - 10;
        END; {CaseIsSmaller}

      PROCEDURE DumpCaseStmt(fStmt: pStmt);

        LABEL 1;

        VAR
          i: Integer;
          lStmt: pStmt;
          lpInt: pIntList;

        BEGIN {DumpCaseStmt}
          Lout(200 {CASEJ} ); Expression(fStmt^.CaseExpr);
          Lout(201 {CASETAB} ); Lout(0 {use a jump table} );
          Lout2(Lo); Lout2(Hi); Lout2(ElseLabNo);
          FOR i := Lo TO Hi DO
            BEGIN
            ThisLabNo := ElseLabNo; lStmt := fStmt^.CStmtList;
            WHILE lStmt <> NIL DO
              WITH lStmt^ DO
                BEGIN
                lpInt := CaseVals; ThisLabNo := ThisLabNo + 1;
                WHILE lpInt <> NIL DO
                  WITH lpInt^ DO
                    IF IntVal = i THEN
                      GOTO 1
                    ELSE
                      lpInt := NextInt;
                lStmt := NextStmt;
                END;
            ThisLabNo := ElseLabNo;
          1:
            Lout2(ThisLabNo);
            END;
          lStmt := fStmt^.CStmtList; ThisLabNo := ElseLabNo;
          WHILE lStmt <> NIL DO
            WITH lStmt^ DO
              BEGIN
              ThisLabNo := ThisLabNo + 1;
              Lout(192 {ILAB} ); Lout2(ThisLabNo);
              DumpStmt(lStmt^.ThisCase);
              Lout(193 {JMP} ); Lout2(ExitLabNo);
              lStmt := NextStmt;
              END;
          Lout(192 {ILAB} ); Lout2(ElseLabNo);
          DumpStmt(fStmt^.OtherStmt);
          Lout(192 {ILAB} ); Lout2(ExitLabNo);
          Lout(204 {ENDCASE} );
        END; {DumpCaseStmt}

      PROCEDURE DumpIfThenElse(fStmt: pStmt);

        LABEL 1;

        VAR
          i: Integer;
          lStmt: pStmt;
          lpInt: pIntList;

        BEGIN {DumpIfThenElse}
          Lout(200 {CASEJ} ); Expression(fStmt^.CaseExpr);
          Lout(201 {CASETAB} ); Lout(1 {use if then else} );
          Lout2(Lo); Lout2(Hi); Lout2(ElseLabNo); Lout2(USED);
          FOR i := Lo TO Hi DO
            BEGIN
            ThisLabNo := ElseLabNo; lStmt := fStmt^.CStmtList;
            WHILE lStmt <> NIL DO
              WITH lStmt^ DO
                BEGIN
                lpInt := CaseVals; ThisLabNo := ThisLabNo + 1;
                WHILE lpInt <> NIL DO
                  WITH lpInt^ DO
                    IF IntVal = i THEN
                      BEGIN
                      Lout2(i); Lout2(ThisLabNo);
                      GOTO 1;
                      END
                    ELSE
                      lpInt := NextInt;
                lStmt := NextStmt;
                END;
          1:
            END;
          lStmt := fStmt^.CStmtList; ThisLabNo := ElseLabNo;
          WHILE lStmt <> NIL DO
            WITH lStmt^ DO
              BEGIN
              ThisLabNo := ThisLabNo + 1;
              Lout(192 {ILAB} ); Lout2(ThisLabNo);
              DumpStmt(lStmt^.ThisCase);
              Lout(193 {JMP} ); Lout2(ExitLabNo);
              lStmt := NextStmt;
              END;
          Lout(192 {ILAB} ); Lout2(ElseLabNo);
          DumpStmt(fStmt^.OtherStmt);
          Lout(192 {ILAB} ); Lout2(ExitLabNo);
          Lout(204 {ENDCASE} );
        END; {DumpIfThenElse}

      FUNCTION VarInExpr(v, e: pN): Boolean; {v assumed to be a REGISTER}

        VAR
          r: Boolean;

        BEGIN {VarInExpr}
          r := False;
          {should the passer of nil be tracked down?}
          IF e <> NIL THEN
            CASE e^.Node OF                                                    {!}{[@=12]}
              IDENTNODE:  r := v = e;
              UNNODE:     IF e^.UnOp IN [12 {^} , 15 {.} , 43 {WITHFLD} ] THEN
                            r := VarInExpr(v, e^.UnArg)
                          ELSE IF e^.UnOp IN [23 {NIL} , 31 {NULLSET} ] THEN
                            r := False
                          ELSE
                            r := VarInExpr(v, e^.UnArg);
              BINNODE:    IF e^.BinOp IN [46 {RNGCHK} , 47 {SRNGCHK} ] THEN
                            r := VarInExpr(v, e^.RightArg)
                          ELSE
                            r := VarInExpr(v, e^.LeftArg) OR VarInExpr(v,
                                 e^.RightArg);
              TRINODE:    IF e^.TriOp = 16 {INDEX} THEN
                            r := VarInExpr(v, e^.Tri1) OR VarInExpr(v, e^.Tri2)
                          ELSE
                            r := False;
              CSTNODE:    r := False;
              REGISTER:   BEGIN
                          r := v^.Reg = e^.Reg;
                          IF e^.LoadExpr <> NIL THEN
                            r := r OR VarInExpr(v, e^.LoadExpr);
                          END;
              ASGNNODE:   r := VarInExpr(v, e^.AsgnVar) OR VarInExpr(v, e^.AsgnExpr) OR
                          VarInExpr(v, e^.AsgnpN);
            END; {case}
          VarInExpr := r;
        END; {VarInExpr}

      BEGIN {DumpStmt}
        WHILE fStmt <> NIL DO
          WITH fStmt^ DO
            BEGIN
            IF Pass2Listing THEN                                               {!02-17-84 start}
              IF StmtNumb <> LastLine THEN
                IF StmtNumb <> 0 THEN
                  BEGIN
                  IF StmtNumb < 0 THEN
                    BEGIN
                    TrueLn := StmtNumb;
                    TrueLn := TrueLn + 65536; {integers > 32767}
                    IF TrueLn > MAXLNUM THEN
                      BEGIN
                      AsmListOk := False; {no more line nbr info for Gen}
                      Pass2Listing := False; {but let Gen give the error}
                      END;
                    END;

                  IF Pass2Listing THEN
                    BEGIN
                    IF NewListFile THEN
                      BEGIN
                      Lout(205 {line number} );  Lout2( - 1 {listing file} );
                      WITH ListingFCBP^ DO
                        BEGIN
                        Len := Length(Filename);
                        Lout(Len);
                        FOR i := 1 TO Len DO Lout(Ord(Filename[i]));
                        END;
                      NewListFile := False;
                      END;

                    IF NewAsmStatus THEN
                      BEGIN
                      Lout(205 {line number} ); Lout2( - 2 {new Asm status} );
                      Lout(Ord(ShowAsmCode));
                      NewAsmStatus := False;
                      END;

                    Lout(205 {line number} );
                    Lout2(StmtNumb);
                    LastLine := StmtNumb;
                    END;
                  END;                                                         {!02-17-84 end}

            CASE StmtOp OF
              BEGINST:    DumpStmt(SubSt);

              ASSIGNST:   BEGIN
                          g := True;
                          IF (AssOp = 34) AND Flippable THEN
                            IF AssVar^.Node = REGISTER THEN
                              IF (AssVar^.Reg >= A1st) AND (AssVar^.Reg <=
                                 Anth) THEN
                                WITH AssExpr^ DO
                                  IF Node = BINNODE THEN
                                    IF BinOp = 65 THEN
                                      IF RightArg^.Node = UNNODE THEN
                                        IF RightArg^.UnOp = 49 THEN
                                          WITH LeftArg^ DO
                                            IF Node = BINNODE THEN
                                              IF BinOp = 178 THEN {sfcall}
                                                WITH LeftArg^ DO
                                                  IF (Node = IDENTNODE) AND (Key =
                                                     10 {ORD} ) THEN
                                                    IF NOT VarInExpr(AssVar,
                                                       AssExpr^.RightArg) THEN
                                                      g := False;
                          IF g THEN
                            BEGIN
                            Lout(AssOp);
                            IF (AssOp >= 32) AND (AssOp <= 35) THEN
                              BEGIN {1/2/4/8 byte assign}
                              IF Flippable THEN
                                BEGIN {evaluate lhs var after rhs expr}
                                Lout(1);
                                Expression(AssExpr);
                                Expression(AssVar);
                                END
                              ELSE {must evaluate lhs var first}
                                BEGIN
                                Lout(0);
                                Expression(AssVar);
                                Expression(AssExpr);
                                END;
                              END
                            ELSE
                              BEGIN
                              IF AssOp = 36 {MULTASS} THEN
                                BEGIN
                                Lout(0); Lout2(AssSubOp);
                                END
                              ELSE IF (AssOp = 37 {SETASS} ) OR (AssOp =
                                      39 {STRASS} ) OR (AssOp = 41 {ADDTO} ) OR
                                      (AssOp = 42 {SUBFROM} ) THEN
                                Lout(AssSubOp)
                              ELSE IF AssOp = 40 {PAOCASS} THEN
                                BEGIN
                                Lout(AssSubOp); Lout(AssSubOp);
                                END;
                              Expression(AssVar);
                              Expression(AssExpr);
                              END;
                            END
                          ELSE
                            BEGIN
                            New(Stmt1, ASSIGNST);
                            Stmt1^ := fStmt^;
                            Stmt1^.AssExpr := AssExpr^.LeftArg^.RightArg^.LeftArg;
                            Stmt1^.NextStmt := NIL;
                            New(Stmt2, ASSIGNST);
                            Stmt2^ := fStmt^;
                            Stmt2^.AssOp := 41;
                            Stmt2^.AssSubOp := 2;
                            Stmt2^.AssExpr := AssExpr^.RightArg^.UnArg;
                            Stmt2^.NextStmt := NIL;
                            DumpStmt(Stmt1);
                            DumpStmt(Stmt2);
                            END;
                          END;
              IFST:       BEGIN
                          g := True;
                          IF ThenSt <> NIL THEN
                            WITH ThenSt^ DO
                              IF StmtOp = GOTOST THEN
                                IF LabLev = Level THEN
                                  BEGIN
                                  g := False;
                                  Lout(195 {JTRUE} );
                                  Lout2(GotoLab^.ILabelNo);
                                  END;
                          IF g THEN
                            BEGIN
                            Lab1 := NextLabel; Lout(194 {JFALSE} );
                            Lout2(Lab1);
                            Expression(IfExpr); DumpStmt(ThenSt);
                            IF ElseSt <> NIL THEN
                              BEGIN
                              Lab2 := NextLabel; Lout(193 {JUMP} );
                              Lout2(Lab2);
                              END;
                            Lout(192 {DEFLAB} ); Lout2(Lab1);
                            IF ElseSt <> NIL THEN
                              BEGIN
                              DumpStmt(ElseSt); Lout(192 {DEFLAB} );
                              Lout2(Lab2);
                              END;
                            END
                          ELSE
                            BEGIN
                            Expression(IfExpr);
                            IF ElseSt <> NIL THEN DumpStmt(ElseSt);
                            END;
                          END;
              WHILEST:    BEGIN
                          Lab1 := NextLabel; Lout(192 {DEFLAB} );
                          Lout2(Lab1);
                          IF CondExpr = NIL THEN
                            g := True
                          ELSE IF CondExpr^.Node <> CSTNODE THEN
                            g := True
                          ELSE
                            g := CondExpr^.CstValu.Ivalu = 0;
                          IF g THEN
                            BEGIN
                            Lab2 := NextLabel; Lout(194 {JFALSE} );
                            Lout2(Lab2);
                            Expression(CondExpr);
                            END;
                          DumpStmt(LoopStmt); Lout(193 {JUMP} );
                          Lout2(Lab1);
                          IF g THEN
                            BEGIN
                            Lout(192 {DEFLAB} ); Lout2(Lab2);
                            END;
                          END;
              REPST:      BEGIN
                          Lab1 := NextLabel; Lout(192 {DEFLAB} );
                          Lout2(Lab1);
                          DumpStmt(LoopStmt);
                          IF CondExpr = NIL THEN
                            g := True
                          ELSE IF CondExpr^.Node <> CSTNODE THEN
                            g := True
                          ELSE
                            g := CondExpr^.CstValu.Ivalu <> 0;
                          IF g THEN
                            BEGIN
                            Lout(194 {JFALSE} ); Lout2(Lab1);
                            Expression(CondExpr);
                            END
                          ELSE
                            BEGIN
                            Lout(193 {JUMP} ); Lout2(Lab1);
                            END;
                          END;
              WITHST:     BEGIN
                          WithLevel := WithLevel + 1; Lout(44 {WITHBEG} );
                          Lout(WithLevel);
                                                                               {!OPT!}
                          {special case those with p^ do ... and with VPRec
                          (var param) do cases where the with statement is
                          better off being treated cosmetically}
                          IsPtr := 0;                                          {!OPT!}
                          IF (WithVar^.Node = UNNODE) THEN                     {!OPT!}
                            BEGIN                                              {!OPT!}
                            IF WithVar^.UnOp = 12 {^} THEN                     {!OPT!}
                              BEGIN                                            {!OPT!}
                              WITH WithVar^.UnArg^ DO                          {!OPT!}
                                BEGIN                                          {!OPT!}
                                IF (Node = IDENTNODE) THEN                     {!OPT!}
                                  BEGIN                                        {!OPT!}
                                  IF Class = VARS THEN                         {!OPT!}
                                    IF (Vkind = DRCT) AND                      {!OPT!}
                                       ((Vlev = Level) OR                      {!OPT!}
                                       UnitIsRegular(Vlev)) THEN               {!OPT!}
                                      BEGIN                                    {!OPT!}
                                      IsPtr := 1;                              {!OPT!}
                                      Lout(IsPtr);                             {!OPT!}
                                      Selector(WithVar^.UnArg);                {!OPT!}
                                      END                                      {!OPT!}
                                  END                                          {!OPT!}
                                ELSE IF (Node = REGISTER) THEN                 {!OPT!}
                                  BEGIN                                        {!OPT!}
                                  IsPtr := 1;                                  {!OPT!}
                                  Lout(IsPtr);                                 {!OPT!}
                                  Selector(WithVar^.UnArg);                    {!OPT!}
                                  END;                                         {!OPT!}
                                END;                                           {!OPT!}
                              END;                                             {!OPT!}
                            END                                                {!OPT!}
                          ELSE IF (WithVar^.Node = IDENTNODE) THEN             {!OPT!}
                            BEGIN                                              {!OPT!}
                            IF WithVar^.Class = VARS THEN                      {!OPT!}
                              BEGIN                                            {!OPT!}
                              IF (WithVar^.Vkind = INDRCT) AND                 {!OPT!}
                                 (WithVar^.Vlev = Level) THEN                  {!OPT!}
                                BEGIN                                          {!OPT!}
                                IsPtr := 1;                                    {!OPT!}
                                Lout(IsPtr);                                   {!OPT!}
                                WithVar^.Vkind := DRCT;                        {!OPT!}
                                Selector(WithVar);                             {!OPT!}
                                WithVar^.Vkind := INDRCT;                      {!OPT!}
                                END;                                           {!OPT!}
                              END;                                             {!OPT!}
                            END;                                               {!OPT!}

                          IF IsPtr = 0 THEN                                    {!OPT!}
                            BEGIN                                              {!OPT!}
                            Lout(0);                                           {!OPT!}
                            Selector(WithVar);                                 {!OPT!}
                            END;                                               {!OPT!}
                          DumpStmt(WithBody);
                          Lout(45 {WITHEND} ); Lout(WithLevel);
                          WithLevel := WithLevel - 1;
                          END;
              METHODCALL: DumpUCall(AssVar^.TripN, AssVar^.Tri2, AssVar^.Tri1,
                                    AssVar^.OrigTri1, AssVar^.TriSuper);       {!12-27-83}
              CALLST:     DumpCallStmt(fStmt);
              GOTOST:     OutGoto(LabLev, GotoLab);
              FORTOST, FORDOWNST:
                          BEGIN
                          Lout(202 {FOR} ); Lout(ForSize);
                          Selector(ForVar); Expression(ForInit);
                          Expression(ForLimit);
                          IF StmtOp = FORTOST THEN
                            OutIntCnst(1, 2)
                          ELSE
                            OutIntCnst( - 1, 2);
                          DumpStmt(ForSt); Lout(203 {FOREND} );
                          END;
              CASEST:     BEGIN
                          FindLoHi(fStmt);
                          IF CaseIsSmaller(fStmt) THEN
                            DumpCaseStmt(fStmt)
                          ELSE
                            DumpIfThenElse(fStmt);
                          END;
              LABEDST:    BEGIN
                          WITH StLab^ DO
                            BEGIN
                            IF GlobRefNo < 0 THEN
                              lOp := 196 {LOCULAB}
                            ELSE
                              lOp := 197; {GLOULAB}
                            Lout(lOp); Lout2(LabelNo); Lout2(ILabelNo);
                            IF GlobRefNo >= 0 THEN Lout2(GlobRefNo);
                            END;
                          DumpStmt(LabStmt);
                          END;
              TEMPST:     BEGIN
                          Lout ($CE); {TEMPSTMT}
                          Lout2(TempCSEregs.iMask);
                          END;
            END;
            fStmt := fStmt^.NextStmt;
            END;
      END; {DumpStmt}

    BEGIN {Dump}
      IF ProcN^.Class = UNITS THEN
        BEGIN
        Out(244);
        FOR i := 1 TO 8 DO Out(Ord(ProcN^.Name[i]));
        Out2(0); Out2(0); {Text address}
        Out2(0); Out2(0); {Text size}
        Out2(ProcN^.ULc); {Global size}
        Out(Ord(ProcN^.Ukind)); {Unit Kind}                                    {!IU!}
        END
      ELSE
        BEGIN
        LabNo := 0; WithLevel := 0; NextExtNo := 0; lByteNo := 0;
        ExtList := NIL; UnitSet := [];
        IntrinSet := [];                                                       {!IU!}

        {Assign internal label numbers to user labels}

        GlobalLabels := False; lpLabel := Display[Level].Labels;
        WHILE lpLabel <> NIL DO
          BEGIN
          lpLabel^.ILabelNo := NextLabel;
          IF lpLabel^.GlobRefNo >= 0 THEN GlobalLabels := True;
          lpLabel := lpLabel^.NextLabel;
          END;

        {Assign internal label number to exit label}

        lpLabel := Display[Level].ExitLabel;
        lpLabel^.ILabelNo := NextLabel;
        IF lpLabel^.GlobRefNo >= 0 THEN GlobalLabels := True;

        {Begin Module}

        Out(240);
        uName := ProcN^.Name;                                                  {!12-20-83}
        IF ProcN^.RtnNo < 0 THEN
          lName := uName
        ELSE
          LocalName(lName, ProcN^.RtnNo);
        FOR i := 1 TO 8 DO Out(Ord(lName[i]));
        IF CallingUnits THEN                                                   {!12-20-83}
          FOR i := 1 TO 8 DO                                                   {!12-20-83}
            IF (uName[i] >= 'a') AND (uName[i] <= 'z') THEN                    {!12-20-83}
              Out(Ord(uName[i]) - 32)                                          {!12-20-83}
            ELSE                                                               {!12-20-83}
              Out(Ord(uName[i]))                                               {!12-20-83}
        ELSE
          FOR i := 1 TO 8 DO Out(Ord(uName[i]));                               {!12-20-83}
                                                                               {!C}
        Father := '        ';
        IF ProcN^.PFdecl = METHDECL THEN
          IF ThisClass <> NIL THEN
            IF ThisClass^.ItsId <> NIL THEN Father := ThisClass^.ItsId^.Name;
        FOR i := 1 TO 8 DO Out(Ord(Father[i]));
                                                                               {!C}
        FOR i := 1 TO 8 DO Out(Ord(SegName[i]));
        Out(Ord(ProcN^.Class = FUNC));                                         {!02-17-84}
        Out(Level);
        Out2(ProcN^.Lc);
        Out2(ProcN^.ParmBytes);
        Out(2 * Ord(StkXFlag) + Ord(GlobalLabels));
        Out2(RegMask.iMask);                                                   {!OPT!}

        {Copy large value parameters}

        lpN := ProcN^.PFargList; lLc := ProcN^.ParmBytes;
        WHILE lpN <> NIL DO
          BEGIN
          IF lpN^.Vkind = DRCT THEN
            BEGIN
            lSize := FullBytes(lpN^.IdType);
            IF (lSize > 4) AND (lpN^.IdType^.Form <> SETS) THEN
              BEGIN
              lLc := lLc - 4;
              Lout(36 {MULTASS} ); Lout(1); Lout2(lSize);
              Lout(2 {LOCAL} ); Lout2(lpN^.Voff);
              Lout(12 {PTR} ); Lout(2 {LOCAL} ); Lout2(lLc);
              END
            ELSE
              BEGIN
              lLc := lLc - lSize;
              IF Odd(lSize) THEN lLc := lLc - 1;
              END;
            END
          ELSE
            lLc := lLc - 4;
          lpN := lpN^.Next;
          END;

        DumpStmt(ProcTree);

        FOR i := 0 TO lByteNo - 1 DO Out(Ord(lBuff[i]));

        IF Pass2Listing THEN                                                   {!02-17-84}
          BEGIN                                                                {!02-17-84}
          Out(205 {line number} );                                             {!02-17-84}
          Out2( - 3 {flush listing to TotalLines} );                           {!02-17-84}
          Out2(TotalLines);                                                    {!02-17-84}
          LastLine := TotalLines;                                              {!02-17-84}
          END;                                                                 {!02-17-84}

        {End Module}

        Out(254);
        IF DbugFlag THEN
          Out(1)
        ELSE
          Out(0);
        END;
    END; {Dump}

