char *tag_rhs_value(int tagnum);
int cpop(void);
void cpush(int op);

int get_icode (FILE * f)
{
int c = fgetc (f);

   if (c != EOF) {
      if (debug_input) {
         if ('!' <= c && c <= '~') {
            memprintf("%c: ", c);
         } else {
            memprintf("%d: ", c);
         }
      }
      if (cstackp != cstack) {
        int tos;
        tos = cpop(); cpush(tos);
        if (debug_input) memprintf("%s\n", tag_rhs_value(tos));
      } else {
        if (debug_input) memprintf("(stack empty)\n");
      }
   }
   return (c);
}

static char *getname (void)
{                                /* A Hack */
   static char local[256];
   int c;
   char *s = local;

   for (;;) {
      c = get_icode (icode_file);
      assert (c != EOF);
      if ((isalpha (c) && isupper (c)) || isdigit (c)) {
      } else
         break;
      *s++ = c;
   }
   *s = '\0';
   ungetc (c, icode_file);
   return (local);
}

static char *getwordconst (int *w)
{
   static char local[12];
   int i, c;
   int word = 0;

   for (i = 0; i < 4; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   sprintf(local, "0x%08x", word);
   if (w != NULL) *w = word;
   return (local);
}

static char *getbyte (void)
{
   static char local[4];
   int c;

   c = get_icode (icode_file);
   assert (c != EOF);
   sprintf(local, "%02x", c & 255);
   return (local);
}

static char *getcond (int *ch)
{
   int c;

   c = get_icode (icode_file);
   assert (c != EOF);
   c &= 255;
   if (ch != NULL) *ch = c;

   return (cond[c]);
}

#ifdef NEVER
static char *getrcond (void)
{
   int c;

   c = get_icode (icode_file);
   assert (c != EOF);
   c &= 255;
   return (rcond[c]);
}
#endif

static char *getimpstring (char **starg)
{
   static char local[256 * 2 + 3];
   char *impstr;
   int i, c, len;
   char *s = local;
   char *p;
   impstr = malloc(257);
   p = impstr+1;
   len = get_icode (icode_file);
   assert (c != EOF);
   *s++ = '"';
   for (i = 0; i < len; i++) {
      c = get_icode (icode_file);
      assert (c != EOF);
      *p++ = c;
      if (c == '"') {
         *s++ = '\\';
         *s++ = c;
      } else if (c == '\n') {
         *s++ = '\\';                /* just for display purposes */
         *s++ = 'n';
      } else
         *s++ = c;
   }
   *s++ = '"';
   *s++ = '\0';
   *p = '\0';
   *impstr = strlen(impstr+1);
   if (starg != NULL) *starg = impstr;
   return (local);
}

static char *getmcstring(int *cp)
{
  static char local[256*2+3];
  int c;
  char *s = local;
  for (;;) {
    c = get_icode(icode_file); assert(c != EOF);
    if ((c == ' ') || (c == ';')) {
      *s++ = '\0';
      *cp = c;
      return(local);
    }
    *s++ = c;
  }
}

static char *getshort (short int *sh)
{
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   if (sh != NULL)
      *sh = word;
   sprintf(local, "0x%04x", word);
   return (local);
}

static char *getshortdecimal (short int *d)
{
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   if (d != NULL)
      *d = word;
   sprintf(local, "%0d", word);
   return (local);
}

#ifdef NEVER
static char *getlab (short int *d, int labtype)
{
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   if (!((word >= 0) && (word < MAX_LINENOS))) {
      memprintf("\n*** word = %04x\n\n", word); exit(0);
   }
   if (lineno[word] == 0) {
      lineno[word] = get_next_lineno ();
//      linetype[word] = labtype;
      /* flag JUMPIF followed by LOCATE */
   }
   if (d != NULL)
      *d = word;
   sprintf(local, "L_%04x", lineno[word]);
   return (local);
}
#endif

static char *getforwardlab (short int *d)
{
   /* target for an if (..) goto skip; inst(); skip: */
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   assert((word >= 0) && (word < MAX_LINENOS));

   /* there may be several jumps to this later label */
   if (lineno[word] == 0) {
     i = get_next_lineno();
//memprintf("//*** setting lineno[0x%04x] to 0x%04x\n", word, i);
     lineno[word] = i;
   }
   if (d != NULL) *d = word;
   sprintf(local, "L_%04x", lineno[word]);
   return (local);
}

static char *getbackwardlab (short int *d)
{
   /* start of for loop */
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   assert((word >= 0) && (word < MAX_LINENOS));
   lineno[word] = get_next_lineno ();
   if (d != NULL) *d = word;
//   sprintf(local, "/*forloop*/L_%04x", lineno[word]);
   return (local);
}

static char *getuserlab (void)
{
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   sprintf(local, "U_%04x", word);
   return (local);
}

static char *nextlab (int d)
{
   static char local[7];

//   assert (lineno[d] == 0);
   lineno[d] = get_next_lineno ();
//   linetype[d] = labtype;
   /* flag JUMPIF followed by LOCATE */
   sprintf(local, "L_%04x", lineno[d]);
   return (local);
}

static char *setbackwardlab (short int d, int *linenod)
{
   static char local[64];
   int word = d;

   /* If you have the LOCATE first, the REPEAT clears it. */
//   assert(lineno[word] == 0);
   lineno[word] = get_next_lineno();
   sprintf(local, "L_%04x", *linenod = lineno[word]);
   return(local);
}

static char *setforwardlab (short int d)
{
   static char local[64];
   int word = d;

   /* but if we have already had a JUMPIF then this LOCATE clears it */
   /* This LOCATE comes before any type of jump */
   /* Could either be start of a loop, or a user label */
   assert(lineno[word] != 0);
   sprintf(local, "L_%04x", lineno[word]);
//memprintf("//*** unsetting lineno[%04x] to 0\n", word);
   lineno[word] = 0;
   return (local);
}

static char *setrepeatlab (short int d, int *linenod)
{
   static char local[64];
   int word = d;

   /* If you have the LOCATE first, the REPEAT clears it. */
   sprintf(local, "L_%04x", *linenod = lineno[word]);
//memprintf("//*** unsetting lineno[%04x] to 0\n", word);
   lineno[word] = 0;
   return(local);
}

static char *setuserlab (short int d)
{
   static char local[7];
   int word = d;
   sprintf(local, "U_%04x", word);
   return (local);
}

static char *getvar (short int *d)
{
   static char local[7];
   int i, c;
   int word = 0;

   for (i = 0; i < 2; i++) {
      word = word << 8 | (c = get_icode (icode_file));
      assert (c != EOF);
   }
   if (d != NULL) *d = word;
   sprintf(local, "V_%04x", word);
   return (local);
}

int memprintf(char *s, ...)
{
   va_list ap;
   char *buff;
   FILE *nullfile;
   int string_length;

   va_start (ap, s);
   nullfile = fopen ("/dev/null", "w");
   if (nullfile == NULL) {
      fprintf(stderr, "Major error - cannot open /dev/null\n");
      exit (1);
   }
   string_length = vfprintf(nullfile, s, ap);
   fclose (nullfile);
   buff = malloc (string_length + 1);
   vsprintf(buff, s, ap);
   va_end (ap);
   string_length = fprintf(cur_impfile, "%s", buff);
   free (buff);
   return string_length;
}