/* Smartalloc.c       Copyright Clinton Staley 1991
 * modified by ceh 1992
 * converted to snew.cpp maw apr93
 */

#include <stdio.h>
#include <stdlib.h>

extern "C" {
#include "table.h"
#include "salloc.h"
}

#include "salloc++.h"

#ifdef MDEBUG
#undef new
#undef delete
#undef malloc
#undef free
#endif

#define PATTERN 0xAA

struct stack_node_t {
   char* filename;
   int linenum;
   struct stack_node_t* next;
};

char *__filename = NULL;
int __linenum = 0;

static stack_node_t *delete_stack = NULL;
static table_t inew_table = NULL;    /* Table of internal new allocations */

static void pop_delete_stack(char** file, int* line)
{
   stack_node_t *temp = delete_stack;

   if (delete_stack == NULL) {
      *file = NULL;
      return;
   }

   *file = delete_stack->filename;
   *line = delete_stack->linenum;
   
   delete_stack = delete_stack->next;
   free((char*)temp);
}

void _push_delete_stack()
{
   stack_node_t *new_node = (stack_node_t*)malloc(sizeof(stack_node_t));

   new_node->filename = __filename;
   new_node->linenum = __linenum;
   new_node->next = delete_stack;
   __filename = NULL;

   delete_stack = new_node;
}

void *operator new(size_t size)
{
   void* ptr;

   if (__filename == NULL) {
      if (inew_table == NULL)
         inew_table = create_table();
      add_item(inew_table, (long)(ptr = malloc(size)), ptr);
   }
   else {
      ptr = smartalloc(size, __filename, __linenum, PATTERN);
      __filename = NULL;
   }

   return ptr;
}

void operator delete(void* object)
{
   char* filename;
   int linenum;

	if (object == NULL) 
		return;

   if (inew_table == NULL || get_item(inew_table, (long)object) == NULL) {
      pop_delete_stack(&filename, &linenum);
      if (filename != NULL)
         smartfree(object, filename, linenum);
      else
         free((char*)object);
   }
   else {
      free((char*)object);
      destroy_item(inew_table, (long)object);
      if (num_items(inew_table) == 0) {
         destroy_table(inew_table);
         inew_table = NULL;
      }
   }
}