///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2003 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS C  ////
//// compiler.  This source code may only be distributed to other      ////
//// licensed users of the CCS C compiler.  No other use, reproduction ////
//// or distribution is permitted without written permission.          ////
//// Derivative programs created using this software in object code    ////
//// form are not restricted in any way.                               ////
///////////////////////////////////////////////////////////////////////////


/*********************************************************************/
#ifndef _STDLIBM
#define _STDLIBM
#USE DYNAMIC_MEMORY
/* Memory Management Functions*/
#include <stddef.h>
#if defined(__PCB__)
typedef struct nodet {
   unsigned int8 size;
   unsigned int8 next; }node_t;
#elif defined(__PCM__)
typedef struct nodet {
   unsigned int8 size;
   unsigned int16 next; }node_t;
#elif defined(__PCH__)
typedef struct nodet {
   unsigned int16 size;
   unsigned int16 next; }node_t;
#elif defined(__PCD__)
typedef struct nodet {
   unsigned int16 size;
   unsigned int16 next; }node_t;
#endif
#include <memmgmt.c>

void traverse()
{
   node_t *node,*temp;
   unsigned int16 nsize,nextsize;
   node=__DYNAMIC_HEAD;
   while(node!=NULL)
   {
     if(!bit_test(node->size,pos))// node free
      {
         nsize=node->size;
         temp=(unsigned int16)node->next;
         if(!bit_test(temp->size,pos)&& (temp==((unsigned int16)node+nsize+sizeof(node_t))))//next node free and consecutive, so combine
         {
            nextsize=temp->size;
            nsize+=nextsize+sizeof(node_t);
            remove_node(temp);
            update_node(node,nsize);
         }
         else
         node=node->next;
      }
      else
      node=node->next;
   }
}

char *malloc(size_t size)
{
   node_t *node,*new;
   unsigned int16 nsize;
   node=__DYNAMIC_HEAD;
   while(node!=NULL) // chk until end of memlist
   {
      if(!bit_test(node->size,pos) && node->size >=size) // node is free and > = req size
      {
         nsize=node->size;
         if(nsize>size +sizeof(node_t)) //node > req size, so split and add new node to memlist
         {
            new=create_node(nsize-size-sizeof(node_t),(unsigned int16)node+sizeof(node_t)+size);
            insert_node_after(node,new);
            update_node(node,size+csize);
         }
         else//not enough space for new node so use original size
         update_node(node,nsize+csize);
         //end if
         break;
      }//end if
      node=node->next;
   }//end while
   if(node==NULL)// reached end without finding an appropriate node
   {
      //prunsigned int8f("\r\n Not enough memory for allocation");
      return NULL;
   }
   else
   return (char *)node+sizeof(node_t); // return pounsigned int8er to allocated space
}

char *calloc(size_t nmemb,size_t size)
{
   node_t *node,*new;
   unsigned int16 nsize,resize;
   node=__DYNAMIC_HEAD;
   resize=nmemb*size;
   while(node!=NULL) // chk until end of memlist
   {
      if(!bit_test(node->size,pos) && node->size >=resize)// node is free and > = req size
      {
         nsize=node->size;
         if(nsize>resize+sizeof(node_t))//node > req size, so split and add new node to memlist
         {
            new=create_node(nsize-resize-sizeof(node_t),(unsigned int16)node+sizeof(node_t)+resize);
            insert_node_after(node,new);
            update_node(node,resize+csize);
         }
         else//not enough space for new node so use original size
         update_node(node,nsize+csize);
         //end if
         break;
      }//end if
      node=node->next;
   }//end while
   if(node==NULL)// reached end without finding an appropriate node
   {
      //prunsigned int8f("\r\n Not enough memory for allocation");
      return NULL;
   }
   else
   {
      memset((unsigned int16)node+sizeof(node_t),0,resize);// initialize to 0
      return (char *)(unsigned int16)node+sizeof(node_t);// return pounsigned int8er to allocated space
   }
}
void free( void * ptr)
{
   node_t *node;
   unsigned int16 nsize;

   if(ptr==NULL) // not a valid pounsigned int8er
      return;
   else
   {
      node=ptr-sizeof(node_t);
      if(bit_test(node->size,pos))// node occupied
      {
         nsize=node->size-csize;
         update_node(node,nsize);
         ptr=NULL;

      }
      else // wrong input, return
      {
         ptr=NULL;
         return;
      }
   }
   traverse();
}

char *realloc(void *ptr,size_t size)
{
   node_t *node,*new,*temp;
   unsigned int16 nsize,nextsize;

   if(ptr==NULL)// null pounsigned int8er, so malloc the req memory
      malloc(size);
   else if(size==0)
   {
   free(ptr);
   }
   else
   {
      node=ptr-sizeof(node_t);
      if(bit_test(node->size,pos))// chk if valid pounsigned int8er
      {
         nsize=node->size-csize;
         temp=(unsigned int16)node->next;
         if(nsize>size)// block > req size
         {
       
               if(!bit_test(temp->size,pos) && (temp==((unsigned int16)node+nsize+sizeof(node_t))))// next block free and consecutive
               {
                  update_node(node,size+csize); // update block
                  nextsize=temp->size;
                  remove_node(temp);
                  new=create_node(nextsize+(nsize-size),(unsigned int16)node+size+sizeof(node_t));
                  insert_node_after(node,new);
                  

               }
               else if (nsize>size +sizeof(node_t))//node > req size, so split and add new node to memlist
               {
                  update_node(node,size+csize); // update block
                  new=create_node(nsize-size-sizeof(node_t),(unsigned int16)node+sizeof(node_t)+size);
                  insert_node_after(node,new);
               }
               else//not enough space for new node so use original size
               update_node(node,nsize+csize); // update block

         }
         else // block < req size
         {
            if(!bit_test(temp->size,pos) && (temp==((unsigned int16)node+nsize+sizeof(node_t))))// next block free and consecutive
            {
               nextsize=temp->size;
               if(nextsize>=size-nsize) // next block >=difference
               {
                  if(nextsize>size-nsize+sizeof(node_t))//next node > req size, so split and add new node to memlist
                  {
                      update_node(node,size+csize);// update block
                      remove_node(temp);
                      new=create_node(nextsize-(size-nsize),(unsigned int16)node+size+sizeof(node_t));
                      insert_node_after(node,new);
                  }
                  else//not enough space for new node in next node, so use original size
                  {
                      update_node(node,nsize+nextsize+csize);// update block
                      remove_node(temp);
                  }
               }
            }
         }
         return (char *)node+sizeof(node_t); // return pounsigned int8er to the reallocated block
      }
      else // not allocated use malloc
      {
         malloc(size);
         //return;
      }
   }
 }
#ENDIF
