#include <perms.h>

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  %begin

int main(int argc, char **argv) { /*%begin*/
  _imp_initialise(argc, argv);
  auto void CSS(void);

  //     2
  //     3      ! An example program which uses a %routinespec and a call
  //     4      ! to the routine BEFORE actually the routine implementation
  //     5
  //     6      %routinespec css
  //     7
  //     8      selectoutput(0)

  _imp_SELECTOUTPUT(0);

  //     9      printstring("start %SPEC test"); newline

  _imp_PRINTSTRING(_imp_str_literal("start %SPEC test"));
  _imp_NEWLINE();

  //    10      css

  CSS();

  //    11      printstring("end %SPEC test"); newline

  _imp_PRINTSTRING(_imp_str_literal("end %SPEC test"));
  _imp_NEWLINE();

  //    12
  //    13      %routine css

  void CSS(void) {
    //    14          %integer a,b,c

    int A;
    int B;
    int C;
    auto int THREE(int P1, int P2, int P3);

    auto int TWO(int P1, int P2);

    //    15
    //    16          %integerfnspec three(%integer p1,p2,p3)
    //    17          %integerfnspec two(%integer p1,p2)
    //    18
    //    19          c = 5

    C = 5;

    //    20
    //    21          %integerfn one(%integer p1)

    int ONE(int P1) {
      //    22              %integer a1,b1,c1,d1

      int A1;
      int B1;
      int C1;
      int D1;

      //    23              %owninteger callcount

      static int CALLCOUNT;

      //    24
      //    25              %begin

      { /*%begin*/

        //    26                  a1 = p1

        A1 = P1;

        //    27                  b1 = 2*p1

        B1 = 2 * P1;

        //    28                  c1 = 3*p1

        C1 = 3 * P1;

        //    29                  callcount = callcount + 1

        CALLCOUNT = CALLCOUNT + 1;

        //    30              %end

        goto end_1000;
      end_1000:;
      }

      //    31
      //    32              ! Use callcount as a defence against repeated calls to routine 'three'
      //    33              ! which would cause a stack overflow.
      //    34              %if (callcount < 10) %then d1 = three(a1,b1,c1) %else d1 = -1

      if (CALLCOUNT >= 10) goto L_0001;
      D1 = THREE(A1, B1, C1);
      goto L_0002;
    L_0001:;
      D1 = -1;
    L_0002:;

    //    35              %result = d1

      return D1;

      //    36          %end

    } /* end of ONE */

    //    37
    //    38          b = 3

    B = 3;

    //    39
    //    40          %integerfn three(%integer p1,p2,p3)

    int THREE(int P1, int P2, int P3) {
      //    41              %integer a3,b3

      int A3;
      int B3;

      //    42              a3 = one(p1)

      A3 = ONE(P1);

      //    43              b3 = two(p2,p3)

      B3 = TWO(P2, P3);

      //    44              %result = a3 + b3

      return A3 + B3;

      //    45          %end

    } /* end of THREE */

    //    46
    //    47          a = three(b,c,b+c)

    A = THREE(B, C, B + C);

    //    48
    //    49          %integerfn two(%integer p1,p2)

    int TWO(int P1, int P2) {
      //    50              %integer a2,b2

      int A2;
      int B2;

      //    51
      //    52              %result = one(p1+p2)

      return ONE(P1 + P2);

      //    53          %end

    } /* end of TWO */

    // ?B2 unused
    // ?A2 unused
    //    54
    //    55      %end

    return;
  } /* end of CSS */

  //    56
  //    57  %endofprogram

  _imp_stop(0);
  return 0;
end_0:;
}