/* This file is part of Cloudy and is copyright (C) 1978-2004 by Gary J. Ferland.
 * For conditions of distribution and use, see copyright notice in license.txt */
/*CrashDo any of several tests to check that the code can crash */
#include "cddefines.h"
#include "physconst.h"
#include "geometry.h"
#include "parse.h"
/* disable warning about undefined vars being used - one of the tests shall do exactly that */
#ifdef _MSC_VER
#pragma warning( disable : 4700 )
#endif
/* disable warning about division by zero */
#ifdef _MSC_VER
#pragma warning( disable : 4756 )
#endif

void CrashDo(char *chCard)
{
	float ar1;
	long int i;

	int lgCrash = FALSE;
	/* div by 0 to get crash as check on FP environment */
	if( lgMatch("ZERO",chCard) )
	{
		fprintf(ioQQQ," I will now div by 0 to get crash.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		geometry.covgeo = (float)(1. / ZeroNum );
		fprintf(ioQQQ," I am still alive - something is wrong, result is %e\n",
			geometry.covgeo);
		lgCrash = TRUE;
	}

	/* use some undefined numbers */
	else if( lgMatch("UNDE",chCard) )
	{ 
		fprintf(ioQQQ," I will now use the malloced undefined variable.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		{
			float *aa , a;
			aa = (float*)MALLOC(2*sizeof(float));
			a = aa[1] * 1e-10f;

			fprintf(ioQQQ," I am still alive - something is wrong,  the result of the mult of undef by 1e-10 is %e\n",a);
			fflush(ioQQQ);
			free( aa );
		}
		
		fprintf(ioQQQ," Now I will now use an undefined variable off the stack.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		{
			float a;
			/*lint -e530 ar1 not initialized */
			a = ar1 * 1e-10f;
			/*lint +e530 ar1 not initialized */

			fprintf(ioQQQ," I am still alive - something is wrong, the result of the mult of undef by 1e-10 is %e\n",a);
			fflush(ioQQQ);
		}
		
		lgCrash = TRUE;
	}

	/* make overflow to get crash as check on FP environment */
	else if( lgMatch("OVER",chCard) && lgMatch("LONG",chCard) )
	{ 
		long lng;
		ar1 = 1e-20f; 
		fprintf(ioQQQ," I will now make long overflow to get crash.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		lng = (long)(LONG_MAX*1000. );
		fprintf(ioQQQ," I am still alive - something is wrong, the result was %li\n",
			lng);
		lgCrash = TRUE;
	}

	/* make overflow to get crash as check on FP environment */
	else if( lgMatch("OVER",chCard) )
	{ 
		ar1 = 1e-20f; 
		fprintf(ioQQQ," I will now make float overflow to get crash.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		geometry.covgeo = (float)(DBL_MAX / ar1 );
		fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
			geometry.covgeo);
		lgCrash = TRUE;
	}

	/* assert impossible to get crash as check on environment */
	else if( lgMatch("ASSE",chCard) )
	{ 
		fprintf(ioQQQ," I will now assert that a false statement is true to get a crash.\n\n");
		fprintf(ioQQQ," The correct behavior is for the statement \"PROBLEM An assert has been thrown, this is bad\" to be printed,\n     followed by a request to show the output to Gary Ferland.\n\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n\n");
		fflush(ioQQQ);
		ASSERT( DBL_MAX <  ZerO );
		fprintf(ioQQQ," I am still alive - the assert macro is not working in this executable.\n");
		lgCrash = TRUE;
	}

	/* assert ratios of zeros (NaN) to get crash as check on environment */
	else if( lgMatch(" NAN",chCard) )
	{ 
		ar1 = 0.;
		fprintf(ioQQQ," I will now make invalid operation (div 0 by 0) to get crash.  Hold on.\n");
		fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
		fflush(ioQQQ);
		geometry.covgeo = (float)(ar1 / ZeroNum );
		fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
			geometry.covgeo);
		lgCrash = TRUE;
	}

	/* array index out of bounds, two options, low and high */
	else if( lgMatch("BOUN",chCard) )
	{
		/* must turn off pclint detection of logical errors in this block */
		/*lint -e662 out of bounds*/
		/*lint -e661 out of bounds*/
		int * ibound;
		int ilow=-2, ihigh=12;
		if( (ibound = ((int *)MALLOC( 10*sizeof(int) ))) == NULL )
			BadMalloc();
		/* do low fail first */
		if( lgMatch(" LOW", chCard ) )
		{
			fprintf(ioQQQ," I will access ibound[-2].  Hold on.\n");
			fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
			fflush(ioQQQ);
			i = ibound[ilow];
			fprintf(ioQQQ," I am still alive - something is wrong, the result was %li.\n",i);
			lgCrash = TRUE;
		}
		/* do high fail first */
		else if( lgMatch("HIGH", chCard ) )
		{
			fprintf(ioQQQ," I will access ibound[limit+3].  Hold on.\n");
			fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
			fflush(ioQQQ);
			i = ibound[ihigh];
			fprintf(ioQQQ," I am still alive - something is wrong.\n");
			lgCrash = TRUE;
		}
		else
		{
			/* not specified, do low then high */
			fprintf(ioQQQ," I will access ibound[-2].  Hold on.\n");
			fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
			fflush(ioQQQ);
			i = ibound[ilow];
			fprintf(ioQQQ," I am still alive - something is wrong.\n");
			lgCrash = TRUE;
			fprintf(ioQQQ," I will access ibound[limit+3].  Hold on.\n");
			fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
			fflush(ioQQQ);
			i = ibound[ihigh];
			fprintf(ioQQQ," I am still alive - something is wrong.\n");
			fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
			lgCrash = TRUE;
		}
		free(ibound);
		/*lint +e662 out of bounds*/
		/*lint +e661 out of bounds*/
	}

	else
	{
		fprintf(ioQQQ,
			" crash options are ZERO, UNDEfined, OVERflow, ASSErt, _NAN, and BOUNds.\n");
		lgCrash = TRUE;
	}
	if( lgCrash )
	{
		puts( "[Stop in CrashDo]" );
		cdEXIT(EXIT_FAILURE);
	}
}
/* thurn this back on */
#ifdef _MSC_VER
#pragma warning( default : 4700 )/* disable warning that conditional expression*/
#endif
