typedef struct descriptor {
 int data; /* int or real or pointer */
 short int a, b, c;
} descriptor;

#define MAX_DESCRIPTORS (1024*32)
descriptor tag[MAX_DESCRIPTORS];
static int thisitag = MAX_DESCRIPTORS; /* I'm reusing the other end of
                                          the tag array for constants. */

extern char *rawtag(int tagnum); /* should probably move all those back here */

/*
   Variable-length automatic arrays are allowed in GNU C.
   These arrays are declared like any other automatic arrays,
   but with a length that is not a constant expression.
   The storage is allocated at the point of declaration and
   deallocated when the brace-level is exited. For example: 

   FILE *concat_fopen (char *s1, char *s2, char *mode)
   {
     char str[strlen (s1) + strlen (s2) + 1];
     strcpy (str, s1);
     strcat (str, s2);
     return fopen (str, mode);
   }
 */

char *cdecl(int tagnum);
// BUG TODO when declaring a record, need to tag it with the recordformat
// so that fieldselect() can extract the correct field name from the
// corresponding record format.
char *define_tag(int tagnum, char *name, short int a, short int b, short int c)
{
  char *info;
  int t, f, u, i, s, x; /* NOTE: 'i' and 's' are not for general use here! */
  tag[tagnum].data = (int)name; /* caller is responsible for strdup if needed */
  tag[tagnum].a = a;
  tag[tagnum].b = b;
  tag[tagnum].c = c;

  /* REST IS DIAGNOSTICS */
  info = cdecl(tagnum);

  t = a>>4; f = a&15;
  x = c&7;  c >>= 3;
  s = c&1; c >>= 1;
  i = c&1;  c >>= 1;
  u = c&1;

  if (f == 11) { /* TODO: will 11 <= f <= 15 cover all arrays? */
    ARRAYDECL = TRUE;
  }
  if (((7 <= f) && (f <= 10)) && (s == 0)) {
    PROCFNMAPPRED = TRUE;
  }
  return(info);
}