// cl_free_heap_object().

// General includes.
#include "cl_sysdep.h"

// Specification.
#include "cl_object.h"


// Implementation.

#include "cl_malloc.h"
#include "cl_I.h"
#include "cl_RA.h"
#include "cl_FF.h"
#include "cl_DF.h"
#include "cl_LF.h"
#include "cl_C.h"
#include "cl_string.h"

cl_heap_destructor_function cl_destructor_table [(int)cl_typetag_dynamic_end - (int)cl_typetag_dynamic_start];
AT_INITIALIZATION(ini_cl_destructor_table)
{
	var unsigned int i;
	for (i = 0; i < sizeof(cl_destructor_table)/sizeof(cl_destructor_table[0]); i++)
		if (!cl_destructor_table[i])
			cl_destructor_table[i] = (cl_heap_destructor_function)cl_abort;
}

void cl_free_heap_object (cl_heap* pointer)
{
	// This is invoked when pointer->refcount gets decremented to 0.

	// I wish it could be possible to write this in a more object oriented
	// way without completely losing efficiency.
	switch (pointer->typetag) {
	case cl_typetag_bignum:
		(*(cl_heap_bignum*)pointer).~cl_heap_bignum();
		break;
	case cl_typetag_ratio:
		(*(cl_heap_ratio*)pointer).~cl_heap_ratio();
		break;
#if !defined(CL_WIDE_POINTERS)
	case cl_typetag_ffloat:
		(*(cl_heap_ffloat*)pointer).~cl_heap_ffloat();
		break;
#endif
	case cl_typetag_dfloat:
		(*(cl_heap_dfloat*)pointer).~cl_heap_dfloat();
		break;
	case cl_typetag_lfloat:
		(*(cl_heap_lfloat*)pointer).~cl_heap_lfloat();
		break;
	case cl_typetag_complex:
		(*(cl_heap_complex*)pointer).~cl_heap_complex();
		break;
	case cl_typetag_string:
		(*(cl_heap_string*)pointer).~cl_heap_string();
		break;
	default:
	    {
		var unsigned int index = pointer->typetag - (int)cl_typetag_dynamic_start;
		if (index < (int)cl_typetag_dynamic_end - (int)cl_typetag_dynamic_start) {
			(cl_destructor_table[index])(pointer);
			break;
		}
	    }
	case cl_typetag_none:
		NOTREACHED
	}
	cl_free_hook(pointer);
}


// The best place to put the free software license is cl_free.o.

// NB about #ident: To see the strings in the .comment section of an ELF
// executable, use "strings < executable", not "strings executable".
// Better put the license into the data section: it is more portable (some
// C++ compilers may not understand #ident), is not lost in object formats
// like a.out, and is taken into account by "intelligent" strings commands.

static const char * copyright_notice[] = {
  "                                                                    ",
  "Copyright (c) Bruno Haible 1988-1997                                ",
  "                                                                     ",
  "This program is free software; you can redistribute it and/or modify",
  "it under the terms of the GNU General Public License as published by",
  "the Free Software Foundation; either version 2, or (at your option) ",
  "any later version.                                                  ",
  "                                                                      ",
  "This program is distributed in the hope that it will be useful, but ",
  "WITHOUT ANY WARRANTY; without even the implied warranty of          ",
  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   ",
  "General Public License for more details.                            ",
  "                                                                       ",
  "You should have received a copy of the GNU General Public License   ",
  "along with this program; if not, write to the Free Software         ",
  "Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.",
  "                                                                        ",
  (const char *) &copyright_notice
};
