/*
 *	symtab.c
 *
 * This part was taken from `s2latex', a scribe-to-latex converter by
 * Van Jacobson, Lawrence Berkeley Laboratory.
 */

#include <stdio.h>
#ifdef __STDC__
#  include <stdlib.h>
#  include <string.h>
#else
#  include <strings.h>
#endif

#include "texchk.h"
#include "cmds.h"


#define HASHSIZE	127

static Latex_Command	*sthash[HASHSIZE];


   static int
SYMHASH (str)
   char *str;
{
   unsigned int h;

   h = *str++;
   for( ; *str != '\0'; str++ ) {
	h += (*str);
	h &= 0xffff;
   }
   return( h % HASHSIZE );
}


   Latex_Command *
command_lookup (command)
   char *command;
{
   Latex_Command *s;
   int hashval = SYMHASH(command);

   s = sthash[hashval];
   while( s  &&  strcmp(command, s->s_text) )
	s = s->s_next;

   if( s )
	return(s);

   /* Not found, if -a flag, return ... */
   if( all_unknown_cmds )
	return(NULL);

   /* ... else make a new struct and add it to cmdtable */

   if( (s = (Latex_Command *) malloc(sizeof(Latex_Command))) == NULL
      || (s->s_text = (char *) malloc(strlen(command) + 1)) == NULL ) {
	fprintf(stderr, "Out of memory\n");
	exit(10);
   }

   strcpy(s->s_text, command);
   s->is_math_mode_only = 0;
   s->flags = 1;

   /* add it to the table */
   s->s_next = sthash[hashval];
   sthash[hashval] = s;

   return(NULL);
}


   void
init_cmdtable (debug_flag)
   int debug_flag;
{
   Latex_Command *cmd, *s;
   int hashval;

   for( cmd = Command_Table ; cmd->s_text != NULL ;  cmd++ ) {

	hashval = SYMHASH(cmd->s_text);

	if( debug_flag ) {
	   /* search this command */
	   s = sthash[hashval];
	   while( s  &&  strcmp(cmd->s_text, s->s_text) )
	      s = s->s_next;

	   if( s != NULL ) {	/* found it ! */
	      printf("(La)TeX command `\\%s' exists twice, please fix this!\n",
			cmd->s_text);
	      continue;		/* don't add this struct */
	   }
	}

	/* add the struct to hash table */
	cmd->s_next = sthash[hashval];
	sthash[hashval] = cmd;
   }
}


/*** Routinen zum sequentiellen Durchwandern der Hashtabelle (br) ***/
static int table_pos = HASHSIZE;
static Latex_Command *current_pos = NULL;

   static void
begin_hashread ()
{
   table_pos = -1;
   current_pos = NULL;
}

   static Latex_Command *
hashread ()
{
   if( current_pos != NULL )
	current_pos = current_pos->s_next;

   /* if next entry == NULL, find first non empty slot */
   while( current_pos == NULL ) {
	table_pos++;
	if( table_pos >= HASHSIZE )
	   break;	/* remember: (current_pos == NULL) is still true */
   	current_pos = sthash[table_pos];
   }

   return(current_pos);
}

   static void
end_hashread ()
{
   table_pos = HASHSIZE;  /* -> next hashread() returns NULL */
   current_pos = NULL;
}


   void
list_undefined_commands()
{
   Latex_Command *s;

   puts("\n\nLIST OF UNKNOWN COMMANDS:\n");
   begin_hashread();
   while( (s = hashread()) != NULL ) {
	if( s->flags )
	   printf("   \\%s\n", s->s_text);
   }
   end_hashread();
   putchar('\n');
}
