#include <perms.h>
static int I77PODDCOLLATZ(int *I77CALLERDISPLAY, int I);

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  %integer %function %spec i77pODDCOLLATZ(%integer %array %name i77callerdisplay,%integer I)
//     2  %record %format i77arfmSHOWCOLLATZLENGTH(%integer %name MAX,

struct I77ARFMSHOWCOLLATZLENGTH {
  union {
    struct {
      int *MAX;
      int BASEVALUE;
    };
  };
};

//     3+ %integer BASEVALUE)
//     4  %record %format i77arfmBLOCK(%integer ODD1,

struct I77ARFMBLOCK {
  union {
    struct {
      int ODD1;
      int ODD2;
    };
  };
};

//     5+ %integer ODD2)
//     6
//     7  %integer %function i77pEVENCOLLATZ(%integer %array %name i77callerdisplay,%integer I)

static int I77PEVENCOLLATZ(int *I77CALLERDISPLAY, int I) {
  //     8  %integer %array i77display(1:3)

  int I77DISPLAY[3];

  //     9  %integer i77

  int I77;

  //    10  i77display(i77)=i77callerdisplay(i77) %for i77=1,1,2

  // %for I77 = 1, 1, 2 %cycle
  {
    I77 = 0;
  L_0001:
    if (I77 == 2) goto L_0002;
    I77 += 1;
    I77DISPLAY[I77 - 1] = [/*BUG*/ 0];
    goto L_0001;
  }

L_0002:;

//    11  i77display(3)=0

  I77DISPLAY[2] = 0;

  //    12  %record(i77arfmBLOCK)%name i77arBLOCK==record(i77display(1))

  struct I77ARFMBLOCK *I77ARBLOCK;
  I77ARBLOCK = (struct I77ARFMBLOCK *)_imp_RECORD(I77DISPLAY[0]);

  //    13  %record(i77arfmSHOWCOLLATZLENGTH)%name i77arSHOWCOLLATZLENGTH==record(i77display(2))

  struct I77ARFMSHOWCOLLATZLENGTH *I77ARSHOWCOLLATZLENGTH;
  I77ARSHOWCOLLATZLENGTH = (struct I77ARFMSHOWCOLLATZLENGTH *)_imp_RECORD(I77DISPLAY[1]);

  //    14  %if I{level 3}>=1 %then ->i77L1

  if (I < 1) goto L_0004;
  goto U_1000;
L_0004:;

//    15  %result=0

  return 0;

  //    16  i77L1:

U_1000:;

//    17  %if I{level 3}<=i77arSHOWCOLLATZLENGTH_MAX{level 2} %then ->i77L2

  if (I > *I77ARSHOWCOLLATZLENGTH->MAX) goto L_0005;
  goto U_1001;
L_0005:;

//    18  i77arSHOWCOLLATZLENGTH_MAX{level 2}=I{level 3}

  *I77ARSHOWCOLLATZLENGTH->MAX = I;

  //    19  i77L2:

U_1001:;

//    20  %if I{level 3}&i77arBLOCK_ODD2{level 1}=0 %then ->i77L3

  if (I & I77ARBLOCK->ODD2 != 0) goto L_0006;
  goto U_1002;
L_0006:;

//    21  %result=i77arSHOWCOLLATZLENGTH_BASEVALUE{level 2}+(i77pODDCOLLATZ(i77display,I{level 3}>>1))

  return I77ARSHOWCOLLATZLENGTH->BASEVALUE + I77PODDCOLLATZ(I77DISPLAY, (unsigned int)I >> 1);

  //    22  i77L3:

U_1002:;

//    23  %result=i77arSHOWCOLLATZLENGTH_BASEVALUE{level 2}+(i77pEVENCOLLATZ(i77display,I{level 3}>>1))

  return I77ARSHOWCOLLATZLENGTH->BASEVALUE + I77PEVENCOLLATZ(I77DISPLAY, (unsigned int)I >> 1);

  //    24  %end

} /* end of I77PEVENCOLLATZ */

//    25
//    26  %integer %function i77pODDCOLLATZ(%integer %array %name i77callerdisplay,%integer I)

static int I77PODDCOLLATZ(int *I77CALLERDISPLAY, int I) {
  //    27  %integer %array i77display(1:3)

  int I77DISPLAY[3];

  //    28  %integer i77

  int I77;

  //    29  i77display(i77)=i77callerdisplay(i77) %for i77=1,1,2

  // %for I77 = 1, 1, 2 %cycle
  {
    I77 = 0;
  L_0007:
    if (I77 == 2) goto L_0008;
    I77 += 1;
    I77DISPLAY[I77 - 1] = [/*BUG*/ 0];
    goto L_0007;
  }

L_0008:;

//    30  i77display(3)=0

  I77DISPLAY[2] = 0;

  //    31  %record(i77arfmSHOWCOLLATZLENGTH)%name i77arSHOWCOLLATZLENGTH==record(i77display(2))

  struct I77ARFMSHOWCOLLATZLENGTH *I77ARSHOWCOLLATZLENGTH;
  I77ARSHOWCOLLATZLENGTH = (struct I77ARFMSHOWCOLLATZLENGTH *)_imp_RECORD(I77DISPLAY[1]);

  //    32  %if I{level 3}>1 %then ->i77L4

  if (I <= 1) goto L_0009;
  goto U_1003;
L_0009:;

//    33  %result=0

  return 0;

  //    34  i77L4:

U_1003:;

//    35  %if I{level 3}<=i77arSHOWCOLLATZLENGTH_MAX{level 2} %then ->i77L5

  if (I > *I77ARSHOWCOLLATZLENGTH->MAX) goto L_000A;
  goto U_1000;
L_000A:;

//    36  i77arSHOWCOLLATZLENGTH_MAX{level 2}=I{level 3}

  *I77ARSHOWCOLLATZLENGTH->MAX = I;

  //    37  i77L5:

U_1000:;

//    38  %if I{level 3}<=715827882 %then ->i77L6

  if (I > 715827882) goto L_000B;
  goto U_1001;
L_000B:;

//    39  %signal 15,1,1

  _imp_signal(15, 1, 1, "");

  //    40  i77L6:

U_1001:;

//    41  %result=i77arSHOWCOLLATZLENGTH_BASEVALUE{level 2}+(i77pEVENCOLLATZ(i77display,((I{level 3}<<1)+I{level 3})+1))

  return I77ARSHOWCOLLATZLENGTH->BASEVALUE + I77PEVENCOLLATZ(I77DISPLAY, (I << 1) + I + 1);

  //    42  %end

} /* end of I77PODDCOLLATZ */

//    43
//    44  %routine i77pSHOWCOLLATZLENGTH(%integer %array %name i77callerdisplay,%integer I,%integer %name MAX)

static void I77PSHOWCOLLATZLENGTH(int *I77CALLERDISPLAY, int I, int *MAX) {
  //    45  %record(i77arfmSHOWCOLLATZLENGTH) i77ar

  struct I77ARFMSHOWCOLLATZLENGTH I77AR;

  //    46  %integer %array i77display(1:2)

  int I77DISPLAY[2];

  //    47  i77display(1)=i77callerdisplay(1)

  I77DISPLAY[0] = [/*BUG*/ 0];

  //    48  i77display(2)=addr(i77ar)

  I77DISPLAY[1] = _imp_ADDR(/*?*/ &I77AR);

  //    49  %record(i77arfmBLOCK)%name i77arBLOCK==record(i77display(1))

  struct I77ARFMBLOCK *I77ARBLOCK;
  I77ARBLOCK = (struct I77ARFMBLOCK *)_imp_RECORD(I77DISPLAY[0]);

  //    50  i77ar_MAX==MAX

  I77AR.MAX = (int *)MAX;

  //    51  i77ar_BASEVALUE{level 2}=0+1

  I77AR.BASEVALUE = 0 + 1;

  //    52  PRINTSTRING("The Collatz sequence for")

  _imp_PRINTSTRING(_imp_str_literal("The Collatz sequence for"));

  //    53  WRITE(I{level 2},1)

  _imp_WRITE(I, 1);

  //    54  PRINTSTRING(" takes")

  _imp_PRINTSTRING(_imp_str_literal(" takes"));

  //    55  %if I{level 2}&i77arBLOCK_ODD1{level 1}=0 %then ->i77L7

  if (I & I77ARBLOCK->ODD1 != 0) goto L_000C;
  goto U_1001;
L_000C:;

//    56  WRITE(i77pODDCOLLATZ(i77display,I{level 2}),1)

  _imp_WRITE(I77PODDCOLLATZ(I77DISPLAY, I), 1);

  //    57  ->i77L8

  goto U_1002;

  //    58  i77L7:

U_1001:;

//    59  WRITE(i77pEVENCOLLATZ(i77display,I{level 2}),1)

  _imp_WRITE(I77PEVENCOLLATZ(I77DISPLAY, I), 1);

  //    60  i77L8:

U_1002:;

//    61  PRINTSTRING(" steps and the largest value reached was")

  _imp_PRINTSTRING(_imp_str_literal(" steps and the largest value reached was"));

  //    62  WRITE(i77ar_MAX{level 2},1)

  _imp_WRITE(*I77AR.MAX, 1);

  //    63  NEWLINE

  _imp_NEWLINE();

  //    64  %end

  return;
} /* end of I77PSHOWCOLLATZLENGTH */

//    65
//    66  %begin

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

  //    67  %record(i77arfmBLOCK) i77ar

  struct I77ARFMBLOCK I77AR;

  //    68  %integer %array i77display(1:1)

  int I77DISPLAY[1];

  //    69  i77display(1)=addr(i77ar)

  I77DISPLAY[0] = _imp_ADDR(/*?*/ &I77AR);

  //    70  %integer HIGHEST

  int HIGHEST;

  //    71  %integer SEED

  int SEED;

  //    72  i77ar_ODD1{level 1}=1

  I77AR.ODD1 = 1;

  //    73  i77ar_ODD2{level 1}=2

  I77AR.ODD2 = 2;

  //    74  PROMPT("Integer seed value: ")

  _imp_PROMPT(_imp_str_literal_size(15, "Integer seed value: "));

  //    75  READ(SEED{level 1})

  _imp_READ(/*?*/ &SEED);

  //    76  %if SEED{level 1}>=0 %then ->i77L9

  if (SEED < 0) goto L_000D;
  goto U_1003;
L_000D:;

//    77  PRINTSTRING("Parameter must be a positive integer.")

  _imp_PRINTSTRING(_imp_str_literal("Parameter must be a positive integer."));

  //    78  NEWLINE

  _imp_NEWLINE();

  //    79  %signal 0,0,0

  _imp_signal(0, 0, 0, "");

  //    80  i77L9:

U_1003:;

//    81  HIGHEST{level 1}=0

  HIGHEST = 0;

  //    82  i77pSHOWCOLLATZLENGTH(i77display,SEED{level 1}-1,HIGHEST{level 1})

  I77PSHOWCOLLATZLENGTH(I77DISPLAY, SEED - 1, /*?*/ &HIGHEST);

  //    83  HIGHEST{level 1}=0

  HIGHEST = 0;

  //    84  i77pSHOWCOLLATZLENGTH(i77display,SEED{level 1},HIGHEST{level 1})

  I77PSHOWCOLLATZLENGTH(I77DISPLAY, SEED, /*?*/ &HIGHEST);

  //    85  HIGHEST{level 1}=0

  HIGHEST = 0;

  //    86  i77pSHOWCOLLATZLENGTH(i77display,SEED{level 1}+1,HIGHEST{level 1})

  I77PSHOWCOLLATZLENGTH(I77DISPLAY, SEED + 1, /*?*/ &HIGHEST);

  //    87  %end %of %program

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