1 | // This may look like C code, but it is really -*- C++ -*-
|
---|
2 | #ifndef EXCEPTIONS_SEEN
|
---|
3 | #define EXCEPTIONS_SEEN
|
---|
4 |
|
---|
5 | // Gestion des exceptions, conformemnt au manuel de reference C++
|
---|
6 | // en attendant que les compilateurs le fassent tous seuls
|
---|
7 | //
|
---|
8 | // Eric Aubourg, la Silla fevrier 95
|
---|
9 | // Pour le moment, on ne sait gerer qu'un seul type d'exception, int.
|
---|
10 | //
|
---|
11 | // La syntaxe est
|
---|
12 | // TRY {
|
---|
13 | // ....
|
---|
14 | // }
|
---|
15 | // CATCH(i) {
|
---|
16 | // ...
|
---|
17 | // }
|
---|
18 | // ENDTRY
|
---|
19 |
|
---|
20 | // ou bien CATCHALL a la place de CATCH.
|
---|
21 | //
|
---|
22 |
|
---|
23 | // On peut faire THROW_ tout court, qui est pareil que THROW(0)
|
---|
24 | // ou bien THROW(n)
|
---|
25 | // ou bien THROW_SAME dans un bloc CATCH
|
---|
26 |
|
---|
27 | // IMPORTANT
|
---|
28 | // Tout objet susceptible d'etre cree automatiquement au cours d'un bloc
|
---|
29 | // try doit etre declare EXC_AWARE (class x EXC_AWARE {...};) ou bien
|
---|
30 | // deriver d'une telle classe.
|
---|
31 |
|
---|
32 | // Tout constructeur d'une classe qui contient d'autres objets parmi ses
|
---|
33 | // champs doit se terminer par END_CONSTRUCTOR.
|
---|
34 |
|
---|
35 | #include "defs.h"
|
---|
36 |
|
---|
37 | #include <iostream.h>
|
---|
38 | #include "peidainit.h"
|
---|
39 |
|
---|
40 | //#define NO_EXCEPTIONS
|
---|
41 | #ifdef NO_EXCEPTIONS
|
---|
42 |
|
---|
43 | #define EXC_ABORT_NEG(_x)
|
---|
44 | #define EXC_ABORT_ALL(_x)
|
---|
45 |
|
---|
46 | #define EXC_AWARE
|
---|
47 |
|
---|
48 | #define END_CONSTRUCTOR
|
---|
49 |
|
---|
50 | #define TRY if (1) {
|
---|
51 | #define CATCH(_var) } else { long _var;
|
---|
52 | #define CATCHALL } else {
|
---|
53 | #define ENDTRY }
|
---|
54 |
|
---|
55 | #define THROW(_i) \
|
---|
56 | {cerr << "Throw " << _i << " file " << __FILE__ << " line " << __LINE__; \
|
---|
57 | cerr << endl; \
|
---|
58 | abort();}
|
---|
59 |
|
---|
60 | #define THROW_ THROW(0)
|
---|
61 |
|
---|
62 | #define THROW_SAME THROW(0)
|
---|
63 |
|
---|
64 | #define ASSERT(_a_) if (!(_a_)) { \
|
---|
65 | cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \
|
---|
66 | << endl; \
|
---|
67 | THROW_ }
|
---|
68 |
|
---|
69 | #define RETURN(x) return(x)
|
---|
70 | #define RETURN_ return
|
---|
71 |
|
---|
72 | #else
|
---|
73 | #ifdef COMPILER_EXCEPTIONS
|
---|
74 |
|
---|
75 | #define EXC_ABORT_NEG(_x)
|
---|
76 | #define EXC_ABORT_ALL(_x)
|
---|
77 |
|
---|
78 | #define EXC_AWARE
|
---|
79 |
|
---|
80 | #define END_CONSTRUCTOR
|
---|
81 |
|
---|
82 | #define TRY try
|
---|
83 | #define CATCH(_var) catch(long _var)
|
---|
84 | #define CATCHALL catch(...)
|
---|
85 | #define ENDTRY
|
---|
86 |
|
---|
87 | #define THROW(_i) throw((long) _i);
|
---|
88 |
|
---|
89 | #define THROW_ THROW(0)
|
---|
90 |
|
---|
91 | #define THROW_SAME throw;
|
---|
92 |
|
---|
93 | #define ASSERT(_a_) if (!(_a_)) { \
|
---|
94 | cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \
|
---|
95 | << endl; \
|
---|
96 | THROW_ }
|
---|
97 |
|
---|
98 | #define RETURN(x) return(x)
|
---|
99 | #define RETURN_ return
|
---|
100 |
|
---|
101 | void InitFailNewHandler();
|
---|
102 | #else
|
---|
103 |
|
---|
104 | #include <setjmp.h>
|
---|
105 | #include <stdlib.h>
|
---|
106 |
|
---|
107 | class ExcAwareObject;
|
---|
108 |
|
---|
109 | class ExcHndl {
|
---|
110 | public:
|
---|
111 | ExcHndl(ExcHndl* up);
|
---|
112 | ~ExcHndl();
|
---|
113 |
|
---|
114 | void SetEnv(jmp_buf& theEnv)
|
---|
115 | #ifndef __GNUG__
|
---|
116 | {memcpy(env, theEnv, sizeof(jmp_buf));}
|
---|
117 | #else
|
---|
118 | {env = theEnv;}
|
---|
119 | #endif
|
---|
120 | void Throw(int exc=0, char* file=0, int line=0);
|
---|
121 | void Add(ExcAwareObject*);
|
---|
122 | void Forget(ExcAwareObject*);
|
---|
123 | void Ignore(ExcAwareObject*);
|
---|
124 | void IgnoreTab(ExcAwareObject*, size_t);
|
---|
125 | void DelTab(ExcAwareObject*);
|
---|
126 | void EndConstructor(void*, size_t);
|
---|
127 | static void NoHandler(int exc=0, char* file=0, int line=0);
|
---|
128 |
|
---|
129 | ExcHndl* nextHandler;
|
---|
130 |
|
---|
131 | int theExc;
|
---|
132 | int hadExc;
|
---|
133 |
|
---|
134 | private:
|
---|
135 | jmp_buf env;
|
---|
136 | int nObj, nObjAlloc;
|
---|
137 | ExcAwareObject** objects;
|
---|
138 | int nDyn, nDynAlloc;
|
---|
139 | ExcAwareObject** dynObjs;
|
---|
140 | int nDynTab, nDynTabAlloc;
|
---|
141 | ExcAwareObject** dynTabObjs;
|
---|
142 | size_t* dynTabSz;
|
---|
143 | };
|
---|
144 |
|
---|
145 | extern ExcHndl* topExcHndl;
|
---|
146 | extern int _ExcAbortNeg;
|
---|
147 | extern int _ExcAbortAll;
|
---|
148 |
|
---|
149 | class ExcAwareObject {
|
---|
150 | friend class ExcHndl;
|
---|
151 | public:
|
---|
152 | ExcAwareObject() {
|
---|
153 | if (topExcHndl) topExcHndl->Add(this);
|
---|
154 | }
|
---|
155 |
|
---|
156 | virtual ~ExcAwareObject() {
|
---|
157 | if (topExcHndl) topExcHndl->Forget(this);
|
---|
158 | }
|
---|
159 |
|
---|
160 | #ifdef HAS_VEC_NEW
|
---|
161 | void* operator new(size_t s) {
|
---|
162 | void* p = ::operator new(s);
|
---|
163 | if (topExcHndl) topExcHndl->Ignore((ExcAwareObject*)p);
|
---|
164 | return p;
|
---|
165 | }
|
---|
166 |
|
---|
167 | void* operator new(size_t /*s*/, void* p) {
|
---|
168 | if (topExcHndl) topExcHndl->Ignore((ExcAwareObject*)p);
|
---|
169 | return p;
|
---|
170 | }
|
---|
171 |
|
---|
172 | void* operator new[](size_t s) {
|
---|
173 | void* p = ::operator new[](s);
|
---|
174 | if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s);
|
---|
175 | return p;
|
---|
176 | }
|
---|
177 |
|
---|
178 | void operator delete[](void* p) {
|
---|
179 | if (topExcHndl) topExcHndl->DelTab((ExcAwareObject*)p);
|
---|
180 | ::operator delete[](p);
|
---|
181 | }
|
---|
182 | #else
|
---|
183 | void* operator new(size_t s) {
|
---|
184 | void* p = ::operator new(s);
|
---|
185 | if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s);
|
---|
186 | return p;
|
---|
187 | }
|
---|
188 |
|
---|
189 | void* operator new(size_t s, void* p) {
|
---|
190 | if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s);
|
---|
191 | return p;
|
---|
192 | }
|
---|
193 |
|
---|
194 | void operator delete(void* p) {
|
---|
195 | if (topExcHndl) topExcHndl->DelTab((ExcAwareObject*)p);
|
---|
196 | ::operator delete(p);
|
---|
197 | }
|
---|
198 | #endif
|
---|
199 | };
|
---|
200 |
|
---|
201 | //extern "C" void terminate();
|
---|
202 |
|
---|
203 | void InitFailNewHandler();
|
---|
204 |
|
---|
205 | // Et maintenant les macros!
|
---|
206 |
|
---|
207 | // TRY cree un nouveau handler, et fait le setjmp
|
---|
208 |
|
---|
209 | #define _UPHANDLER \
|
---|
210 | { ExcHndl* tmp = topExcHndl->nextHandler; \
|
---|
211 | delete topExcHndl; \
|
---|
212 | topExcHndl = tmp; }
|
---|
213 |
|
---|
214 | #define EXC_ABORT_NEG(_x) _ExcAbortNeg = _x;
|
---|
215 | #define EXC_ABORT_ALL(_x) _ExcAbortAll = _x;
|
---|
216 |
|
---|
217 | #define EXC_AWARE : public virtual ExcAwareObject
|
---|
218 |
|
---|
219 | #define END_CONSTRUCTOR \
|
---|
220 | if (topExcHndl) topExcHndl->EndConstructor(this, sizeof(*this));
|
---|
221 |
|
---|
222 | #define TRY \
|
---|
223 | { topExcHndl = new ExcHndl(topExcHndl); \
|
---|
224 | jmp_buf _jmpBuffer; \
|
---|
225 | volatile int _excCaught = 0; \
|
---|
226 | if (!setjmp(_jmpBuffer)) { \
|
---|
227 | topExcHndl->SetEnv(_jmpBuffer);
|
---|
228 |
|
---|
229 | #define CATCH(_var) \
|
---|
230 | _UPHANDLER \
|
---|
231 | } else if (topExcHndl->hadExc) { \
|
---|
232 | int _caughtException = topExcHndl->theExc; \
|
---|
233 | int _var = _caughtException; \
|
---|
234 | _excCaught = 1; \
|
---|
235 | _UPHANDLER
|
---|
236 |
|
---|
237 | #define CATCHALL \
|
---|
238 | _UPHANDLER \
|
---|
239 | } else if (topExcHndl->hadExc) { \
|
---|
240 | int _caughtException = topExcHndl->theExc;\
|
---|
241 | _excCaught = _caughtException; \
|
---|
242 | _excCaught = 1; \
|
---|
243 | _UPHANDLER
|
---|
244 |
|
---|
245 | #define ENDTRY \
|
---|
246 | } else _UPHANDLER\
|
---|
247 | }
|
---|
248 |
|
---|
249 | #define THROW(_i) \
|
---|
250 | {if (!topExcHndl) ExcHndl::NoHandler(_i,__FILE__,__LINE__); \
|
---|
251 | topExcHndl->Throw(_i,__FILE__,__LINE__);}
|
---|
252 |
|
---|
253 | #define THROW_ THROW(0)
|
---|
254 |
|
---|
255 | #define THROW_SAME THROW(_caughtException)
|
---|
256 |
|
---|
257 | #define ASSERT(_a_) if (!(_a_)) { \
|
---|
258 | cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \
|
---|
259 | << endl; \
|
---|
260 | THROW_ }
|
---|
261 |
|
---|
262 | #define RETURN(x) { _UPHANDLER; return(x); }
|
---|
263 | #define RETURN_ { _UPHANDLER; return; }
|
---|
264 |
|
---|
265 | #endif
|
---|
266 | #endif
|
---|
267 | #endif
|
---|