#include <perms.h>

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  ! Imp needs some perm code to determine upper and lower bounds of arrays
//     2  ! which might look something like this...
//     3  %permintegerfnspec LB(%integerarray(2)%name A, %integer index)

extern int _imp_LB(int *A, int INDEX);

//     4  %permintegerfnspec UB(%integerarray(2)%name A, %integer index)

extern int _imp_UB(int *A, int INDEX);

//     5
//     6  %begin

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

  //     7
  //     8    %routine printarray(%integerarray(2)%name A)

  void PRINTARRAY(int *A) {
    //     9      %integer A0, A1

    int A0;
    int A1;

    //    10      ! Imp needs some perm code to determine upper and lower bounds of arrays
    //    11      %for A0 = LB(A,0), 1, UB(A,0) %cycle

    // %for A0 = _imp_LB(A, 0), 1, _imp_UB(A, 0) %cycle
    {
      int _initial = _imp_LB(A, 0), _final = _imp_UB(A, 0);
      if (invalid_for_loop(_initial, 1, _final))
        _imp_signal(5, 1, 0, "Illegal cycle A0 = _imp_LB(A, 0), 1, _imp_UB(A, 0)");
      A0 = _initial - (1);
    L_0001:
      if (A0 == _final) goto L_0002;
      A0 += 1;

      //    12        %for A1 = LB(A,1), 1, UB(A,1) %cycle

      // %for A1 = _imp_LB(A, 1), 1, _imp_UB(A, 1) %cycle
      {
        int _initial = _imp_LB(A, 1), _final = _imp_UB(A, 1);
        if (invalid_for_loop(_initial, 1, _final))
          _imp_signal(5, 1, 0, "Illegal cycle A1 = _imp_LB(A, 1), 1, _imp_UB(A, 1)");
        A1 = _initial - (1);
      L_0004:
        if (A1 == _final) goto L_0005;
        A1 += 1;

        //    13          write(A(A0, A1), 3); print string(", ")

        _imp_WRITE([/*BUG*/ 0], 3);
        _imp_PRINTSTRING(_imp_str_literal(", "));

        //    14        %repeat

        goto L_0004;
      }

    L_0005:;

    //    15        newline

      _imp_NEWLINE();

      //    16      %repeat

      goto L_0001;
    }

  L_0002:;

  //    17      newline

    _imp_NEWLINE();

    //    18    %end

    return;
  } /* end of PRINTARRAY */

  //    19
  //    20    %integername element

  int *ELEMENT;

  //    21    %integer i

  int I;

  //    22
  //    23    ! imp77 doesn't allow initialised multi-dimensional arrays.  (Imp80 would!)
  //    24    ! So I'll initialise these explicitly:
  //    25    %integerarray fred(0:1, 0:2)       { simple case }

  int FRED[2][3];

  //    26    %integerarray jim(11:13, 100:103)  { non-zero lower bounds }

  int JIM[3][4];

  //    27    element == fred(0,0); element = i %and element == element++1 %for i = 0, 1, 5

  ELEMENT = (int *)/*?*/ &FRED[0][0];
  // %for I = 0, 1, 5 %cycle
  {
    I = -1;
  L_0007:
    if (I == 5) goto L_0008;
    I += 1;
    *ELEMENT = I;
    ELEMENT = (int *)ELEMENT + 1;
    goto L_0007;
  }

L_0008:;

//    28    element == jim(11,100); element = i %and element == element++1 %for i = 0, 1, 11

  ELEMENT = (int *)/*?*/ &JIM[0][0];
  // %for I = 0, 1, 11 %cycle
  {
    I = -1;
  L_0009:
    if (I == 11) goto L_000A;
    I += 1;
    *ELEMENT = I;
    ELEMENT = (int *)ELEMENT + 1;
    goto L_0009;
  }

L_000A:;

//    29
//    30    printarray(fred)

  PRINTARRAY(FRED);

  //    31    printarray(jim)

  PRINTARRAY(JIM);

  //    32
  //    33  %endofprogram

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