#ifndef _EIFFEL_RT_H
#define _EIFFEL_RT_H

/*************************************************************************** 
 *
 * Configuration section
 *
 ***************************************************************************/

#ifdef __linux__
extern "C" {

/* 
 * Hard code in these declarations. The correct thing to do would be to
 * include <std.h> but this file include definitions that cause other
 * problems
*/

int  open (char *, int);
int  close (int);
int  read (int, char *, int);
int  write (int, char *, int);
char *strcat (char *, char *);
void memset (char *, int, int);
}
#endif


/* 
 * Enable tracing in the runtime. If tracb.C is to be removed from the
 * runtime system, comment this out.
 * WARNING - Untested
*/
#define _ERT_TRACE		

/*
 * The depth of nested function calls
*/
#define _ERT_JMP_MAX	96

/* 
 * The runtime system supports a method of caching equal string constants 
 * together. If your application uses a lot of strings you can increase
 * this value for a better performance (but it won't make a great difference)
*/
#define MAX_CONST_STRINGS 300

/*
 * Configuration for exception handling. Determined by C++ compiler limits
*/
#define HAS_LONGJMP			/* longjmp implemented */

#if defined (__linux__)
#define sigset signal
#endif

#ifdef _DJGPP_
#define sigset signal
#endif

#ifdef _EMX_
#define sigset signal
#endif

#ifdef _TCC_
#include <stdlib.h>

#define sigset signal

#if defined (BORLAND_SIGNAL_BUG) && defined ( SIG_IGN)
#undef SIG_IGN
typedef void _Cdecl (* _CatcherPTRcpp)(int);
#define SIG_IGN ((_CatcherPTRcpp)1)   /* Ignore action    */
#endif

#endif

#ifdef _BCC_

#define sigset signal

#if defined (BORLAND_SIGNAL_BUG) && defined ( SIG_IGN)
#undef SIG_IGN
typedef void _Cdecl (* _CatcherPTRcpp)(int);
#define SIG_IGN ((_CatcherPTRcpp)1)   /* Ignore action    */
#endif

#endif

/*
 * If the preprocess is capable of coercing arguments with the `#' operator
 * set _SMART_CPP_. This passes the failing conditional of an assertion to
 * be displayed in the traceback.
*/

#if defined(__GNUC__)
#define _SMART_CPP_
#endif


/*
 * This is a bit of a problem.  We have to hard code the id's of the REF
 * classes. If these class are removed, the next time a system is built
 * they will be inserted in the wrong place (probably).
 *
*/
#define _bibt_BOOLEAN_REF_id		 9
#define _bibt_CHARACTER_REF_id	10
#define _bibt_INTEGER_REF_id		11
#define _bibt_REAL_REF_id		12
#define _bibt_DOUBLE_REF_id		13

/*************************************************************************** 
 *
 * End of configuration section. Change anything below at your peril.
 *
 ***************************************************************************/


#ifdef _SMART_CPP_

#define _eiffel_rt_Assert(TYPE,CLASS,RTN,TAG,EX,RESC) if (EX) /* TAG */ ; \
	else { _ert_raise ( TYPE, CLASS, RTN, TAG, #EX); RESC; }

#else
#define _eiffel_rt_Assert(TYPE,CLASS,RTN,TAG,EX,RESC) if (EX) /* TAG */ ; \
	else { _ert_raise ( TYPE, CLASS, RTN, TAG, 0); RESC; }
#endif

#define A_REQUIRE   0x0001         /*  'r' */	/* Copied from beth.c */
#define A_ENSURE    0x0002         /*  'e' */
#define A_INVARIANT 0x0004         /*  'i' */
#define A_LOOP      0x0008         /*  'l' */
#define A_CHECK     0x0010         /*  'c' */
#define A_ALL       0x0020         /*  'a' */
#define A_NONE      0x0040         /*  'n' */

int _set_class_assert ( int);

/*
 * These re-map the terser C++ compiler #defines into the ones used in the
 * generated code
*/

/*
 * Problem here... Must be defined unless the entire system is optimised
*/
#define EA_INVARIANT


#ifndef EON_O
#define NO_OPTIMISATION
#endif  // EON_O

#ifdef EON_T
#define EIFFEL_TRACE
#endif  // EON_T

#ifdef EON_E
#define EA_ENSURE
#endif
#ifdef EON_R
#define EA_REQUIRE
#endif
#ifdef EON_I
#define EA_INVARIANT
#endif
#ifdef EON_L
#define EA_LOOP_INVARIANT
#define EA_LOOP_VARIANT
#endif
#ifdef EON_C
#define EA_CHECK
#endif

#ifdef NEEDS_BOOL
enum bool { false=0, true=1 };
#endif

#define MAX_ROUTINE_NAME_LEN  30 /* Also in cdb/eon_tables.h - don't change */

/*
 * implementation-depeandant values:
 */
#define BYTE_SIZE	8

/*
 * aliasing for basic types (BIBT)
 */
#define CHARACTER	char
#define INTEGER 	int
#define REAL		float
#define DOUBLE  	double
#define BOOLEAN 	bool
#define BIT     	void*
#define NONE    	void*
#define POINTER	void*

#define _ert_init_CHARACTER 	0
#define _ert_init_INTEGER   	0
#define _ert_init_REAL 		0.0
#define _ert_init_DOUBLE 	0.0
#define _ert_init_BOOLEAN 	"false"
#define _ert_init_BIT 		0
#define _ert_init_POINTER 	(void*) 0

class GENERAL;
class ANY;
class STRING;
class ARRAY;
class CORE;

#define Current	this

/*
#define WRAP_MAX_ARGS	16		
typedef union { int Wi; double Wd; } _ert_Wrap;
*/

/* #define AND_THEN(e1,e2)	(e1)?(e2):0 */

#define _ert_BOOLEAN_AND_THEN(e1,e2)	((e1)&&(e2))
#define _ert_BOOLEAN_OR_ELSE(e1,e2)	((e1)?1:(e2))
#define _ert_BOOLEAN_XOR(e1,e2)	_ert_BOOLEAN_Const ( (((e1)?(!(e2)):(e2)) ? "true" : "false"))

#define _ert_BOOLEAN_IMPLIES(e1,e2)	((e1)?(e2):1)
#define _ert_INTEGER_IMPLIES(e1,e2)	(INTEGER) ((e1)?(e2):1)
#define _ert_REAL_IMPLIES(e1,e2)		(REAL)    ((e1)?(e2):1)
#define _ert_DOUBLE_IMPLIES(e1,e2)		(DOUBLE)  ((e1)?(e2):1)

#define _ert_INTEGER_IDIV(e1,e2)		((int) (e1/e2))

/*
 * Copy constructors for built-in types:
*/
#define _ert_INTEGER_Const(ip)		((INTEGER)(ip))
#define _ert_REAL_Const(rp)		((REAL)(rp))
#define _ert_DOUBLE_Const(rp)		((DOUBLE)(rp))
#define _ert_NONE_Const(vp)		((NONE)(vp))
#define _ert_POINTER_Const(ptr)		((POINTER)(ptr))
#define _ert_BOOLEAN_Const(bp)		((BOOLEAN)(bp))
#define _ert_CHARACTER_Const(cp) 	((CHARACTER)(cp))

#define _ert_INTEGER_Copy(ip)		((INTEGER)(ip))
#define _ert_REAL_Copy(rp)		((REAL)(rp))
#define _ert_DOUBLE_Copy(rp)		((DOUBLE)(rp))
#define _ert_NONE_Copy(vp)		((NONE)(vp))
#define _ert_POINTER_Copy(ptr)		((POINTER)(ptr))
#define _ert_BOOLEAN_Copy(bp)		((BOOLEAN)(bp))
#define _ert_CHARACTER_Copy(cp)		((CHARACTER)(cp))

#define _ert_INTEGER_Equal(selfp,ip)	((selfp)==(ip))
#define _ert_REAL_Equal(selfp,rp)	((selfp)==(rp))
#define _ert_DOUBLE_Equal(selfp,rp)	((selfp)==(rp))
#define _ert_NONE_Equal(selfp,vp)	((selfp)==(vp))
#define _ert_POINTER_Equal(selfp,ptr)	((selfp)==(ptr))
#define _ert_BOOLEAN_Equal(selfp,bp)	((selfp)==(bp))
#define _ert_CHARACTER_Equal(selfp,cp)	((selfp)==(cp))

extern "C" {
	int  c_open ( POINTER, INTEGER);
	void c_close ( INTEGER);
	void c_putstring ( INTEGER,POINTER);
	void c_putint ( INTEGER, INTEGER);
	void c_putreal ( INTEGER, float);
	void c_putdouble ( INTEGER, double);
	void c_putchar ( INTEGER, char);
   	INTEGER c_atoi ( POINTER);
	void c_itoa ( POINTER, INTEGER);
	void c_memcpy ( POINTER, POINTER, INTEGER);
	void c_free ( POINTER);
	int printf ( const char* ...);
	STRING* _ert_new_string(POINTER);
	void _ert_initialise( int, char*);
	void _ert_terminate ( int);
	void _ert_set_exitcode(int);
	void *_ert_wrap_expr ( int, ...);
	void _ert_array_put ( POINTER, INTEGER, ANY*);
	ARRAY* _ert_make_array ( int, ...);
	ARRAY *_ert_make_array_from_nv ( int, char**);
	ARRAY *_ert_make_array_from_v ( char *envp[]);

	POINTER _ert_object_address ( NONE);
	POINTER _ert_to_c();

	STRING* _bibt_CHARACTER_out ( CHARACTER);
	STRING* _bibt_INTEGER_out ( INTEGER);
	STRING* _bibt_BOOLEAN_out ( BOOLEAN);
	STRING* _bibt_REAL_out ( REAL);
	STRING* _bibt_DOUBLE_out ( REAL);
	STRING* _bibt_NONE_out ( NONE);
	STRING* _bibt_POINTER_out ( POINTER);

	char* _bibt_CHARACTER_save ( char *);
	char* _bibt_INTEGER_save ( int);
	char* _bibt_BOOLEAN_save ( char *);
	char* _bibt_REAL_save ( float);
	char* _bibt_DOUBLE_save ( double);
	char* _bibt_NONE_save ( void *);
	char* _bibt_POINTER_save ( char *);

	INTEGER _ert_char_size();
	INTEGER _ert_int_size();
	INTEGER _ert_real_size();
	INTEGER _ert_double_size();
	INTEGER _ert_ptr_size();
	INTEGER _ert_max_char();

	POINTER _ert_CORE_space_Copy ( CORE *);
	POINTER _ert_GENERAL_c_class_name_Copy ( GENERAL *);
	POINTER _ert_GENERAL_c_object_address_Copy ( GENERAL *);

	void _ert_longjmp();
	void _ert_raise ( int, char*, char*, char*, char*);
	BOOLEAN _ert_assertion_violation();
	void _ert_exception_init(int, char*);
	STRING *_ert_except_mesg (int);
	void *_base2obj ( ANY *, int);

	void _ert_memory_error ( char*, int);
	void _trace_write_log ( char*, char*, void *, int, 
				char*, char*, char*, char*, int, int);
	void _ert_trace_log ( char *, char *, int, int);
	void _ert_no_show_trace_on_failure(void);
	void _ert_show_trace_on_failure(void);
	int _ert_original_exception(void);
	STRING *_ert_routine_name(void);
	STRING *_ert_tag_name(void);
     STRING *_ert_void_call_target(void);
	void _ert_show_trace(void);
	void _ert_no_show_trace(void);
	void _ert_raise_developer_exception(int);

	INTEGER _ert_INTEGER_POW(double,int);
	REAL    _ert_REAL_POW(double,int);
	DOUBLE  _ert_DOUBLE_POW(double,int);
}

/*
 * Defined in C++
*/

extern int _ert_trace_depth;
extern int _ert_debug_depth;
extern int _ert_trace_mode;
extern int _ert_signaled;
extern int _ert_show_traceback;
extern int _ert_expand;
extern int _ert_exitcode;
extern int _ert_rescuing;
extern int _ert_in_assertion;
void _ert_set_trace_mode();
void _ert_set_debug_mode();


#ifdef _ERT_TRACE
#include "tracb.H"
#endif

#include <malloc.h>
#include <setjmp.h>


typedef struct {
	jmp_buf jmpenv;
	void    *caddr;
}  _ERT_ENV;

extern int _ert_depth;
extern _ERT_ENV _ert_cenv[_ERT_JMP_MAX];


/*
 * Well known exception conditions
 * These are duplicated in ec2.h
 *
 * If you add a new EXCEPT_ type change:
 * ert.C _ert_raise() if it is an assertion.
 * ert.C _ert_except_mesg()
*/

#define EXCEPT_BUILTIN			100	/* Start of Assertions */

#define EXCEPT_PRECONDITION		100
#define EXCEPT_POSTCONDITION		101
#define EXCEPT_INVARIANT    		102
#define EXCEPT_LOOP_INVARIANT		103
#define EXCEPT_LOOP_VARIANT		104
#define EXCEPT_CHECK_INSTRUCTION	105	/* These are grouped as Assertions */

#define EXCEPT_ROUTINE_FAILURE	106
#define EXCEPT_VOID_TARGET_CALL	107
#define EXCEPT_NO_MORE_MEMORY		108
#define EXCEPT_CALL_TO_DEFERRED	109
#define EXCEPT_BAD_SIGNAL		110
#define EXCEPT_NESTED_FUNCTIONS	111
#define EXCEPT_INSPECTION_VALUE    112
#define EXCEPT_ASSIGNED_TO_EXPANDED 113
#define EXCEPT_ARRAY_TYPE_ERROR    114
#define EXCEPT_RESCUE_FAILED       115
#define EXCEPT_MAX				115		/* Same as last EXCEPT_... */


#define EXCEPT_IGNORE			1
#define EXCEPT_CATCH			2
#define EXCEPT_CONTINUE			3

#define EXCEPT_DEVELOPER_1		-1
#define EXCEPT_DEVELOPER_2		-2
#define EXCEPT_DEVELOPER_3		-3
#define EXCEPT_DEVELOPER_4		-4
#define EXCEPT_DEVELOPER_5		-5

#define EXCEPT_OFFSET			5  /* the number of developer exceptions */

#define EXCEPT_RETRY			1
#define EXCEPT_FAIL				2


/*
 * Signal compatibility
 *
 * This is a messy area because MSDOS doesn't support full Unix signals
 * and different vendors have different include files.
 *
 * Here, we attempt to plug a few holes.
*/

#ifdef MSDOS

#ifdef _DJGPP_
#ifndef SIGUSR1
#define SIGUSR1	30
#define SIGUSR2	31
#endif
#endif

/*
 * A few platform dependant bits
*/

#define PATH_SEP_CHAR 	'\\'


#else /* MSDOS */

#define PATH_SEP_CHAR 	'/'

#endif /* MSDOS */

#endif /* _EIFFEL_RT_H */


