/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Debug.c.Signal
    Author:  Paul Field and Cy Booker, hacked around by Julian Smith
    Version: 0.01 (04 Jun 1995)
    Purpose: Provides a set of Debug_ functions which deal with signals
             nicely.
    Mods:    11 Sep 1995 - JS - Changed text of debug_signalnames to be same
                                as in <signal.h>.
*/

#include <signal.h>

#include "Desk.Debug.h"

#include "Desk.Event.h"	/* for event_taskname	*/
#include "Desk.Error.h"



typedef struct	{
	Desk_debug_signalhandlerfn	fn;
	void			*reference;
	}
	Desk_debug_sighandlerblock;

static Desk_debug_sighandlerblock	Desk_debug_usersighandler = { NULL, NULL};

static Desk_bool	Desk_debug_siginited = Desk_bool_FALSE;
	/* So we can check we are inited when Debug_ClaimSignal is called	*/

static const char *Desk_debug_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"
	};

#define Desk_debug_maxsignal 10



static void	Desk_Debug__SignalHandler( int sig)
{
if ( Desk_debug_usersighandler.fn)
	Desk_debug_usersighandler.fn( sig, Desk_debug_usersighandler.reference);

Desk_Error_Report( 
	0, 
	"'%s' has suffered a fatal internal error, signal %i (%s) and must exit immediately",
	Desk_Event_taskname,
	sig,
	(sig>=1 && sig<=Desk_debug_maxsignal) ? Desk_debug_signalnames[ sig] : "Illegal signal"
	);

/* Pass things on to the default handler     */
/* (gives a useful message and a stack dump) */
raise( sig);
}


	
void	Desk_Debug_InitialiseSignal( void)
{
signal( SIGABRT, &Desk_Debug__SignalHandler);
signal( SIGFPE,  &Desk_Debug__SignalHandler);
signal( SIGILL,  &Desk_Debug__SignalHandler);
signal( SIGSEGV, &Desk_Debug__SignalHandler);
signal( SIGTERM, &Desk_Debug__SignalHandler);
signal( SIGSTAK, &Desk_Debug__SignalHandler);
}



void	Desk_Debug_ClaimSignal( Desk_debug_signalhandlerfn fn, void *reference)
{
if ( !Desk_debug_siginited)	 Desk_Debug_InitialiseSignal();
Desk_debug_usersighandler.fn		= fn;
Desk_debug_usersighandler.reference	= reference;
}



void	Desk_Debug_ReleaseSignal( void)
{
Desk_debug_usersighandler.fn	= NULL;
}
