/**************************************************************
 *       memo.c - LBM Interpreter Memory Functions
 **************************************************************/
/***********************************************
 (C) Copyright 1993-1994; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************************
 $Log: memo.c,v $
 * Revision 1.4  1994/11/14  11:24:27  lotos
 * avoid name collision
 *
 * Revision 1.3  1994/10/17  16:41:02  lotos
 * cosmetics
 *
 * Revision 1.2  1993/10/19  19:19:04  lotos
 * remove malloc.h for portability ...
 *
 * Revision 1.1  1993/10/16  10:54:04  lotos
 * Initial revision
 *
 **********************************************
 $Id: memo.c,v 1.4 1994/11/14 11:24:27 lotos Exp $
 **********************************************/

/* KJT 11/03/98: added for NS/OS */

#ifndef __NeXT__
#include <malloc.h>
#endif

#include "swbus.h"

PUBLIC char*
emalloc (i)
  int i;
{
  char *p;

  assert (i > 0);

  p = malloc ((unsigned)i);
  if (p == NULL) {
    (void)fprintf (stderr, "Out of memory\n");
    exit (1);
  }
  return p;
}

/****** SPECIFICATIONS ******/

PUBLIC spe
new_spe ()
{
  spe S;

  S = (spe)emalloc (sizeof (struct Spe));

  S->code          = 0;
  S->name          = NULL;
  S->lbmroot       = NULL;
  S->BUTlist       = NULL;
  S->alroot        = NULL;
  S->ATable        = NULL;
  S->SymbolTable   = NULL;
  S->ldi           = -1;
  S->lastBUTnumber = 1;
  S->lastPI        = 1;
  S->lastOffId     = 1;
  S->lastUID       = 1;
  S->grnl          = NULL;
  S->kt            = NULL;
  S->keepguards    = FALSE;
  S->doph          = FALSE;
  S->ph            = NULL;
  S->soffs         = NULL;
  S->cfg.rndm      = NULL;
  return S;
}

PUBLIC void
free_spe (S)
  spe S;
{
  int cnt;

  assert (S != NULL);

  if (S->name != NULL) {
    free (S->name);           /* a strdup was done when building S  */
    S->name = NULL;
  }
  if (S->lbmroot != NULL) {
    cnt = (int)takeclr (c_refcount, S->lbmroot);
    cnt--;
    assert (cnt >= 0);
    if (cnt < 1) {
      kill_tree (S->lbmroot);   /* kills the tree, including ATable */
      S->lbmroot = NULL;
      /* There, grnl, SymbolTable should be freed, if needed */
    }
    else {
      find_attr (c_refcount, S->lbmroot)->value = (CLR_TYPE)cnt;
    }
    S->lbmroot = NULL;
  }
                              /* SymbolTable, etc, as they are colours */
  S->BUTlist = NULL;
  S->alroot  = NULL;
  S->ATable  = NULL;
  S->ldi     = -1;
  S->lastBUTnumber = 1;
  S->lastPI        = 1;
  S->lastOffId     = 1;
  S->lastUID       = 1;
  S->grnl = NULL;

  if (S->kt != NULL) {
    free_kt (S->kt);
    S->kt = NULL;
  }
  S->keepguards = FALSE;
  if (S->doph) {
    kill_tree (S->ph);
    S->ph = NULL;
    S->doph = FALSE;
  }
  if (S->soffs != NULL) {
    free_sset_off (S->soffs);
    S->soffs = NULL;
  }
  S->cfg.rndm = NULL;
  free ((char*)S);
}

/****** ENVIRONMENT ******/

PUBLIC void
free_environ (env)
  xnviron env;
{
  int i;

  /* clearing values */
  for (i = 0; i < env->size; i++)
    if (reset_var (env->data[2*i+1]))
      fatal_error ("Cannot clear variable", __FILE__, __LINE__);
  /* Freeing variables */
  for (i = 0; i < env->size; i++)
    if (free_var (env->data[2*i+1]))
      fatal_error ("Cannot free variable", __FILE__, __LINE__);
  fI2T ((CLR_TYPE)env);
}

/****** KERNEL TREE ******/

PUBLIC krnlt
new_kt ()
{
  krnlt kt;

  kt = (krnlt)emalloc (sizeof (struct Krnlt));

  kt->uid   = -1;
  kt->class = LUNDEFINED;
  kt->env   = NULL;
  kt->lb    = NULL;
  kt->fth   = NULL;
  kt->son1  = NULL;
  kt->son2  = NULL;
  kt->xto   = NOCHOOSEN;
  kt->BUT   = -1;
  kt->pi    = -1;
  kt->ph    = NULL;
  kt->grdl  = NULL;
  kt->soffs = NULL;
  kt->g     = LNOGATE;
  kt->gtes  = NULL;
  kt->rlb   = NULL;
  return kt;
}

PUBLIC void
free_kt (kt)
  krnlt kt;
{
  assert (kt != NULL);

  kt->uid   = -1;
  kt->class = LUNDEFINED;
  kt->lb    = NULL;
  kt->fth   = NULL;
  if (kt->son1 != NULL) {
    free_kt (kt->son1);
    kt->son1 = NULL;
  }
  if (kt->son2 != NULL) {
    free_kt (kt->son2);
    kt->son2 = NULL;
  }
  if (kt->env != NULL) {
    free_environ (kt->env);
    kt->env = NULL;
  }
  kt->xto   = NOCHOOSEN;
  kt->BUT   = -1;
  kt->pi    = -1;
  kt->ph    = NULL; /* I think it shouldn't be freed */
  if (kt->grdl != NULL) {
    free_CNDlist (kt->grdl);
    kt->grdl = NULL;
  }
  if (kt->soffs != NULL) {
    free_sset_off (kt->soffs);
    kt->soffs = NULL;
  }
  kt->g     = LNOGATE;
  if (kt->gtes != NULL) { /* a INTdup was done */
    fIL ((CLR_TYPE)kt->gtes);
    kt->gtes  = NULL;
  }
  if (kt->rlb != NULL) {
    free_rlbset (kt->rlb);
    kt->rlb = NULL;
  }
  free ((char*)kt);
}

/****** CONDITIONS ******/

PUBLIC cond
new_cond ()
{
  cond cnd;

  cnd = (cond)emalloc (sizeof (struct Cond));

  cnd->val1 = NULL;
  cnd->val2 = NULL;
  return cnd;
}

PUBLIC void
free_cond (g)
  cond g;
{
  assert (g != NULL);

  kd_free (g->val1);
  kd_free (g->val2);
  free ((char*)g);
}

PUBLIC CNDlist
new_CNDlist ()
{
  CNDlist cl;

  cl = (CNDlist)emalloc (sizeof (struct CondList));

  cl->c    = NULL;
  cl->next = NULL;
  return cl;
}

PUBLIC void
free_CNDlist (cl)
  CNDlist cl;
{
  assert (cl != NULL);

  free_cond (cl->c);
  cl->c = NULL;
  if (cl->next != NULL) {
    free_CNDlist (cl->next);
    cl->next = NULL;
  }
  free ((char*)cl);
}

/****** EXPERIMENTS ******/

PUBLIC exper
new_exper ()
{
  exper e;

  e = (exper)emalloc (sizeof(struct Exper));

  e->type  = NOTYPE;
  e->sort  = NOSORT;
  e->var   = NOVAR;
  e->ldiui = 0;
  e->vrlst = NULL;
  e->val   = NULL;
  return e;
}

PUBLIC void
free_exper (e)
  exper e;
{
  assert (e != NULL);

  e->type = NOTYPE;
  e->sort  = NOSORT;
  e->var   = NOVAR;
  e->ldiui = 0;
  if (e->vrlst != NULL) {
    fIL ((CLR_TYPE)e->vrlst);
    e->vrlst = NULL;
  }
  if (e->val != NULL) {
    kd_free (e->val);
    e->val = NULL;
  }
  free ((char*)e);
}

PUBLIC exper*
new_exper_array (size)
  int size;
{
  int   i;
  exper *el;

  el = (exper*)emalloc (size * sizeof (exper));

  for (i = 0; i < size; i++)
    el[i] = NULL;

  return el;
}

PUBLIC void
free_exper_array (max, el)
  int   max;
  exper *el;
{
  int i;

  assert (el != NULL);

  for (i = 0; i < max; i++)
    if (el[i] != NULL) {
      free_exper (el[i]);
      el[i] = NULL;
    }
  free ((char*)el);
}

/****** OFFERTS ******/

PUBLIC soffert*
new_soffert ()
{
  soffert *soff;

  soff = (soffert*)emalloc (sizeof (soffert));

  soff->OffId = -1;
  soff->ready = FALSE;
  soff->g     = LNOGATE;
  soff->nexp  = 0;
  soff->expl  = NULL;
  soff->prdl  = NULL;
  soff->ktl   = NULL;
  soff->next  = NULL;
  return soff;
}

/*
 * Frees a soffert node
 */
PUBLIC void
free_soffert (soff)
  soffert *soff;
{
  assert (soff != NULL);

  soff->OffId = -1;
  soff->ready = FALSE;
  soff->g     = LNOGATE;
  if (soff->nexp > 0) {
    free_exper_array (soff->nexp, soff->expl);
    soff->nexp = 0;
    soff->expl = NULL;
  }
  if (soff->prdl != NULL) {
    free_CNDlist (soff->prdl);
    soff->prdl = NULL;
  }
  if (soff->ktl != NULL) {
    fIL ((CLR_TYPE)soff->ktl);
    soff->ktl = NULL;
  }
  soff->next = NULL;
  free ((char*)soff);
}

/*
 * Frees a soffert list
 */
PUBLIC void
free_sset_off (soff)
  soffert *soff;
{
  soffert *next;

  assert (soff != NULL);

  do {
    next = soff->next;
    free_soffert (soff);
    soff = next;
  } while (soff != NULL);
}

/****** RELABELING ******/

PUBLIC rlbset*
new_rlbset ()
{
  rlbset *rlb;

  rlb = (rlbset*)emalloc (sizeof (rlbset));

  rlb->actual = NULL;
  rlb->formal = NULL;
  return rlb;
}

PUBLIC void
free_rlbset (rlb)
  rlbset *rlb;
{
  assert (rlb != NULL);

  fIL ((CLR_TYPE)rlb->actual);
  rlb->actual = NULL;
  fIL ((CLR_TYPE)rlb->formal);
  rlb->formal = NULL;
  free ((char*)rlb);
}

