#include "cexn.h"
#include <stdio.h>
#include <string.h>

exn_handler(handler);

#define nostep() {printf("error, line %d\n",__LINE__); exit(2);}
#define step(x) {if (x == ++__step) printf("step n°%d\n",x); else nostep(); }

static int __step = 0;

int g(int a)
{
	return 42 + a;
}

void f(int i)
{
	try
	{
		switch(i)
		{
			case 0:
				step(3);
				throw(int,42);
			case 1:
				step(9);
				throw(float,3.14);
			case 2:
				step(14);
				throw(char,'b');
			case 3:
				step(19);
				throw(int(*)(int),g);
		}
	}
	catch(int,a)
	{
		step(4)
		printf("  42 == %d\n",a);
	}
	finally
	{
		if (i == 0)
			step(5)
		else
			step(6+i*4+(i>1)+(i>2));
	}
	rethrow;
	if (i == 0)
		step(6)
	else
		step(25);
	return;
}

int main()
{
	volatile int i;
	printf("All written steps should be in sequential order with no missing number. Every written equality should be true.\nThe test is successful if the program returns with error code 1. If the program return with any other error code (particularly 0 or 2, then something has gone wrong.");
	step(1);

	if (__check_handler_list()) nostep();
	register_handler(int,handler);
	if (__check_handler_list()) nostep();
	register_handler(char,handler);
	if (__check_handler_list()) nostep();
	register_handler(float,handler);
	if (__check_handler_list()) nostep();
	register_handler(char*,handler);
	if (__check_handler_list()) nostep();
	register_handler(double,handler);
	if (__check_handler_list()) nostep();
	register_handler(unsigned,handler);
	if (__check_handler_list()) nostep();
	register_handler(complex,handler);
	if (__check_handler_list()) nostep();
	register_handler(int,handler);
	if (__check_handler_list()) nostep();
	register_handler(char,handler);
	if (__check_handler_list()) nostep();
	register_handler(float,handler);
	if (__check_handler_list()) nostep();
	unregister_handler(char*);
	if (__check_handler_list()) nostep();
	unregister_handler(double);
	if (__check_handler_list()) nostep();
	unregister_handler(unsigned);
	if (__check_handler_list()) nostep();
	unregister_handler(complex);
	if (__check_handler_list()) nostep();

	for (i = 0; i < 5; i++)
	try
	{
		step(2+i*4 + (i>1) + 2 * (i>0) + (i>2) + (i>3));
		f(i);
	}
	with
	{
		catch(char*,a)
		{
			nostep();
			printf("  \"\" == \"%s\"\n",a);
		}
		catch(float,b)
		{
			step(11);
			printf("  3.14 == %.2f\n",b);
		}
		catch(int(*)(int),t)
		{
			step(21);
			printf("  84 == %d\n",t(42));
		}
		finally
		{
			step(7+i*5-(i>1)+(i>2)-(i>3));
		}
	} catchall;

	step(27);
	printf("We are now going to raise one last un-catched exception. This is normal behaviour for this test program.\n");
	throw(char*,"Uncatched exception !");
	nostep();
	return 0;
}

exn_handler(handler)
{
	(void)(r_fct);
	(void)(r_file);
	(void)(r_line);
	(void)(c_fct);
	(void)(c_file);
	(void)(c_line);
	step(17);
	printf("  <char> == <%s>\n",type);
	printf("  'b' == '%c'\n",*(char*)exn);
}
