// This may look like C code, but it is really -*- C++ -*- #ifndef EXCEPTIONS_SEEN #define EXCEPTIONS_SEEN // Gestion des exceptions, conformemnt au manuel de reference C++ // en attendant que les compilateurs le fassent tous seuls // // Eric Aubourg, la Silla fevrier 95 // Pour le moment, on ne sait gerer qu'un seul type d'exception, int. // // La syntaxe est // TRY { // .... // } // CATCH(i) { // ... // } // ENDTRY // ou bien CATCHALL a la place de CATCH. // // On peut faire THROW_ tout court, qui est pareil que THROW(0) // ou bien THROW(n) // ou bien THROW_SAME dans un bloc CATCH // IMPORTANT // Tout objet susceptible d'etre cree automatiquement au cours d'un bloc // try doit etre declare EXC_AWARE (class x EXC_AWARE {...};) ou bien // deriver d'une telle classe. // Tout constructeur d'une classe qui contient d'autres objets parmi ses // champs doit se terminer par END_CONSTRUCTOR. #include "defs.h" #include #include "peidainit.h" //#define NO_EXCEPTIONS #ifdef NO_EXCEPTIONS #define EXC_ABORT_NEG(_x) #define EXC_ABORT_ALL(_x) #define EXC_AWARE #define END_CONSTRUCTOR #define TRY if (1) { #define CATCH(_var) } else { long _var; #define CATCHALL } else { #define ENDTRY } #define THROW(_i) \ {cerr << "Throw " << _i << " file " << __FILE__ << " line " << __LINE__; \ cerr << endl; \ abort();} #define THROW_ THROW(0) #define THROW_SAME THROW(0) #define ASSERT(_a_) if (!(_a_)) { \ cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \ << endl; \ THROW_ } #define RETURN(x) return(x) #define RETURN_ return #else #ifdef COMPILER_EXCEPTIONS #define EXC_ABORT_NEG(_x) #define EXC_ABORT_ALL(_x) #define EXC_AWARE #define END_CONSTRUCTOR #define TRY try #define CATCH(_var) catch(long _var) #define CATCHALL catch(...) #define ENDTRY #define THROW(_i) throw((long) _i); #define THROW_ THROW(0) #define THROW_SAME throw; #define ASSERT(_a_) if (!(_a_)) { \ cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \ << endl; \ THROW_ } #define RETURN(x) return(x) #define RETURN_ return void InitFailNewHandler(); #else #include #include class ExcAwareObject; class ExcHndl { public: ExcHndl(ExcHndl* up); ~ExcHndl(); void SetEnv(jmp_buf& theEnv) #ifndef __GNUG__ {memcpy(env, theEnv, sizeof(jmp_buf));} #else {env = theEnv;} #endif void Throw(int exc=0, char* file=0, int line=0); void Add(ExcAwareObject*); void Forget(ExcAwareObject*); void Ignore(ExcAwareObject*); void IgnoreTab(ExcAwareObject*, size_t); void DelTab(ExcAwareObject*); void EndConstructor(void*, size_t); static void NoHandler(int exc=0, char* file=0, int line=0); ExcHndl* nextHandler; int theExc; int hadExc; private: jmp_buf env; int nObj, nObjAlloc; ExcAwareObject** objects; int nDyn, nDynAlloc; ExcAwareObject** dynObjs; int nDynTab, nDynTabAlloc; ExcAwareObject** dynTabObjs; size_t* dynTabSz; }; extern ExcHndl* topExcHndl; extern int _ExcAbortNeg; extern int _ExcAbortAll; class ExcAwareObject { friend class ExcHndl; public: ExcAwareObject() { if (topExcHndl) topExcHndl->Add(this); } virtual ~ExcAwareObject() { if (topExcHndl) topExcHndl->Forget(this); } #ifdef HAS_VEC_NEW void* operator new(size_t s) { void* p = ::operator new(s); if (topExcHndl) topExcHndl->Ignore((ExcAwareObject*)p); return p; } void* operator new(size_t /*s*/, void* p) { if (topExcHndl) topExcHndl->Ignore((ExcAwareObject*)p); return p; } void* operator new[](size_t s) { void* p = ::operator new[](s); if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s); return p; } void operator delete[](void* p) { if (topExcHndl) topExcHndl->DelTab((ExcAwareObject*)p); ::operator delete[](p); } #else void* operator new(size_t s) { void* p = ::operator new(s); if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s); return p; } void* operator new(size_t s, void* p) { if (topExcHndl) topExcHndl->IgnoreTab((ExcAwareObject*)p,s); return p; } void operator delete(void* p) { if (topExcHndl) topExcHndl->DelTab((ExcAwareObject*)p); ::operator delete(p); } #endif }; //extern "C" void terminate(); void InitFailNewHandler(); // Et maintenant les macros! // TRY cree un nouveau handler, et fait le setjmp #define _UPHANDLER \ { ExcHndl* tmp = topExcHndl->nextHandler; \ delete topExcHndl; \ topExcHndl = tmp; } #define EXC_ABORT_NEG(_x) _ExcAbortNeg = _x; #define EXC_ABORT_ALL(_x) _ExcAbortAll = _x; #define EXC_AWARE : public virtual ExcAwareObject #define END_CONSTRUCTOR \ if (topExcHndl) topExcHndl->EndConstructor(this, sizeof(*this)); #define TRY \ { topExcHndl = new ExcHndl(topExcHndl); \ jmp_buf _jmpBuffer; \ volatile int _excCaught = 0; \ if (!setjmp(_jmpBuffer)) { \ topExcHndl->SetEnv(_jmpBuffer); #define CATCH(_var) \ _UPHANDLER \ } else if (topExcHndl->hadExc) { \ int _caughtException = topExcHndl->theExc; \ int _var = _caughtException; \ _excCaught = 1; \ _UPHANDLER #define CATCHALL \ _UPHANDLER \ } else if (topExcHndl->hadExc) { \ int _caughtException = topExcHndl->theExc;\ _excCaught = _caughtException; \ _excCaught = 1; \ _UPHANDLER #define ENDTRY \ } else _UPHANDLER\ } #define THROW(_i) \ {if (!topExcHndl) ExcHndl::NoHandler(_i,__FILE__,__LINE__); \ topExcHndl->Throw(_i,__FILE__,__LINE__);} #define THROW_ THROW(0) #define THROW_SAME THROW(_caughtException) #define ASSERT(_a_) if (!(_a_)) { \ cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \ << endl; \ THROW_ } #define RETURN(x) { _UPHANDLER; return(x); } #define RETURN_ { _UPHANDLER; return; } #endif #endif #endif