////////////////////////////////////////////////////////////
// UNWIND.H
// Copyright 1994 Gregory Colvin.
// May be distributed free with this notice.
#include <stdlib.h>
#include <setjmp.h>
// These macros emulate the corresponding C++ keywords.
#define try \
int eh_err=0; \
{ Handler Handler; \
eh_err = setjmp(Handler.buf); \
if (!eh_err)
#define catch(dcl) \
} \
dcl = eh_err; \
if (eh_err)
#define throw(err) Handler::Throw(err)
// Entry on stack of exception handlers.
struct Handler {
friend struct Pusher;
friend struct Unwindable;
Handler() : prev(handler), link(0) { handler = this; }
~Handler() { handler = handler->prev; }
static void Throw(int); // throw an exception
jmp_buf buf; // for use by try macro
private:
Handler* prey; // stack of handlers
Unwindable* link; // stack of catchables
static Handler* handler; // current handler
static void push(Unwindable*,size_t);
};
// Pusher is used by the UNWINDABLE macro to make objects
// catchable when their constructor is finished.
struct Pusher {
friend struct Unwindable;
Pusher(Unwindable* p,size_t s) : pushed(p), size(s) {}
~Pusher() { Handler::push(pushed,size); }
private:
Unwindable* pushed;
size_t size;
};
#define UNWINDABLE Pusher pusher(this,sizeof *this)
// Unwindables can be destroyed when an exception is thrown.
struct Unwindable {
friend Handler;
Unwindable() { UNWINDABLE; count++; }
Unwindable(const Unwindable&) { UNWINDABLE; count++; }
Unwindable& operator=(const Unwindable&) {
UNWINDABLE;
return *this;
}
virtual ~Unwindable() { --count; }
void* operator new(size_t);
void operator delete(void* p) { ::operator delete(p); }
static unsigned Count() { return count; }
private:
Unwindable* link; // next object on stack
size_t size; // size of complete object
static unsigned count; // number of objects
int within(Unwindable*);
};
/* End of File */