1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: exception.h 4206 2010-04-03 16:32:33Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2010 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 #define DO_GUARD		1
27 #define DO_CHECK		1
28 
29 #ifdef PARANOID
30 #define DO_GUARD_SLOW	1
31 #define DO_CHECK_SLOW	1
32 #endif
33 
34 //==========================================================================
35 //
36 //	Exceptions
37 //
38 //==========================================================================
39 
40 class VException : VInterface
41 {
42 public:
43 	virtual const char* What() const = 0;
44 };
45 
46 #define MAX_ERROR_TEXT_SIZE		1024
47 
48 class VavoomError : public VException
49 {
50 public:
51 	char message[MAX_ERROR_TEXT_SIZE];
52 
53 	explicit VavoomError(const char *text);
54 	const char* What() const;
55 };
56 
57 class RecoverableError : public VavoomError
58 {
59 public:
RecoverableError(const char * text)60 	explicit RecoverableError(const char *text) : VavoomError(text) { }
61 };
62 
63 class ZoneError : public VavoomError
64 {
65 public:
ZoneError(const char * text)66 	explicit ZoneError(const char* text) : VavoomError(text) { }
67 };
68 
69 //==========================================================================
70 //
71 //	Guard macros
72 //
73 //==========================================================================
74 
75 //	Turn on usage of context in guard macros on platforms where it's not
76 // safe to throw an exception in signal handler.
77 #if DO_GUARD && defined(__linux__)
78 #define USE_GUARD_SIGNAL_CONTEXT
79 #endif
80 
81 #ifdef USE_GUARD_SIGNAL_CONTEXT
82 #include <setjmp.h>
83 //	Stack control.
84 class __Context
85 {
86 public:
__Context()87 	__Context() { memcpy(&Last, &Env, sizeof(jmp_buf)); }
~__Context()88 	~__Context() { memcpy(&Env, &Last, sizeof(jmp_buf)); }
89 	static jmp_buf Env;
90 	static const char* ErrToThrow;
91 
92 protected:
93 	jmp_buf Last;
94 };
95 #endif
96 
97 #if defined(_DEBUG) || !DO_GUARD
98 #define guard(name)		{static const char __FUNC_NAME__[] = #name; {
99 #define unguard			}}
100 #define unguardf(msg)	}}
101 #elif defined(USE_GUARD_SIGNAL_CONTEXT)
102 #define guard(name)		{static const char __FUNC_NAME__[] = #name; \
103 	__Context __LOCAL_CONTEXT__; try { if (setjmp(__Context::Env)) { \
104 	throw VavoomError(__Context::ErrToThrow); } else {
105 #define unguard			}} catch (RecoverableError &e) { throw e; } \
106 	catch (...) { Host_CoreDump(__FUNC_NAME__); throw; }}
107 #define unguardf(msg)	}} catch (RecoverableError &e) { throw e; } \
108 	catch (...) { Host_CoreDump(__FUNC_NAME__); Host_CoreDump msg; throw; }}
109 #else
110 #define guard(name)		{static const char __FUNC_NAME__[] = #name; try {
111 #define unguard			} catch (RecoverableError &e) { throw e; } \
112 	catch (...) { Host_CoreDump(__FUNC_NAME__); throw; }}
113 #define unguardf(msg)	} catch (RecoverableError &e) { throw e; } \
114 	catch (...) { Host_CoreDump(__FUNC_NAME__); Host_CoreDump msg; throw; }}
115 #endif
116 
117 #if !defined(_DEBUG) && DO_GUARD_SLOW
118 #define guardSlow(name)		guard(name)
119 #define unguardSlow			unguard
120 #define unguardfSlow(msg)	unguardf(msg)
121 #else
122 #define guardSlow(name)		{
123 #define unguardSlow			}
124 #define unguardfSlow(msg)	}
125 #endif
126 
127 void Host_CoreDump(const char *fmt, ...);
128 void __attribute__((noreturn, format(printf, 1, 2))) __declspec(noreturn)
129 	Sys_Error(const char*, ...);
130 
131 //==========================================================================
132 //
133 //	Assertion macros
134 //
135 //==========================================================================
136 
137 #if DO_CHECK
138 #define check(e)	if (!(e)) throw VavoomError("Assertion failed: " #e)
139 #define verify(e)	if (!(e)) throw VavoomError("Assertion failed: " #e)
140 #else
141 #define check(e)
142 #define verify(e)	(e)
143 #endif
144 
145 #if DO_CHECK_SLOW
146 #define checkSlow(e)	check(e)
147 #define verifySlow(e)	verify(e)
148 #else
149 #define checkSlow(e)
150 #define verifySlow(e)	(e)
151 #endif
152