#include <yafl_rnt.h>
#include <assert.h>
#include <stdio.h>

static unsigned used_modules = 0;
static module_dual* module_dictionary[MAX_MODULES];

/**********************************************************/
void register_module YPARAMS2(module_dual*,module)
    {
    char         a[200];

    assert(module!=NULL);

    /* To_Delete
    if ((module->ymelt_ready)&&(module->inlined))
  	{
        sprintf(a,"attempt to register module '%s' ymelt ready and containing C inlines\n");
        emit_stdout(a);
        exit();
        } 
END To_Delete */

    assert(used_modules<MAX_MODULES);
    module_dictionary[used_modules] = module;
    used_modules ++;
    }
/*****************************************************/
module_dual* get_module_by_name YPARAMS2(char*,name)
    {
    unsigned i;

    assert(name!=NULL);
    
    for (i=0; i<MAX_MODULES; i++)
      if (strcmp(name, module_dictionary[i]->name) == 0)
        return module_dictionary[i];

    return NULL;
    }
/*****************************************************/
module_dual* get_module YPARAMS2(unsigned,num)
    {
    module_dual *result;

    if (num>=used_modules) 
      result=NULL;
     else 
      result=module_dictionary[num];

    return result;
    }
/*****************************************************/
unsigned get_module_count YPARAMS0
    {
    return used_modules; 
    }
/*****************************************************/
/*
void mark_module_as_interpreted YPARAMS2(char*,name)
    {
    MODULE_ENTRY *tmp;
    char         a[200];

    assert(name!=NULL);

    tmp=seek_module_entry(name);

    if (tmp==NULL)
        {
        sprintf(a,"attempt to interprete module '%s' not in module dictionary\n",name);
        emit_stdout(a);
        exit();
        }

    if (!(tmp->ymelt_ready))
        {
        sprintf(a,"attempt to interprete module '%s' not ymelt ready\n",name);
        emit_stdout(a);
        exit();
        }

    if (tmp->inline)
        {
        sprintf(a,"attempt to interprete module '%s' containing C inlines\n",name);
        emit_stdout(a);
        exit();
        }

    tmp->interpreted=TRUE;
    }

int check_module_dictionary_integrity YPARAMS0
    {
    MODULE_ENTRY	*act_mod;
    char		result;

    act_mod=md.first;

    result=TRUE;

    while (act_mod!=NULL && result)
        {
        result=(strlen(act_mod->name)>0);
	result=result && ((act_mod->ymelt_ready && !act_mod->inline)
                         || (!act_mod->ymelt_ready && act_mod->inline));
	result=result && ((act_mod->binary && act_mod->yim!=NULL)
                         || (!act_mod->binary && act_mod->yim==NULL));
        result=result && (!act_mod->interpreted || act_mod->ymelt_ready);

        if (act_mod->next!=NULL) result=result && (act_mod->next->prec==act_mod);
        if (act_mod->prec!=NULL) result=result && (act_mod->prec->next==act_mod);

        act_mod=act_mod->next;
        }

    assert(!result || act_mod==NULL);

    return result;
    }
*/
   
void dump_module_dictionary YPARAMS0
    {
    module_dual	*module;
    char       	a[200];
    unsigned 	i;

    emit_stdout("MODULE DICTIONARY\n");
    emit_stdout("=================\n");
    emit_stdout("\n");

    for(i=0;i<MAX_MODULES;i++)
       {
       sprintf(a,"NAME         : %s\n",module_dictionary[i]->name);
       emit_stdout(a);

       /* To_Delete
       if (module_dictionary[i]->binary) emit_stdout("     BINARY : true\n");
       else emit_stdout("     BINARY : false");

       if (module_dictionary[i]->interpreted) emit_stdout("INTERPRETED : true\n");
       else emit_stdout("INTERPRETED : false");

       if (module_dictionary[i]->ymelt_ready) emit_stdout("YMELT READY : true\n");
       else emit_stdout("YMELT_READY : false");

       if (module_dictionary[i]->inlined) emit_stdout("  C INLINES : true\n");
       else emit_stdout("  C INLINES : false");

       if (module_dictionary[i]->yim!=NULL) emit_stdout("        YIM : not VOID\n");
       else emit_stdout("        YIM : VOID");
END To_Delete */
       }
    
    emit_stdout("\n");
    }


module_dual *first_module YPARAMS0
{
  if (used_modules > 0)
    return module_dictionary[0];
  else
    return (NULL);
}

module_dual *last_module YPARAMS0
{
  if (used_modules > 0)
    return module_dictionary[used_modules - 1];
  else
    return (NULL);
}

module_dual *next_module YPARAMS2(module_dual *,  pm)
{
  int i;
  for (i = 0; i < used_modules; i++)
  {
    if (module_dictionary[i] == pm)
    {
    if (i == used_modules - 1)
      return NULL;
    else
      return module_dictionary[i + 1];
    }
  }
}

module_dual *prev_module YPARAMS2(module_dual *,  pm)
{
  int i;
  for (i = 0; i < used_modules; i++)
  {
    if (module_dictionary[i] == pm)
    {
    if (i == 0)
      return NULL;
    else
      return module_dictionary[i - 1];
    }
  }
}

char *module_name YPARAMS2(module_dual *,  pm)
{
  assertp(pm);
  if (pm->name)
    return (pm->name);
  else
    return("<undefined>");
}

char *file_name YPARAMS2(module_dual *,  pm)
{
  assertp(pm);
/* the file name can be NULL if no file was found for this module */  
  return (pm->source_file_name);
}

unsigned module_endline YPARAMS2(module_dual *,   pm)
{
  assertp(pm);
  return (pm->line_count);
}

minimal_dual *first_class YPARAMS2(module_dual *,    pm) /* _of_module */
{
  assertp(pm);
  return (pm->first_class);
}

minimal_dual *last_class YPARAMS2(module_dual *,  pm) /* _of_module */
{
  assertp(pm);
  return (pm->last_class);
}
/*******************************************/
int yafl_profile;
/*******************************************/
void reset_profile_info YPARAMS2(module_dual *, pm)
{
  int i;
  unsigned *p;

  assertp(pm);
  if (pm->line_count > 0 && pm->y_profile_lines != NULL)
    {
    p = pm->y_profile_lines;
    for (i=0; i < pm->line_count; i++)
      {
      *p = 0;
      p++;
      }
    }
}
/*******************************************/
obj_ptr clone_profile_info YPARAMS2(module_dual *, pm)
{
  unsigned *p;
  int i;

  assertp(pm);
  if (pm->line_count > 0 && pm->y_profile_lines != NULL)
    {
    p = y_alloc(pm->line_count, 1, &YD_INT);
    memcpy (p, pm->y_profile_lines, alloc_size (pm->line_count, 1, &YD_INT));
    return p;
    }
  return NULL;
}
