128 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| 	Trap handling
 | |
| */
 | |
| 
 | |
| /* $Header$ */
 | |
| 
 | |
| #include	<setjmp.h>
 | |
| 
 | |
| #include	<em_abs.h>
 | |
| #include	"logging.h"
 | |
| #include	"global.h"
 | |
| #include	"log.h"
 | |
| #include	"trap.h"
 | |
| #include	"warn.h"
 | |
| #include	"mem.h"
 | |
| #include	"shadow.h"
 | |
| #include	"linfil.h"
 | |
| #include	"rsb.h"
 | |
| #include	"fra.h"
 | |
| 
 | |
| extern char *sprintf();
 | |
| 
 | |
| extern jmp_buf trapbuf;			/* from main.c */
 | |
| 
 | |
| int must_test;				/* TEST-bit on in EM header word 2 */
 | |
| int signalled;
 | |
| 
 | |
| PRIVATE int nonreturnable();
 | |
| 
 | |
| PRIVATE char *trap_msg[] = {
 | |
| #include	"trap_msg"		/* generated from $(EM)/etc/traps */
 | |
| 	""
 | |
| };
 | |
| 
 | |
| char *trap2text(nr)			/* transient */
 | |
| 	int nr;
 | |
| {
 | |
| 	if (	/* trap number in predefined range */
 | |
| 		nr < sizeof (trap_msg) / sizeof (trap_msg[0])
 | |
| 	&&	/* trap message not the empty string */
 | |
| 		trap_msg[nr][0]
 | |
| 	) {
 | |
| 		return trap_msg[nr];
 | |
| 	}
 | |
| 	else {
 | |
| 		static char buf[50];
 | |
| 
 | |
| 		sprintf(buf, "TRAP %d", nr);
 | |
| 		return buf;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| do_trap(nr, L, F)
 | |
| 	int nr;
 | |
| 	int L;
 | |
| 	char *F;
 | |
| {
 | |
| 	/*
 | |
| 	1.	The trap has not been masked.
 | |
| 	2.	This routine does not return; it either ends in a call of
 | |
| 		fatal() or in a longjmp().
 | |
| 	*/
 | |
| 	static int rec_nr;		/* Recursive trap number */
 | |
| 	static int rec_trap = 0;	/* To detect traps inside do_trap() */
 | |
| 	
 | |
| 	register long tpi;		/* Trap Procedure Identifier */
 | |
| 
 | |
| 	LOG(("@t1 trap(%d) [%s: %d]", nr, F, L));
 | |
| 	warning(WMSG + nr);
 | |
| 
 | |
| 	switch (OnTrap) {
 | |
| 	case TR_ABORT:
 | |
| 		fatal("trap \"%s\" before program started", trap2text(nr));
 | |
| 		/*NOTREACHED*/
 | |
| 
 | |
| 	case TR_HALT:
 | |
| 		fatal("trap \"%s\" not caught at %s",
 | |
| 				trap2text(nr), position());
 | |
| 		/*NOTREACHED*/
 | |
| 
 | |
| 	case TR_TRAP:
 | |
| 		/* execute the trap */
 | |
| 		if (rec_trap) {
 | |
| 			fatal("recursive trap; first trap number was \"%s\"",
 | |
| 					trap2text(rec_nr));
 | |
| 		}
 | |
| 		rec_trap = 1;
 | |
| 		rec_nr = nr;
 | |
| 
 | |
| 		/* save the Function Return Area */
 | |
| 		pushFRA(FRASize);
 | |
| 		wpush((long)FRASize);
 | |
| 		wpush((long)FRA_def);
 | |
| 
 | |
| 		/* set up the trap number as the only parameter */
 | |
| 		wpush((long) nr);
 | |
| 
 | |
| 		tpi = TrapPI;		/* allowed since OnTrap == TR_TRAP */
 | |
| 		TrapPI = 0;
 | |
| 		OnTrap = TR_HALT;
 | |
| 		call(tpi, (nonreturnable(nr) ? RSB_NRT : RSB_RTT));
 | |
| 		rec_trap = 0;
 | |
| 		longjmp(trapbuf, 1);
 | |
| 		/*NOTREACHED*/
 | |
| 	}
 | |
| }
 | |
| 
 | |
| PRIVATE int nonreturnable(nr)
 | |
| 	int nr;
 | |
| {
 | |
| 	switch (nr) {
 | |
| 	case ESTACK:
 | |
| 	case EILLINS:
 | |
| 	case EODDZ:
 | |
| 	case ECASE:
 | |
| 	case EMEMFLT:
 | |
| 	case EBADPTR:
 | |
| 	case EBADPC:
 | |
| 	case EBADLAE:
 | |
| 	case EBADGTO:
 | |
| 		return 1;
 | |
| 	default:
 | |
| 		return 0;
 | |
| 	}
 | |
| 	/*NOTREACHED*/
 | |
| }
 | |
| 
 |