// I nominate this to be the Spring libg++ exception handling code.
// 
// Note that it contains Sparc dependent machine code for the log.
// 
//                                                    - Graham


typedef int jmp_buf[9];

struct
ExceptionHandler
{
  ExceptionHandler *prev;
  jmp_buf handler;
  void *name;
  void *parameters;
  ExceptionHandler ();
  ExceptionHandler (int x, int y, int z);
  ~ExceptionHandler ();
};

#include <stdio.h>
#undef _X_H
#pragma implementation "x.h"
#include "/tools/cygnus/test-os/interfaces/util/x.h"

extern "C" void exit (int);

ExceptionHandler EHS (1,2,3);

ExceptionHandler::ExceptionHandler (int x, int y, int z)
{
    exceptionHandlerStack = &EHS;
    if (setjmp (EHS.handler)) {
        printf ("*** Unhandled exception ***\n");
        exit (22);
    }
}

extern "C" void __unhandled_exception (const char*, int);
extern "C" void __raise_exception (void **, void *);

// The history of raises is mainatined as acourtesy to our users.
// It is only approximately true - we don't lock on updates.
int raises_pcs[32];
void *raises_exceptions[32];
int raises_index;

void
__unhandled_exception(const char *filename, int lineno) {
	printf ("unhandled exception caught in file `%s' at line %d\n",filename, lineno);
	printf ("Recent raises : \n");
	int index = raises_index;
	for (int i = 0 ; i < 6 ; i++) {
		index = (index-1) & 31;
		if (raises_pcs[index] == 0) {
			break;
		}
		printf ("    raising pc = 0x%X, exception = 0x%X\n", raises_pcs[index], raises_exceptions[index]);
	}
	printf ("     ......\n");
	printf ("*** Unhandled exception ***\n");
    exit(22);
}


void
__raise_exception (void **addr, void *id)
{
    // Log the exception
    register int ____return_pc asm ("%i7");
    raises_pcs[raises_index] = ____return_pc;
    raises_exceptions[raises_index] = id;
    raises_index = (raises_index + 1) & 31;

    // Do the real work:
    *addr = id;
}
