/*****************************************************
* Unit:    stacks           release 0.4              *
* Purpose: general manipulation with FIFO structures *
* Licency: GPL or LGPL                               *
******************************************************/
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#ifdef Streams
 #include <iostream.h>
#endif

#include "typedfs.h"
#include <stacks.h>


//Constructors Of set class
stack::stack(void)
{
 data=NULL;
 Level=Allocated=0;
}


stack &stack::operator=(const stack & s)
{
 erase(*this);
 if(s.Level<=0) return(*this);

 data=(int *)malloc(s.Level*sizeof(int));
 if(data==NULL)
     {
     RaiseError(StackId|No_Memory,this); //Memory Exhausted
     return(*this);
     }
 Allocated=Level=s.Level;
 memcpy(data,s.data,Level*sizeof(int));
 return(*this);
}

//Destructor Of class set
//stack::~stack(void)
//{
// erase(*this);
//}


int stack::pop(void)
{
 if(Level<=0)
   {
   return(0);
   }
 return(data[--Level]);
}


void stack::push(int value)
{
 if(Allocated<=Level)
   {
   if(data==NULL)
      {
      data = (int *)malloc(16*sizeof(int));
      Allocated=16;
      }
   else
      {
      Allocated += 16;
      void *cpdata = realloc(data,Allocated*sizeof(int));
      if(cpdata==NULL) free(data);
      data = (int *)cpdata;
      }

   if(data==NULL)
     {
     Allocated=Level=0;
     RaiseError(StackId|No_Memory,this); //Memory Exhausted
     }
   }
 data[Level++]=value;
}


int stack::operator[](int i) const
{
 if(i>Level) return(0);
 return(data[Level-i]);
}


void erase(stack & s)
{
 if(s.data!=NULL)
   {
   free(s.data);
   s.data=NULL;
   }
 s.Allocated=s.Level=0;
}


/*This procedure verifies integrity of given object ==0 OK  !=0 fail*/
int check(stack & s)
{
int ret=0;

if(s.data==NULL)
	{
	if(s.Allocated!=0) ret=StackId | Bad_Allocated;
	if(s.Level!=0) ret=StackId | Bad_Allocated;
	s.Level=s.Allocated=0;
	return(ret);
	}

if(s.Allocated==0) // && data!=NULL
  {
  erase(s);
  return(StackId | Bad_Allocated);
  }

if(s.Level>s.Allocated)
  {
  s.Level=s.Allocated;	// this error could be perhaps fixed
  ret = StackId|Bad_Allocated;
  }

return(ret);
}


#ifdef Streams
ostream &operator<<(ostream & xout, const stack & s)
{
//!!!! TODO
/// return xout<<"TODO");
}

/*istream &operator>>(istream &, string &)
{
} */
#endif
