int x = 0, y = 0;                /* x and y of the PC */
int dx = 1, dy = 0;              /* direction of the PC */
int v10err_compat = 0;           /* flag : emulate v1.0 off-by-one err? */
int stringmode = 0;              /* flag : are we in string mode? */

struct stack                    /* stack structure, for values on stack */
  {
    signed long val;
    struct stack *next;
  }
 *head;                         /* head of stack */

void push (signed long val);
signed long pop (void);

int main(int argc, char **argv) {
  while ((cur != '@') || (stringmode))          /*** Intepreting Phase */
  {
    if (stringmode && (cur != '"'))
      push (cur);
    else if (isdigit (cur))
      push (cur - '0');
    else
      switch (cur)
      {
	 case '>':            /* PC Right */
	   dx = 1;
	   dy = 0;
	   break;
	 case '<':            /* PC Left */
	   dx = -1;
	   dy = 0;
	   break;
	 case '^':            /* PC Up */
	   dx = 0;
	   dy = -1;
	   break;
	 case 'v':            /* PC Down */
	   dx = 0;
	   dy = 1;
	   break;
	 case '|':            /* Vertical 'If' */
	   dx = 0;
	   if (pop ())
	     dy = -1;
	   else
	     dy = 1;
	   break;
	 case '_':            /* Horizontal 'If' */
	   dy = 0;
	   if (pop ())
	     dx = -1;
	   else
	     dx = 1;
	   break;
	 case '+':            /* Add */
	   push (pop () + pop ());
	   break;
	 case '-':            /* Subtract */
	   {
	     long a = pop();
	     long b = pop();
	     push(b - a);
	   }
	   break;
	 case '*':            /* Multiply */
	   push (pop () * pop ());
	   break;
	 case '/':            /* Integer Divide */
	   {
	     signed long a = pop ();
	     signed long b = pop ();
	     push (b / a);
	   }
	   break;
	 case '%':            /* Modulo */
	   {
	     signed long a = pop ();
	     signed long b = pop ();
	     push (b % a);
	   }
	   break;
	 case '\\':           /* Swap */
	   {
	     signed long a = pop ();
	     signed long b = pop ();
	     push (a);
	     push (b);
	   }
	   break;
	 case '.':            /* Pop Out Integer */
	   {
		 fprintf (stdout, "%ld ", pop ());
		 fflush (stdout);
	   }
	   break;
	 case ',':            /* Pop Out ASCII */
	   {
		 fprintf (stdout, "%c", pop ());
		 fflush (stdout);
	   }
	   break;
	 case '"':		/* Toggle String Mode */
	   stringmode = !stringmode;
	   break;
	 case ':':            /* Duplicate */
	   {
	     signed long a = pop ();
	     push (a);
	     push (a);
	   }
	   break;
	 case '!':            /* Negate */
	if (pop())
	  push(0);
	else
	  push(1);
	   break;
	 case '`':
	   {
	     signed long b = pop ();
	     signed long a = pop ();
	     push (a > b);
	   }
	   break;
	 case '#':            /* Bridge */
	   x += dx;
	   y += dy;
	   break;
	 case '$':            /* Pop and Discard */
	   pop ();
	   break;
	 case '?':            /* Random Redirect */
	   switch ((rand () / 32) % 4)
	      {
	      case 0:
		dx = 1;
		dy = 0;
		break;
	      case 1:
		dx = -1;
		dy = 0;
		break;
	      case 2:
		dx = 0;
		dy = -1;
		break;
	      case 3:
		dx = 0;
		dy = 1;
		break;
	      }
	   break;
	 case '&':            /* Input Integer */
	   {
	     signed long b;
		 fscanf (stdin, "%ld", &b);
		 push (b);
	   }
	   break;
	 case '~':            /* Input ASCII */
	   {
	     char c;
		 c = fgetc (stdin);
		 push (c);
	   }
	   break;
	 case 'g':            /* Get Value */
	   {
	     signed long y = pop (), x = pop ();
	     push (cur);
	   }
	   break;
	 case 'p':            /* Put Value */
	   {
	     signed long y = pop (), x = pop ();
	     cur = pop ();
	   }
	   break;
	 default:
	   break;
      }
    x += dx;
    y += dy;
    if (x < 0)
      if (v10err_compat)
      {
	x = LINEWIDTH;
      } else
      {
	x = LINEWIDTH - 1;
      }
    else
      x = x % LINEWIDTH;
    if (y < 0)
      if (v10err_compat)
      {
	y = PAGEHEIGHT;
      } else
      {
	y = PAGEHEIGHT - 1;
      }
    else
      y = y % PAGEHEIGHT;
  }
}

/*
 * pushes a value onto the stack.
 */
void
  push (signed long val)
{
  struct stack *s;
  s = (struct stack *) malloc (sizeof (struct stack));
  s->val = val;
  s->next = head;
  head = s;
}

/*
 * pops a value off the stack. returns 0 in case of underflow.
 */
signed long
  pop ()
{
  signed long v;
  struct stack *s = head;
  if (s)
    {
      v = head->val;
      head = head->next;
      free (s);
      return v;
    }
  else
    {
      return 0;
    }
}