//Copyright, 2001-2003, Astra Network Inc.  All Rights Reserved

//This source code has been published by Astra Network Inc. However, any
//use, reproduction, modification, distribution or transfer of this
//software, or any software which includes or is based upon any of this
//code, is only permitted if expressly authorized by a written license
//agreement from Astra. Contact your Astra representative directly for
//more information.

#include <string.h>
#include <stdio.h>

#include "module_load.h"
#include "global_bits.h"

/*@null@*/ modlist_entry_t *modtable = NULL;

// walk the modtable and ensure all references are resolved
void
checkmodules (void)
{
  int i, j, good;

  if (modtable == NULL)
    {
      fatal ("Internal error: NULL modtable");
    }

  // compare the pcode module table
  for (i = 0; pcode_module_table[i][0] != '\0'; i++)
    {
      good = 0;
      // with the loaded module table
      for (j = 0; modtable[j].module != NULL; j++)
	{
	  // if there is no keyword, we are really broken
	  if (modtable[j].module->keyword == NULL)
	    {
	      fatal ("Internal error: NULL modtable[].module->keyword");
	    }
	  // if we match the keyword, we are good
	  if (strcmp (pcode_module_table[i], modtable[j].module->keyword) ==
	      0)
	    {
	      good = 1;
	    }
	}
      // if we have gotten this far with no match, we have a fatal problem
      // usual cause would be pcode which needs a module we forgot to include
      if (good == 0)
	{
	  fatal ("Module reference \"%s\" in pcode cannot be resolved!",
		 pcode_module_table[i]);
	}
    }
}

void
initmodules (void)
{
  int i, j, init;

  if (modtable == NULL)
    {
      fatal ("Internal error: NULL modtable in initmodules");
    }

  for (i = 0; modtable[i].module != NULL; i++)
    {
      init = 0;
      if (modtable[i].module->keyword == NULL)
	{
	  fatal ("Internal error: NULL modtable[].module->keyword");
	}
      for (j = 0; pcode_module_table[j][0] != '\0'; j++)
	{
	  if (strcmp (pcode_module_table[j], modtable[i].module->keyword) ==
	      0)
	    {
	      init = 1;
	      break;
	    }
	}
      if (init == 0)
	{
	  if (verbose != 0)
	    printf ("Initializing module \"%s\"\n",
		    modtable[i].module->keyword);
	  (void) (modtable[i].module->module_init) ();	//XXXX should we ignore the return value?
	}
    }
}

void
deinitmodules (void)
{
  int i, j;
  static int deinited = 0;

  // make sure this is only called once
  if (deinited == 1)
    return;
  deinited = 1;

  // make sure we haven't corrupted anything
  if (modtable == NULL)
    {
      fatal ("Internal error: NULL modtable in dinitmodules");
    }

  // walk the table of loaded modules
  for (i = 0; modtable[i].module != NULL; i++)
    {
      // catch for more corruption - prevents assumptions from segv'ng
      if (modtable[i].module->keyword == NULL)
	{
	  fatal ("Internal error: NULL modtable[].module->keyword");
	}
      for (j = 0; pcode_module_table[j][0] != '\0'; j++)
	{
	  // if we have refered to it in the pcode, we want to call the
	  // deinit function provided with the module
	  if (strcmp (pcode_module_table[j], modtable[i].module->keyword) ==
	      0)
	    {
	      if (verbose != 0)
		printf ("Deinitializing module \"%s\"\n",
			modtable[i].module->keyword);
	      (modtable[i].module->module_deinit) ();
	      break;
	    }
	}
    }
}
