#include <stdlib.h>
#include <signal.h>

#include "kernel.h"

#ifdef MemCheck_MEMCHECK
	#include "MemCheck:MemCheck.h"
#endif

#include "Desk.Error2.h"
#include "Desk.DeskMem.h"



const char *Desk_Error2_signalnames[] =
	{
	"zero signal",
	"abort", 
	"arithmetic exception",
	"illegal instruction", 
	"attention request from user",
	"bad memory access", 
	"termination request", 
	"stack overflow",
	"user1 signal",
	"user2 signal",
	"OS error signal"
	};



void	Desk_Error2_FDescribe( Desk_Error2_printf_fn fn, void* reference, const Desk_error2_block* error)
{
	if (0)	;
	
	else if ( error->type==Desk_error2_type_MISC)
		fn( reference, "Misc error 0x%p", error->data.misc);
	
	else if ( error->type==Desk_error2_type_OSERROR)	{
		if ( error->data.oserror)	{
			#ifdef MemCheck_MEMCHECK
				/*
				Turn off checking while we access the os_error - MemCheck
				will fault the access.
				 */
				MemCheck_checking	oldchecking = MemCheck_SetChecking( 0, 0);
			#endif
			fn( reference, "OS error. %i, '%s'", 
				error->data.oserror->errnum,
				error->data.oserror->errmess
				);
			#ifdef MemCheck_MEMCHECK
				MemCheck_RestoreChecking( oldchecking);
			#endif
			}
		else	fn( reference, "OS error. NULL");
		}
	
	else if ( error->type==Desk_error2_type_DESKMEM)	{
		if ( error->data.deskmem)
			fn( reference, "DeskMem error Size=%i, ptr=0x%p",
				error->data.deskmem->size,
				error->data.deskmem->ptr
				);
		else 	fn( reference, "DeskMem error");
		}
	
	else if ( error->type==Desk_error2_type_SIGNAL)	{
		
		if ( error->data.signal == SIGOSERROR)	{
			Desk_os_error*	e = (Desk_os_error*) _kernel_last_oserror();
			if (e)	{
				fn( reference, "Signal for OS error %i, '%s'", 
					e->errnum,
					e->errmess
					);
				}
			else	fn( reference, "Signal for unknown OS error");
			}
		else	fn( reference, "Signal %i: %s", error->data.signal, Desk_Error2_signalnames[ error->data.signal]);
		}
	
	else if ( error->type==Desk_error2_type_MEM)	{
		fn( reference, "Mem error %p", error->data.misc);
		}
	
	else if ( error->type==Desk_error2_type_TEXT)	{
		if ( error->data.text)	fn( reference, "%s", error->data.text);
		else			fn( reference, "");
		}
		
	else	fn( reference, "Unknown error-type %i, data %p", 
			(int) error->type, 
			error->data.misc
			);
	
	}
