/*
    This is an automatic translation of GPM from Imp to C - it
    has not been tested and may require some hand editing.  Please
    refer to the Imp version if in doubt.
 */

    /* EPC Imp to C Translation Release 4 Version Apr 95 */


#include "imptoc.h"

#define marker (0xFFFFC000)
#define snl ("\n")
static short int st[10000 + 1] = { -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, 0,
  /* Plus remaining entries are all 0 */
};
static int e = 33;
static int s = 39;
int a, w, w1, h, p, f, c, q, e0, f0, h0, r;
char filename[64];
/*------------------------------------------------------------------------------*/

static void /*0x0 */
load ()
{
  if (h == 0)
    fprintf (out_file, "%c", a);
  else
    {
      st[s] = a;
      s++;
    }
}

        /*------------------------------------------------------------------------------*/

static void /*0x0 */
nextch ()
{
  if (c == 0)
    a = fgetc (in_file);
  else
    {
      a = st[c];
      c++;
    }
}

        /*------------------------------------------------------------------------------*/

static void /*0x0 */
item (int x)
{
  int k, l;
  if (st[x] == 0)
    l = (s - x) - 1;
  else
    l = st[x] - 1;
  if (l > 0)
    {
      for (k = 1; k <= l; k++)
        fprintf (out_file, "%c", st[x + k]);
    }
  if (st[x] == 0)
    fprintf (out_file, "%s", "...    (incomplete)");
}


static void /*0x0 */
monitor (int n)
{
  int fault_value;
  int fault_line;
  char *fault_file;

  fprintf (out_file, "%s", imp_concat (snl, "Monitor : "));
  {
    fault_value = n;
    fault_line = __LINE__;
    fault_file = __FILE__;
    goto fault_dispatch;
  }

fault_1:
  fprintf (out_file, "%s", "Unmatched semicolon in definition of ");
  item (p + 2);
  goto end;

fault_2:
  fprintf (out_file, "%s", "Unquoted # in argument list of ");
  item (f + 2);
  goto end;

fault_3:
  fprintf (out_file, "%s", "Impossible argument number in definition of ");
  item (p + 2);
  goto end;

fault_4:
  fprintf (out_file, "%s", "No argument ");
  fprintf (out_file, "%c", a);
  fprintf (out_file, "%s", " in call for ");
  item (p + 2);
  goto end;

fault_5:
  fprintf (out_file, "%s", "Terminator in ");
  if (c == 0)
    {
      fprintf (out_file, "%s", "input stream; GPM error ?");
      goto end;
    }
  fprintf (out_file, "%s", "argument list for ");
  item (f + 2);
  fprintf (out_file, "%s",
           imp_concat (snl,
                       "probably due to semicolon missing from definition of "));
  item (p + 2);
  goto end;

fault_6:
  fprintf (out_file, "%s", "GPM error?");
  goto end;

fault_7:
  fprintf (out_file, "%s", "Undefined name ");
  item (w);
  goto end;

fault_8:
  fprintf (out_file, "%s", "Unmatched >; GPM error ?");
  goto end;

fault_9:
  fprintf (out_file, "%s", "Update argument too long for ");
  item (p + 9);
  goto end;

fault_10:
  fprintf (out_file, "%s", "Non-digit in number ");

end:


/* general monitor*/
  w = 20;
  fprintf (out_file, "%s", imp_concat (snl, "Current macros are :"));
  while (p != 0 || f != 0)
    {
      if (p > f)
        {
          w1 = p + 2;
          p = st[p];
          fprintf (out_file, "%s", imp_concat (snl, "already entered :  "));
        }
      else
        {
          w1 = f + 2;
          f = st[f];
          fprintf (out_file, "%s", imp_concat (snl, "not yet entered :  "));
        }
      for (r = 1; r <= w; r++)
        {
          item (w1);
          if (st[w1] == 0)
            break;
          w1 += st[w1];
          if (st[w1] == marker)
            break;
          if (!(w == 1))
            {
              fprintf (out_file, "\n%s%1d%s", "arg", r, " :    ");
            }
        }
      w = 1;
    }
  fprintf (out_file, "\n%s\n", "End of monitor printing");
  exit (0);
  goto fault_skip;
fault_dispatch:
  switch (fault_value)
    {
    case 1:
      goto fault_1;
    case 2:
      goto fault_2;
    case 3:
      goto fault_3;
    case 4:
      goto fault_4;
    case 5:
      goto fault_5;
    case 6:
      goto fault_6;
    case 7:
      goto fault_7;
    case 8:
      goto fault_8;
    case 9:
      goto fault_9;
    case 10:
      goto fault_10;
    default:
      BADSWITCH (fault_value, fault_line, fault_file);
    }
fault_skip:;
}


static void /*0x0 */
find (int x)
{
  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];
  return;
next:
  a = st[a];
  if (!(a < 0))
    goto again;
  monitor (7);
}

        /*------------------------------------------------------------------------------*/


int
main ()
{
  int mcm_value;
  int mcm_line;
  char *mcm_file;

/*  %ON %EVENT 0, 9 %START*/
/*    %IF event_event = 9 %THEN %START*/
/*      select input(0)*/
/*      ->start*/
/*    %FINISH %ELSE print string(snl."GPM terminated".snl)*/
/*    %STOP*/
/*  %FINISH*/

  a = 0;
  w = 0;
  w1 = 0;
  h = 0;
  p = 0;
  f = 0;
  c = 0;
  q = 1;

start:
  nextch ();
  if (a == '@')
    {
      /* Call to %routine READ STRING(%stringname S) - please modify pass2.i to handle it */
        ;
      openinput (1, filename);
      selectinput (1);
      goto start;
    }
  if (a == '/')
    {
      /* Call to %routine READ(%name NUMBER) - please modify pass2.i to handle it */
        ;
      openoutput (1, filename);
      selectoutput (1);
      goto start;
    }
  if (a == '<')
    {
      q++;
      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:
  nextch ();
  if (a == '<')
    {
      q++;
      goto copy;
    }
  if (a != '>')
    goto copy;
  q--;
  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 += 4;
  goto start;

nextitem:
  if (h == 0)
    goto copy;
  st[h] = (s - h) - st[h];
  st[s] = 0;
  h = s;
  s++;
  goto start;

apply:
  if (p > f)
    monitor (1);
  if (h == 0)
    goto copy;
  st[h] = s - h;
  st[s] = (*(short int *) (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++;
  if (!(h == 0))
    st[h] = st[h] + st[p - 1];
  find (p + 2);
  if (st[w] < 0)
    {
      mcm_value = -st[w];
      mcm_line = __LINE__;
      mcm_file = __FILE__;
      goto mcm_dispatch;
    }
  c = w + 1;
  goto start;

loadarg:
  if (p == 0)
    {
      if (h == 0)
        goto copy;
      else
        monitor (2);
    }
  nextch ();
  w = p + 2;
  if (a < '0')
    monitor (3);
  if (a > '0')
    {
      for (r = 0; r <= (a - '0') - 1; r++)
        {
          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 -= st[p - 1];
      else
        st[h] = st[h] - st[p - 1];
    }
  a = p - 1;
  w = a + st[p - 1];
  c = st[p + 1];
  s -= st[p - 1];
  p = st[p];
  while (a != s)
    {
      st[a] = st[w];
      a++;
      w++;
    }
  goto start;

Exit:
  if (!((c == h) && (h == 0)))
    monitor (8);
  exit (0);

mcm_1:
  /* def */
  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:
  /* val */
  find (p + 6);
  while (st[w + 1] != marker)
    {
      a = st[w + 1];
      w++;
      load ();
    }
  goto endfn;

mcm_3:
  /* update */
  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:
  /* bin */
  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++;
    }
  if (st[p + 7] == '-')
    st[s] = -w;
  else
    st[s] = w;
  s++;
  goto endfn;

mcm_5:
  /* dec */
  w = st[p + 7];
  if (w < 0)
    {
      w = -w;
      a = '-';
      load ();
    }
  r = 1;
  while ((10 * r) <= w)
    r *= 10;
  while (r >= 1)
    {
      a = (w / r) + '0';
      load ();
      w -= r * (a - '0');
      r /= 10;
    }
  goto endfn;

mcm_6:
  /* bar */
  w = st[p + 9];
  a = st[p + 11];
  if (st[p + 7] == '+')
    a += w;
  if (st[p + 7] == '-')
    a = w - a;
  if (st[p + 7] == '*')
    a *= w;
  if (st[p + 7] == '/')
    a = w / a;
  if (st[p + 7] == 'r')
    a = w - ((w / a) * a);
  load ();
  goto endfn;

  goto mcm_skip;
mcm_dispatch:
  switch (mcm_value)
    {
    case 1:
      goto mcm_1;
    case 2:
      goto mcm_2;
    case 3:
      goto mcm_3;
    case 4:
      goto mcm_4;
    case 5:
      goto mcm_5;
    case 6:
      goto mcm_6;
    default:
      BADSWITCH (mcm_value, mcm_line, mcm_file);
    }
mcm_skip:;
}


/* end of automatic translation */