
/*
   This software is copyright 1989 by John Dunning.  See the file
   'COPYLEFT.JRD' for the full copyright notice.
*/

/* symbol table code */

#include "util.h"
#include "symtab.h"
#include "parse.h"
#include "global.h"
#include <stdio.h>

#define	HASHMOD	53

#define CASE_INSENSITIVE 1

struct sym * symtab[HASHMOD];

void string_upcase(str)
char * str;
{
#ifdef CASE_INSENSITIVE
  char c;

  for( ; c = *str ; str++)
	if ((c >= 'a') && (c <= 'z'))
		*str = c - 0x20;
#endif
}
  
int hash(str)
char * str;
{
  int accum;
  char c;

  for (accum = 0 ; c = *str++ ; )
	{
#ifdef CASE_INSENSITIVE
	c = toupper(c);
#endif
	accum = ((accum << 1) & 0x3FFF) ^ c;
	}
  return(accum % HASHMOD);
}

struct sym * find_sym(name, new_ok)
char * name;
int new_ok;
{
  struct sym * sym_p;
  int idx;

  idx = hash(name);
  for (sym_p = symtab[idx] ; sym_p ; sym_p = sym_p->next)
	if (string_equal(sym_p->name, name))
		return(sym_p);

  if (!new_ok)
	return(0);

  sym_p = (struct sym * )malloc((sizeof (struct sym )) + strlen(name) + 1);
  sym_p->value = 0;
  sym_p->flags = 0;
  sym_p->nbr = -1;
  strcpy(sym_p->name, name);
  string_upcase(sym_p->name);
  sym_p->next = symtab[idx];
  symtab[idx] = sym_p;
  return(sym_p);
}

struct sym * assign_sym(name, value, no_redef)
char * name;
int value;
int no_redef;
{
  struct sym * sym_p;

  sym_p = find_sym(name, 1);
  if (no_redef && (sym_p->flags & DEFINED))
	if (sym_p->value != value)
		barf("'%s' redefined: %X vs %X\n", name, sym_p->value, value);
  sym_p->value = value;
  sym_p->flags |= DEFINED;
  return(sym_p);
}

set_label()
{
  if (p.label)
	{
	assign_sym(p.label, pc, 1);
	if (!p.opcode)
		{
		list_v = pc;
		list_v_p = 1;
		}
	    else
		{
		list_pc = pc;
		}
	}
}

init_sym()
{
  int i;

  for (i = 0 ; i < HASHMOD ; i++)
	symtab[i] = 0;
}

describe_symtab()
{
  int i, j;
  struct sym * sym_p;

  for (i = 0 ; i < HASHMOD ; i++ )
	{
	for (j = 0, sym_p = symtab[i] ; sym_p ; j++)
		sym_p = sym_p->next;
	printf("Bucket %d contains %d syms\n", i, j);
	}
}

map_syms(fun)
void (* fun)();
{
  struct sym * sym_p;
  int i;

  for (i = 0 ; i < HASHMOD ; i++ )
	{
	for (sym_p = symtab[i] ; sym_p ; )
		{
		(*fun)(sym_p);
		sym_p = sym_p->next;
		}
	}
}

#ifdef DEBUG
dump_syms()
{
  char * name[32];
  int i, j;
  struct sym * sym_p;
  FILE * f;

  sprintf(name, "pass%d.sym", pass);
  f = fopen(name, "w");
  for (i = 0 ; i < HASHMOD ; i++ )
	{
	for (j = 0, sym_p = symtab[i] ; sym_p ; j++)
		{
		fprintf(f, "%s:\t\t%X\n", sym_p->name, sym_p->value);
		sym_p = sym_p->next;
		}
	}
  fclose(f);
}
#endif

