/*
    Lifo.c, Copyright  (c) by Boris Lutz,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Topsy/Lifo.c,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
*/


#include "Lifo.h"
#include "Error.h"
#include "Support.h"
#include "MMHeapMemory.h"


int lifoIsEmpty(Lifo *myLifo)
{
  return (*myLifo == NULL);
}


Error lifoPush (Lifo *myLifo, void* item)
{
  LifoElem		elem;
  Error			err;


  err = hmAlloc((Address*)&elem, sizeof(LifoElemDesc));
  if ( err != HM_ALLOCOK)
  {
    return LIFO_ERROR;
  }
  elem->item = item;

  if (*myLifo == NULL)
  {
    *myLifo = elem;
    elem->next = NULL;
  }
  else
  {
    elem->next = *myLifo;
    *myLifo = elem;
  }

  return LIFO_OK;
}


Error lifoPop (Lifo *myLifo, void** item)
{
  Lifo	OldTop;


  if ( *myLifo == NULL)
  {
    return LIFO_ERROR;
  }

  OldTop = *myLifo;
  *item = (*myLifo)->item;
  *myLifo = (*myLifo)->next;
  hmFree(OldTop);

  return LIFO_OK;
}


Error lifoSelectivePop (Lifo *myLifo, void* item)
{
  Lifo	CurElem,
  PrevElem;


  if ( *myLifo == NULL)
  {
    return LIFO_ERROR;
  }

  CurElem = *myLifo;
  if (CurElem->item == item)
  {
    return lifoPop(myLifo, &item);
  }

  PrevElem = CurElem; /* make gcc happy */
  while (CurElem->item != item && CurElem->next)
  {
    PrevElem = CurElem;
    CurElem = CurElem->next;
  }
  if (CurElem->item == item)
  {
    PrevElem->next = CurElem->next;
    hmFree(CurElem);
    return LIFO_OK;
  }
  else
  {
    return LIFO_NOTFOUND;
  }
}


Error lifoFree (Lifo *myLifo)
{
  Lifo	CurTop;


  if ( *myLifo == NULL)
  {
    return LIFO_OK;
  }

  while ( (CurTop = *myLifo) )
  {
    *myLifo = (*myLifo)->next;
    hmFree(CurTop);
  }

  return LIFO_OK;
}
