/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* |_o_o|\\ Copyright (c) 1989 The Software Distillery.                    *
* |. o.| ||          All Rights Reserved                                  *
* | .  | ||          Written by Doug Walker                               *
* | o  | ||          The Software Distillery                              *
* |  . |//           235 Trillingham Lane                                 *
* ======             Cary, NC 27513                                       *
*                    BBS:(919)-471-6436                                   *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "mempriv.h"

extern struct MWGlobal mwg;

void *MWAllocMem(size, flags, file, line)
long size, flags;
char *file;
long line;
{
   struct MWAlc *hd;
   char *tmpchar;
   int memtype;

   if(!(mwg.flags & MWF_ACTIVE)) return(NULL);
   if(!(mwg.flags & MWF_NOCHECK)) MWCheck();

   memtype = (flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
   if(mwg.sum[memtype] + size > mwg.lim[memtype])
   {
      /* Over the limit, fail it */
      if(mwg.dbfh)
      {
         MSG(mwg.dbfh, "MemWatch: ");
         if(memtype == MWT_CHIP)
            MSG(mwg.dbfh, "CHIP ");
         else
            MSG(mwg.dbfh, "FAST ");
         MSG(mwg.dbfh, "memory allocation exceeds MWLimit amount\n");
      }
      return(NULL);
   }

   while(!(tmpchar = (char *)AllocMem(sizeof(struct MWAlc)+size, flags)))
   {
      if(mwg.freed) MWPurge();
      else return(NULL);
   }
   
   hd = (struct MWAlc *)tmpchar;
   hd->size = size;
   hd->flags = flags;
   hd->myflags = 0L;
   hd->file = file;
   hd->line = line;
   memcpy((char *)&hd->header, MWHEADER, 4);
   tmpchar += (sizeof(struct MWAlc)+size-4);
   memcpy(tmpchar, MWTRAILER, 4);
   if(!(flags & MEMF_CLEAR) && !(mwg.flags & MWF_NOATRASH))
      memset(hd->memory, MWATRASH, size);   /* Trash the memory */

   hd->next = mwg.first;
   mwg.first = hd;

   if((mwg.sum[memtype] += size) > mwg.max[memtype]) 
      mwg.max[memtype] = mwg.sum[memtype];
   ++(mwg.num[memtype]);

   return((char *)hd->memory);
}

void MWFreeMem(mem, size, internal)
void *mem;
long size;
int internal;
{
   struct MWAlc *mwa, *prev;
   int memtype;
   int error = 0;

   if(!(mwg.flags & MWF_ACTIVE)) return;
   if(!(mwg.flags & MWF_NOCHECK)) MWCheck();

   for(prev = NULL, mwa = mwg.first; 
       mwa && mwa->memory != mem; 
       prev = mwa, mwa = mwa->next);

   if(!mwa)
   {
      if(mwg.dbfh)
         MWPrint(NULL, 1, (LONG)mem, size);
      error = 1;
   }
   else if(!internal && mwa->size != size)
   {
      if(mwg.dbfh) 
      {
         MWPrint(NULL, 2, size, 0);
         MWPrint(mwa,  0,    0, 0);
      }
      error = 1;
   }

   if(error)
   {
      MWHold();
      return;
   }

   memtype = (mwa->flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
   mwg.sum[memtype] -= mwa->size;
   --mwg.num[memtype];

   if(prev) prev->next = mwa->next;
   else     mwg.first = mwa->next;

   if(!(mwg.flags & MWF_NOFTRASH))
      memset(mwa->memory, MWFTRASH, mwa->size);  /* Trash it */

   if(mwg.flags & MWF_NOFKEEP)
     FreeMem((char *)mwa, size + sizeof(struct MWAlc));
   else
   {
      mwa->next = mwg.freed;
      mwg.freed = mwa;
   }
}