/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/*=~=~=~=~ McGill-Computer-Vision-and-Robotics-Laboratory--C-Module ~=~=~=~=
 *		
 * MODULE NAME:	symtable
 *
 * DESCRIPTION:	Implements the hashed symbol table.
 * 
 * AUTHOR/DATE:	John Lloyd, Summer 1987
 *
 *~=~=~=~=~=~= McGill-Computer-Vision-and-Robotics-Laboratory ~=~=~=~=~=~=*/

#include "cdefs.h"
#include "types.h"
#include "symbols.h"
#include "parameters.h"

SYMBOL_TABLE_ENTRY *hash_table [HASH_TABLE_SIZE], *symbol;

struct _constant_declaration{
  char *name;
  int type;
  int protection;
  void *value;
};

char *strcpy();
char *malloc();

/* create a symbol table entry with the id 'name' */

SYMBOL_TABLE_ENTRY *insertSymbol (name)
char *name;
{
 SYMBOL_TABLE_ENTRY *new;
 int index = hash (name, HASH_TABLE_SIZE);
 
 if ((new = (SYMBOL_TABLE_ENTRY *)malloc(sizeof (SYMBOL_TABLE_ENTRY)))
	  == NULL)
  { error (0, "out of memory\n");
    return (NULL);
  }
 new->next = hash_table [index];
 if ((new->name = strcpy (malloc (strlen(name)+1), name)) == NULL)
  { error (0, "out of memory\n");
    return (NULL);
  }
 hash_table[index] = new;
 return (new);
}

/* locate a symbol table entry with the id 'name' */

SYMBOL_TABLE_ENTRY *locateSymbol (name)
char *name;
{
 SYMBOL_TABLE_ENTRY *test;
 test = hash_table [hash (name, HASH_TABLE_SIZE)];
 
 while (test != NULL)
  { 
    if (strcmp (test->name, name) == 0)
       return (test);
    test = test->next;
  }
 return (test);
}

static SYMBOL_TABLE_ENTRY *symbolMark;
static int symbolIndex = 0;

SYMBOL_TABLE_ENTRY *firstSymbol()
{
	int i;

	/* start at the beginning of the symbol table */

	for (i=0; i<HASH_TABLE_SIZE; i++)
	 { if (hash_table[i])
	    { symbolIndex = i;
	      symbolMark = hash_table[i];
	      return (symbolMark);
	    }
	 }
	return (NULL);
}

SYMBOL_TABLE_ENTRY *nextSymbol()
{
	int i;

	if (symbolMark->next != NULL)
	 { symbolMark = symbolMark->next;
	   return (symbolMark);
	 }
	else
	 { for (i=symbolIndex+1; i<HASH_TABLE_SIZE; i++)
	    { if (hash_table[i])
	       { symbolIndex = i;
		 symbolMark = hash_table[i];
		 return (symbolMark);
	       }
	    }
	   return (NULL);
	 }
}


hash (string, size)
char *string;
int size;
{
 /* returns a hashed index in the range of size */
 
 int i, count = 0;
 
 for (i = 0; i < strlen (string); i++)
  { count += string[i];
  }
 return (count % size);
}

/* ----- variables for built in constants ----- */

static double pi = PI;
static double e = E;
static double rtod = RADTODEG;
static double dtor = DEGTORAD;
static double xunit_buf[3] = { 1.0, 0.0, 0.0 };
static matrix xunit = { 3, 1, 0, xunit_buf };
static double yunit_buf[3] = { 0.0, 1.0, 0.0 };
static matrix yunit = { 3, 1, 0, yunit_buf };
static double zunit_buf[3] = { 0.0, 0.0, 1.0 };
static matrix zunit = { 3, 1, 0, zunit_buf };
static double unitr_buf[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
				0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
static matrix unitr = { 4, 4, 0, unitr_buf };

/* ----- table defining the built in constants ----- */

static struct _constant_declaration constant_defs [] =
 { "PI",     DOUBLE, WRITE, (void*)(&pi),
   "E",	     DOUBLE, WRITE, (void*)(&e),
   "RTOD",   DOUBLE, WRITE, (void*)(&rtod),
   "DTOR",   DOUBLE, WRITE, (void*)(&dtor),

   "XU",     MATRIX, WRITE, (void*)(&xunit),
   "YU",     MATRIX, WRITE, (void*)(&yunit),
   "ZU",     MATRIX, WRITE, (void*)(&zunit),

   "UNITR",  MATRIX, WRITE, (void*)(&unitr),
 };

/* initialize the symbol table with pre-defined constants in the
   above table */

initSymbolTable ()
{ 	
	int i;

	SYMBOL_TABLE_ENTRY *new;
	for (i = 0; i < ARRAY_SIZE (constant_defs); i++)
	 { 
	   new = (SYMBOL_TABLE_ENTRY *) insertSymbol(constant_defs[i].name);
	   new->g.type = constant_defs[i].type;
	   new->protection = constant_defs[i].protection;

	   switch (new->g.type)
	    { case DOUBLE:
	       { new->g.val.d = *(double *)constant_defs[i].value;
		 break;
	       }
	      case INTEGER:
	       { new->g.val.i = *(int *)constant_defs[i].value;
		 break;
	       }
	      case MATRIX:
	       { new->g.val.m = (matrix *)constant_defs[i].value;
	       }
	    }
	 }
}
