#define USE_IMP_TRACING 1
#include <perms.h>
int _imp_mainep(int _imp_argc, char **_imp_argv) {
  _imp_enter();
  auto void Load(void);
  auto void Gpmnextch(void);
  auto void Find(int X);
  auto void Monitor(int N);
  const int Marker = 0xFFFFC000;
  static short St[10001 /*0:10000*/] = {
      -1,  4,   'd', 'e', 'f', -1,  0,   4,   'v', 'a',
      'l', -2,  6,   7,   'u', 'p', 'd', 'a', 't', 'e',
      -3,  12,  4,   'b', 'i', 'n', -4,  21,  4,   'd',
      'e', 'c', -5,  27,  4,   'b', 'a', 'r', -6,  [39 ... 10000] = 0};
  static int E = 33;
  static int S = 39;
  int A;
  int W;
  int W1;
  int H;
  int P;
  int F;
  int C;
  int Q;
  int E0;
  int F0;
  int H0;
  int R;
  _imp_string Filename;
  static int Mcm_sw;
  static void *Mcm[6 /*1:6*/] = {
      &&Mcm_1, &&Mcm_2, &&Mcm_3, &&Mcm_4, &&Mcm_5, &&Mcm_6,
  };
  if (_imp_on_event(0, 9)) {
    if (Event() == 9) {
      Selectinput(0);
      goto Start;
    } else
      Printstring(
          _imp_join(Snl, _imp_join(_imp_str_literal("GPM terminated"), Snl)));
    _imp_leave();
    exit(0);
  }
  A = 0;
  W = 0;
  W1 = 0;
  H = 0;
  P = 0;
  F = 0;
  C = 0;
  Q = 1;
Start:
  Gpmnextch();
  if (A == '@') {
    Read(Filename);
    Openinput(1, Filename);
    Selectinput(1);
    goto Start;
  }
  if (A == '/') {
    Read(Filename);
    Openoutput(1, Filename);
    Selectoutput(1);
    goto Start;
  }
  if (A == '<') {
    Q = Q + 1;
    goto Q2;
  }
  if (A == '$') goto Fn;
  if (A == ',') goto Nextitem;
  if (A == ';') goto Apply;
  if (A == '#') goto Loadarg;
  if (A == Marker) goto Endfn;
  if (A == '>') goto Exit;
Copy:
  Load();
  if (Q == 1) goto Start;
Q2:
  Gpmnextch();
  if (A == '<') {
    Q = Q + 1;
    goto Copy;
  }
  if (A != '>') goto Copy;
  Q = Q - 1;
  if (Q == 1)
    goto Start;
  else
    goto Copy;
Fn:
  St[S] = H;
  St[S + 1] = F;
  St[S + 2] = 0;
  St[S + 3] = 0;
  H = S + 3;
  F = S + 1;
  S = S + 4;
  goto Start;
Nextitem:
  if (H == 0) goto Copy;
  St[H] = S - H - St[H];
  St[S] = 0;
  H = S;
  S = S + 1;
  goto Start;
Apply:
  if (P > F) Monitor(1);
  if (H == 0) goto Copy;
  St[H] = S - H;
  St[S] = Marker;
  H0 = St[F - 1];
  F0 = St[F];
  St[F - 1] = S - F + 2;
  St[F] = P;
  St[F + 1] = C;
  P = F;
  F = F0;
  H = H0;
  S = S + 1;
  if (H != 0) St[H] = St[H] + St[P - 1];
  Find(P + 2);
  if (St[W] < 0) goto *Mcm[Mcm_sw = (-St[W]) - 1];
  C = W + 1;
  goto Start;
Loadarg:
  if (P == 0)
    if (H == 0)
      goto Copy;
    else
      Monitor(2);
  Gpmnextch();
  W = P + 2;
  if (A < '0') Monitor(3);
  if (A > '0')
    for (R = 0; R <= A - '0' - 1; R++) {
      W = W + St[W];
      if (St[W] == Marker) Monitor(4);
    }
  for (R = 1; R <= St[W] - 1; R++) {
    A = St[W + R];
    Load();
  }
  goto Start;
Endfn:
  if (F > P) Monitor(5);
  St[S] = E;
  A = S;
  while (St[A] >= P - 1 + St[P - 1]) {
    E0 = St[A];
    St[A] = E0 - St[P - 1];
    A = E0;
  }
  W = St[A];
  while (W > P - 1) W = St[W];
  St[A] = W;
  E = St[S];
  if (H != 0)
    if (H > P)
      H = H - St[P - 1];
    else
      St[H] = St[H] - St[P - 1];
  A = P - 1;
  W = A + St[P - 1];
  C = St[P + 1];
  S = S - St[P - 1];
  P = St[P];
  while (A != S) {
    St[A] = St[W];
    A = A + 1;
    W = W + 1;
  }
  goto Start;
Exit:
  if (C != H || H != 0) Monitor(8);
  _imp_leave();
  exit(0);
Mcm_1:;
  if (H != 0) St[H] = St[H] - St[P - 1] + 6;
  St[P - 1] = 6;
  St[P + 5] = E;
  E = P + 5;
  goto Endfn;
Mcm_2:;
  Find(P + 6);
  while (St[W + 1] != Marker) {
    A = St[W + 1];
    W = W + 1;
    Load();
  }
  goto Endfn;
Mcm_3:;
  Find(P + 9);
  A = P + 9 + St[P + 9];
  if (St[A] > St[W]) Monitor(9);
  for (R = 1; R <= St[A]; R++) St[W + R] = St[A + R];
  goto Endfn;
Mcm_4:;
  W = 0;
  if (St[P + 7] == '+' || St[P + 7] == '-')
    A = P + 8;
  else
    A = P + 7;
  while (St[A] != Marker) {
    if ('0' > St[A] || St[A] > '9') Monitor(10);
    W = 10 * W + St[A] - '0';
    A = A + 1;
  }
  if (St[P + 7] == '-')
    St[S] = -W;
  else
    St[S] = W;
  S = S + 1;
  goto Endfn;
Mcm_5:;
  W = St[P + 7];
  if (W < 0) {
    W = -W;
    A = '-';
    Load();
  }
  R = 1;
  while (10 * R <= W) R = 10 * R;
  while (R >= 1) {
    A = W / R + '0';
    Load();
    W = W - R * (A - '0');
    R = R / 10;
  }
  goto Endfn;
Mcm_6:;
  W = St[P + 9];
  A = St[P + 11];
  if (St[P + 7] == '+') A = W + A;
  if (St[P + 7] == '-') A = W - A;
  if (St[P + 7] == '*') A = W * A;
  if (St[P + 7] == '/') A = W / A;
  if (St[P + 7] == 'r') A = W - W / A * A;
  Load();
  goto Endfn;
  void Load(void) {
    _imp_enter();
    if (H == 0)
      Printsymbol(A);
    else {
      St[S] = A;
      S = S + 1;
    }
    _imp_leave();
  }
  void Gpmnextch(void) {
    _imp_enter();
    if (C == 0)
      A = Nextsymbol();
    else {
      A = St[C];
      C = C + 1;
    }
    _imp_leave();
  }
  void Find(int X) {
    _imp_enter();
    A = E;
    W = X;
  Again:
    for (R = 0; R <= St[W] - 1; R++)
      if (St[W + R] != St[A + R + 1]) goto Next;
    W = A + 1 + St[W];
    _imp_leave();
    return;
  Next:
    A = St[A];
    if (A >= 0) goto Again;
    Monitor(7);
    _imp_leave();
  }
  void Monitor(int N) {
    _imp_enter();
    auto void Item(int X);
    static int Fault_sw;
    static void *Fault[10 /*1:10*/] = {
        &&Fault_1, &&Fault_2, &&Fault_3, &&Fault_4, &&Fault_5,
        &&Fault_6, &&Fault_7, &&Fault_8, &&Fault_9, &&Fault_10,
    };
    Printstring(_imp_join(Snl, _imp_str_literal("Monitor : ")));
    goto *Fault[Fault_sw = (N)-1];
  Fault_1:
    Printstring(_imp_str_literal("Unmatched semicolon in definition of "));
    Item(P + 2);
    goto End;
  Fault_2:
    Printstring(_imp_str_literal("Unquoted # in argument list of "));
    Item(F + 2);
    goto End;
  Fault_3:
    Printstring(
        _imp_str_literal("Impossible argument number in definition of "));
    Item(P + 2);
    goto End;
  Fault_4:
    Printstring(_imp_str_literal("No argument "));
    Printsymbol(A);
    Printstring(_imp_str_literal(" in call for "));
    Item(P + 2);
    goto End;
  Fault_5:
    Printstring(_imp_str_literal("Terminator in "));
    if (C == 0) {
      Printstring(_imp_str_literal("input stream; GPM error ?"));
      goto End;
    }
    Printstring(_imp_str_literal("argument list for "));
    Item(F + 2);
    Printstring(_imp_join(
        Snl, _imp_str_literal(
                 "probably due to semicolon missing from definition of ")));
    Item(P + 2);
    goto End;
  Fault_6:
    Printstring(_imp_str_literal("GPM error?"));
    goto End;
  Fault_7:
    Printstring(_imp_str_literal("Undefined name "));
    Item(W);
    goto End;
  Fault_8:
    Printstring(_imp_str_literal("Unmatched >; GPM error ?"));
    goto End;
  Fault_9:
    Printstring(_imp_str_literal("Update argument too long for "));
    Item(P + 9);
    goto End;
  Fault_10:
    Printstring(_imp_str_literal("Non-digit in number "));
  End:;
    W = 20;
    Printstring(_imp_join(Snl, _imp_str_literal("Current macros are :")));
    while (P != 0 || F != 0) {
      if (P > F) {
        W1 = P + 2;
        P = St[P];
        Printstring(_imp_join(Snl, _imp_str_literal("already entered :  ")));
      } else {
        W1 = F + 2;
        F = St[F];
        Printstring(_imp_join(Snl, _imp_str_literal("not yet entered :  ")));
      }
      for (R = 1; R <= W; R++) {
        Item(W1);
        if (St[W1] == 0) break;
        W1 = W1 + St[W1];
        if (St[W1] == Marker) break;
        if (W != 1)
          Printstring(_imp_join(
              Snl,
              _imp_join(_imp_str_literal("arg"),
                        _imp_join(Itos(R, 1), _imp_str_literal(" :    ")))));
      }
      W = 1;
    }
    Printstring(_imp_join(
        Snl, _imp_join(_imp_str_literal("End of monitor printing"), Snl)));
    _imp_leave();
    exit(0);
    void Item(int X) {
      _imp_enter();
      int K;
      int L;
      if (St[X] == 0)
        L = S - X - 1;
      else
        L = St[X] - 1;
      if (L > 0)
        for (K = 1; K <= L; K++) Printsymbol(St[X + K]);
      if (St[X] == 0) Printstring(_imp_str_literal("...    (incomplete)"));
      _imp_leave();
    }

    _imp_leave();
  }
  _imp_leave();
  exit(0);
  return (1);
}
