/*
**    copyright (c) 1995  Birk Huber
*/

#include "pelsymbl.h"

#define HASHSIZE 100
static Sym_ent hashtab[HASHSIZE];

/*-----------------------------------------------------------------
empty_symbol_table()

free all data structures on the symbol table;
------------------------------------------------------------------*/
void init_symbol_table()
{ int i;
 for(i=0;i<HASHSIZE;i++) hashtab[i]=0;
}


void empty_symbol_table()
{
int i;
Sym_ent np,np1;
for(i=0;i<HASHSIZE;i++) {
   np=hashtab[i];
   while(np!=0) { np1=np;
                  np=np->next;
                  free_Gen_list(np1->def);
                  mem_free(np1->name); 
                  mem_free(np1); 
                 }
    }
}

/*-------------------------------------------------------------------
hashing functiion
---------------------------------------------------------------------*/
int hash(char *s)
{
 int hashval=0;
 while( *s !='\0') hashval+=*s++;
 return hashval % HASHSIZE;
}

/* -----------------------------------------------------------------
  lookup takes a string and returns the value on
   the hashtable corresponding to the string, or returns NULL if  
    there is no such entry
----------------------------------------------------------------- */

Sym_ent Slookup(char *s)
 { Sym_ent np;
   for(np=hashtab[hash(s)]; np!=0;np=np->next)
       if (strcmp(s,np->name)== 0) return(np);
  return 0;
  }

/* --------------------------------------------------------------------
Sym_ent install(char *s, Gen_node t)
 if s is already on the symbol table and is unlocked its value
     is freed and replaced by t;
 if s is already on the symbol table and is locked a warning is 
     printed to stderr, and NULL is returned.
 otherwise a new_node is created and the values for s and t are 
     placed on the symbol table

Error Conditions:
 if either s or t is NULL then nothing is done and NULL is returned
 A malloc failure in the attempt to create a newnode is treated
  as an unrecoverable error.
--------------------------------------------------------------------*/ 

Sym_ent install(char *s, Gen_node t)
{
 Sym_ent np,lookup();
 int hashval;

 if (s==NULL||t==NULL) return NULL;
 if((np=Slookup(s))==NULL) {
    np=(Sym_ent)mem_malloc(sizeof(struct Sym_ent_tag)); 
    if (np==NULL) bad_error("malloc bad malloc in install");
    np->name=Copy_String(s); 
    hashval=hash(np->name);
    np->next=hashtab[hashval];
    hashtab[hashval]=np;
    np->lock=0;
    np->def=t;
 }
 else
    if (np->lock==0){
         free_Gen_list(np->def);
         np->def=t;
         np->lock=0;
    }
    else {
      fprintf(stderr /* was Pel_Err */,"warning trying to reinstall a reserved symbol (%s)\n",s);
     return NULL;
    }
return np;
}

/* ---------------------------------------------------------------

Sym_ent lock(Sym_ent s) 
   Sets lock switch on Symbol table entry so that it is marked as 
        belonging to a reserved word (If s is NULL does nothing).
   return s;

Int locked(Sym_ent s) 
    Returns value of lock switch on s if s is nonNULL. If s is NULL
    returns 0 indicate symbol is unlocked (this case could legitimatly
    happen if one does try to lock the result of a lookup on a string 
    wich has no value on the symbol table. Such a symbol is undefined
    and clearly should not be considered reserved).
-----------------------------------------------------------------*/
  
Sym_ent lock(Sym_ent s)
{ if (s!=NULL) s->lock=1;
  return s;}

int locked(Sym_ent s)
{ if (s==NULL) return 0;
  return s->lock;}


syntax highlighted by Code2HTML, v. 0.9.1