
/* Initialize subroutine module */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <module.h>
#include "maininit.h"

/* external functions */
extern mod_exec      *modlink();
extern mod_exec      *modloadp();

/* external variables */
extern SUBMODHANDLE **_handles;
extern int            _handlenum;

/* local function */
static int            findfreehandle(void);


/*
 * _ i n i t _ c
 */
int _init_c(char *submodname, long rev, long rv)
{
  int       i, datasize;
  mod_exec *submod;
  static init = 0;

  if ((submod = modlink(submodname, mktypelang(MT_SUBROUT,ML_OBJECT))) == (mod_exec *) -1) {
    if ((submod = modloadp(submodname, MP_OWNER_EXEC, NULL)) == (mod_exec *) -1)
      return((int) submod);
  }

  datasize = (submod->_mdata + 8) & 0xfffffffc;  /* alignment */
  
  if( datasize < 2500 ) datasize = 2500;	/* patch !? */
  
  if( init == 0 )
  {
    if ((_handles = (SUBMODHANDLE **) realloc((char *) _handles,
      sizeof(*_handles) * (_handlenum + HANDLECHUNK))) == NULL)
      return(-1);
    memset((char *) (_handles + _handlenum), 0,
      sizeof(*_handles) * HANDLECHUNK);
    _handlenum += HANDLECHUNK;
    init = 1;
  }

  if ((_handles[rv] = (SUBMODHANDLE *) malloc(sizeof(**_handles))) == NULL)
    return(-1);
  _handles[rv]->submod = submod;
  _handles[rv]->globmemsize = datasize;
  if ((_handles[rv]->globmem = (char *) malloc(datasize)) == NULL) {
    free(_handles[rv]);
    return(-1);
  }
  memset((char *) _handles[rv]->globmem, 0, datasize); /* set glob-mem to 0 */
  return(rv);
}


/*
 * f i n d f r e e h a n d l e
 */
static int findfreehandle(void)
{
  int i;
  
  for (i = 0; i < _handlenum; i++) {
    if (_handles[i] == NULL)
      break;
  }

  return(i == _handlenum ? -1 : i);
}


/*
 * s h o w s u b m o d s
 */
void showsubmods(void)
{
  int i;

  for (i = 0; i < _handlenum; i++) {
    if (_handles[i] != NULL)
      fprintf(stderr, "Subroutine module '%s' has %d Bytes at %08X\n",
        (char *) _handles[i]->submod + _handles[i]->submod->_mh._mname,
         _handles[i]->globmemsize, _handles[i]->globmem);
  }
}


/*
 * t e r m
 */
int term(int submodno)
{
  if (_handles == NULL)
    return(-1);
  if (submodno >= _handlenum)
    return(-1);
  if (_handles[submodno] != NULL) {
    if(_handles[submodno]->submod)
      munlink(_handles[submodno]->submod);
    if(_handles[submodno]->globmem)
      free(_handles[submodno]->globmem);
    free(_handles[submodno]);
    _handles[submodno] = NULL;
    return(0);
  }
  return(-1);
}