/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
 */
/*
 * AtFS -- Attribute Filesystem
 *
 * afsymtab.c -- manage symbol table for AtFS
 *
 * Author: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: afsymtab.c[7.0] Fri Jun 25 14:32:20 1993 andy@cs.tu-berlin.de frozen $
 */

#include "atfs.h"

/*==========================================================================
 *	definition of hashtable for symbols
 *==========================================================================*/

typedef struct AfSmnt AfSyment;

struct AfSmnt { char     *symbol;
		AfSyment *next;
	      };
LOCAL AfSyment *afSymhash;

LOCAL int symtabSize;

/*==========================================================================
 *	determine hash value
 *==========================================================================*/

EXPORT int afHashval (symbol, size) /* from Aho/Ullman */
     char *symbol;
     int  size;
{
  register char *p;
  register unsigned long hval, g;

  hval = 0;
  for (p = symbol; *p != '\0'; p++) {
    hval = (hval << 4) ^ (*p);
    if ((g = hval & 0xf0000000)) {
      hval = hval ^ (g >> 24);
      hval = hval ^ g;
    }
  }
  return (hval % size);
}

/*==========================================================================
 * af_entersym -- return pointer of symbol in Symbol Table
 *                (enter symbol if necessary)
 *==========================================================================*/

EXPORT char *af_entersym (symbol)
     char *symbol;
{
  static   bool hinit = FALSE; /* indicate if hashtable is yet initialized */
  int           symlen, where;
  AfSyment      *new, *entry = NULL;

  if ((symbol == NULL) || (symbol[0] == '\0'))
    return (NULL);

  if (!hinit) {
    /* the reserved symbols could be added to the hashtable here */
    /* but I don't think that it's worthwhile */
    symtabSize = AF_SYMHASHSIZE * sizeof (AfSyment);
    if ((afSymhash = (AfSyment *)malloc ((unsigned) symtabSize)) == NULL)
      FAIL ("entersym", "malloc", AF_ESYSERR, NULL);
    /* set hashlist all zeros */
    memset ((char *)afSymhash, 0, symtabSize);
    hinit = TRUE;
  }

  /* lookup symbol */
  where = afHashval (symbol, AF_SYMHASHSIZE);
  if (afSymhash[where].symbol)  /* found something */ {
    if (!strcmp (afSymhash[where].symbol, symbol))
      return (afSymhash[where].symbol);
    else /* maybe it is somewhere down the gully */  {
      entry = &afSymhash[where];
      while (entry->next) {
	entry = entry->next;
	if (!strcmp (entry->symbol, symbol))
	  return (entry->symbol);
      }
    }
  }
  
  /* the symbol hasn't been known */
  symlen = strlen (symbol) + sizeof (char);
  if (!afSymhash[where].symbol)  /* entry is not used yet */ {
    if ((afSymhash[where].symbol = malloc ((unsigned) (symlen)))==NULL)
      FAIL ("entersym", "malloc", AF_ESYSERR, NULL);
    symtabSize += symlen;
    strcpy (afSymhash[where].symbol, symbol);
    return (afSymhash[where].symbol);
  }
  else /* hash collision! */ {
    if ((new = (AfSyment *)malloc ((unsigned) sizeof (AfSyment))) == NULL)
      FAIL ("entersym", "malloc", AF_ESYSERR, NULL);
    symtabSize += sizeof (AfSyment);
    if ((new->symbol = malloc ((unsigned) (symlen))) == NULL)
      FAIL ("entersym", "malloc", AF_ESYSERR, NULL);
    symtabSize += symlen;
    strcpy (new->symbol, symbol);
    new->next = NULL;
    entry->next = new;
      return (new->symbol);
    } /* endif */
}

/*==========================================================================
 * af_enterhost -- enter hostname into symbol table (do only once)
 *==========================================================================*/

EXPORT char *af_enterhost (hostname)
     char *hostname;
{
  register char *hostsym;

  hostsym = af_gethostname();

  if (strcmp (hostname, hostsym))
    return (af_entersym (hostname));
  else
    return (hostsym);
}


/*==========================================================================
 * af_enterdomain -- enter domain name into symbol table (do only once)
 *==========================================================================*/

EXPORT char *af_enterdomain (domain)
     char *domain;
{
  register char *domainsym;

  domainsym = af_getdomain();

  if (strcmp (domain, domainsym))
    return (af_entersym (domain));
  else
    return (domainsym);
}

