/*
 * symmap.c -- map strings into UID's
 *
 *  Created May 16, 1990 by Raymie Stata
 *  C++ port on July 13, 1990 by Raymie Stata.
 *  Port back to C for spec, Sept 15, 1990 by RS
 *
 *  (c) 1990 Raymie Stata, All Rights Reserved
 */

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "symmap.h"
#include "bucket.h"

#define LOCAL static
#define IMPORT extern
#define EXPORT /* */


/* Imported variables and routines. */
#define HTSIZE 512
IMPORT char *malloc();


/* begin rep */
struct symmapstruct {
  struct ht_bucket *chains[HTSIZE];
  int next_uid;
};

struct ht_bucket {
  char *key;
  int uid;
  struct ht_bucket *next;
};
/* end rep */


/* Local variables and routines. */
LOCAL Bucket htnodes = NULL;
LOCAL Symmap symmap = NULL;

LOCAL hashfn(s)
  char *s;
{
  int h;
  for(h = 0; *s; s++) h += *s;
  return(h % HTSIZE);
}


/* Exported routines. */
EXPORT Symmap sm_init()
{
  int i;

  symmap = (Symmap) malloc(sizeof(struct symmapstruct));
  htnodes = bk_create(sizeof(struct ht_bucket));
  assert(htnodes && symmap);

  for(i = 0; i < HTSIZE; i++) symmap->chains[i] = NULL;
  symmap->next_uid = 1;
  return(symmap);    
}


EXPORT int sm_lookup(key)
  char *key;
{
  struct ht_bucket *c = symmap->chains[hashfn(key)];
  for(; c; c = c->next)  if (! strcmp(c->key, key)) return(c->uid);
  return(SM_NULL);
}


EXPORT int sm_internalize(key)
  char *key;
{
  int h = hashfn(key);
  struct ht_bucket *c = symmap->chains[h];

  for( ; c; c = c->next) if (! strcmp(c->key, key)) return(c->uid);
  assert(c = (struct ht_bucket *)bk_alloc(htnodes));

  c->key = malloc(strlen(key)+1);
  strcpy(c->key, key);
  c->uid = symmap->next_uid++;
  c->next = symmap->chains[h];
  symmap->chains[h] = c;
  return(c->uid);
}


EXPORT int sm_eq(s1, s2)
  int s1, s2;
{
  return(s1 == s2);
}


EXPORT char *sm_pname(uid)
  int uid;
{
  int h;
  struct ht_bucket *c;
  assert(uid > 0 && uid < symmap->next_uid);

  for(h = 0; h < HTSIZE; h++)
    for(c = symmap->chains[h]; c; c = c->next) if (c->uid == uid) return(c->key);

  assert(0);    /* If we got this far something's wrong. */
  return(NULL); /* Avoid dumb warnings. */
}


EXPORT char *sm_unparse(uid)
  int uid;
{
  char *pname = sm_pname(uid);
  char *ret = malloc(strlen(pname) + 1);
  assert(ret);
  strcpy(ret, pname);
  return(ret);
}
