char rcsid_map[] = "$Id$";

#include <stdio.h>
#include <string.h>
#include "b.h"
#include "fe.h"

Mapping globalMap;

static void growMapping ARGS((Mapping));
static int hash ARGS((Item_Set, int));

Mapping
newMapping(size) int size;
{
  Mapping m;

  m = (Mapping) zalloc(sizeof(struct mapping));
  assert(m);

  m->count = 0;
  m->hash = (List*) zalloc(size * sizeof(List));
  m->hash_size = size;
  m->max_size = STATES_INCR;
  m->set = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
  assert(m->set);

  return m;
}

static void
growMapping(m) Mapping m;
{
  Item_Set *tmp;

  m->max_size += STATES_INCR;
  tmp = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
  memcpy(tmp, m->set, m->count * sizeof(Item_Set));
  zfree(m->set);
  m->set = tmp;
}

static int
hash(ts, mod) Item_Set ts; int mod;
{
  register Item *p = ts->virgin;
  register int v;
  register Relevant r = ts->relevant;
  register int nt;

  if (!ts->op) {
    return 0;
  }

  v = 0;
  for (; (nt = *r) != 0; r++) {
    v ^= ((long)p[nt].rule) + (PRINCIPLECOST(p[nt].delta)<<4);
  }
  v >>= 4;
  v &= (mod-1);
  return v;
}

Item_Set
encode(m, ts, new) Mapping m; Item_Set ts; int *new;
{
  int h;
  List l;

  assert(m);
  assert(ts);
  assert(m->count <= m->max_size);

  if (grammarNts && errorState && m == globalMap) {
    List l;
    int found;

    found = 0;
    for (l = grammarNts; l; l = l->next) {
      Symbol s;
      s = (Symbol) l->x;

      if (ts->virgin[s->u.nt->num].rule) {
        found = 1;
        break;
      }
    }
    if (!found) {
      *new = 0;
      return errorState;
    }
  }

  *new = 0;
  h = hash(ts, m->hash_size);
  for (l = m->hash[h]; l; l = l->next) {
    Item_Set s = (Item_Set) l->x;
    if (ts->op == s->op && equivSet(ts, s)) {
      ts->num = s->num;
      return s;
    }
  }
  if (m->count >= m->max_size) {
    growMapping(m);
  }
  assert(m->count < m->max_size);
  m->set[m->count] = ts;
  ts->num = m->count++;
  *new = 1;
  m->hash[h] = newList(ts, m->hash[h]);
  return ts;
}

Item_Set
decode(m, t) Mapping m; ItemSetNum t;
{
  assert(m);
  assert(t);
  assert(m->count < m->max_size);
  assert(t < m->count);

  return m->set[t];
}

void
dumpMapping(m) Mapping m;
{
  int i;

  printf("BEGIN Mapping: Size=%d\n", m->count);
  for (i = 0; i < m->count; i++) {
    dumpItem_Set(m->set[i]);
  }
  printf("END Mapping\n");
}
