#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <signal.h>
#include <sys/types.h>
#include <ucontext.h>
#include <fpu_control.h>

/*#ifdef DEBUG
#define DIE_HERE raise(SIGFPE)
#else
#define DIE_HERE
#endif*/


void sigfpe_handler(int signo, siginfo_t *si, void *data)
{
	ucontext_t *uc = (ucontext_t *) data;
	uc->uc_flags = 0;

	/*ucontext_t *uc;
	uc = (ucontext_t *) data;

	switch (signo) {
	case SIGFPE:
		fprintf(stdout, "Caught FPE\n");
		uc->uc_mcontext.gregs[REG_PC] = uc->uc_mcontext.gregs[REG_nPC];
		break;
	default:
		fprintf(stdout, "default handler\n");
	}*/
}

void no_exc()
{
	double a = 1.932847289347532947238e20;
	double b = 1.932847293472394732424e-128;

	a /= b;
	a /= b;
	a /= b;
	a /= b;
	a /= b;
	a /= b;
	a /= b;

	double zero = 0;
	a /= zero;

	printf("a=%f\n", a);


	unsigned int c = 3984794;
	c *= c;
	c *= c;
	c *= c;

	printf("c=%u\n", c);
}

int div_by_zero()
{
	/* "volatile" needed to eliminate compile-time optimizations */
	volatile unsigned long x = 42; 
	volatile unsigned long y = 0;
	x=x/y;
	return 0; /* Never reached */
}

int div_intmin_by_invone()
{
	volatile unsigned long x=INT_MIN;
	volatile unsigned long y=-1;
	x=x/y;
	return 0;
}

int main(void)
{
	//_FPU_SETCW (_FPU_DEFAULT);

	/* register SIGFPE handler */
	/*struct sigaction sa, osa;
	unsigned int b = ULONG_MAX;
	sa.sa_sigaction = sigfpe_handler;
	sigaction(SIGFPE, &sa, &osa);*/

	//no_exc();
	//div_by_zero();
	div_intmin_by_invone();

	return EXIT_SUCCESS;
}