Listing 2 Implementation of exception handler

////////////////////////////////////////////////////////////
// UNWIND.CPP
// Copyright 1994 Gregory Colvin.
// May be distributed free with this notice.

#include "unwind.h"

static Unwindable* Newbie;       // stack of newbies
static Handler Top;              // default handler
Handler* Handler::handler=&Top;  // current handler
unsigned Unwindable::count;      // count of objects

// Set size and push on stack of newbies.
void* Unwindable::operator new(size_t size) {
   Unwindable* p = (Unwindable*)::operator new(size);
   p->size = size;
   p->link = Newbie, Newbie = p;
   return p;
}

// True iff *this is a subobject of *w.
inline int Unwindable::within(Unwindable* w) {
   return (char*)w <= (char*)this
        && (char*)w + w->size >= (char*)this + size;
}

// If p is under construction by new then if *p is complete
// object pop it off stack of newbies, else pop subobjects
// of *p off of and push p onto stack for current handler.
void Handler::push(Unwindable* p,size_t sz) {
   p->size = sz;
   if (Newbie && p->within(Newbie)) {
      if (Newbie->size == p->size)
         Newbie = p->link;
   } else {
      for (Unwindable* stack= handler->link;
          stack && stack->within(p);
          stack = handler->link)
         handler->link = stack->link;
      p->link = handler->link, handler->link = p;
   }
}

// Pop and destroy all Unwindables on stack for current
// handler and restore context of handler.
void Handler::Throw(int err) {
   for (Unwindable* stack= handler->link;
      stack;
      stack = handler->link)
      handler->link = stack->link, stack->~Unwindable();
   if (handler!= &Top)
      longjmp(handler->buf,err);
   abort();
}

#ifdef TEST
   #include <iostream.h>

   struct Test : Unwindable {
      int n;
      Unwindable sub;
      Unwindable* psub;
      Test(int i) : n(i) {
         UNWINDABLE;
         psub = new Unwindable();
         cout << "Test" << n << " " << this << endl;
      }
      virtual ~Test() {
         cout << "~Test "<< n << " " << this << endl;
         n = 0;
         delete psub;
      }
   };

   int test(int n_try, int curt_try=0) {
      try {
         cout << "try in test" << curr_try << endl;
         Test local (curr_try);
         if (curr_try < n_try)
            return test(n_try,++curr_try);
         else {
            cout << "throw in test "<< curr_try << endl;
            throw(-1);
         }
      } catch(int x) {
         cout << "catch" << x <<" and rethrow in test"
             << curr_try << endl;
         throw(x);
      }
      return curr_try;
   }

   int main() {
      int n_test;
      cout << "enter number of test recursions: ";
      cin >> n_test;
      Test* pTest= new Test(-1);
      try {
         return test(n_test);
      } catch(int thrown) {
         cout << "catch" << thrown <<" in main" << endl;
      }
      delete pTest;
      cout << "Count" << Unwindable::Count() << endl;
      return 0;
   }
#endif

// End of File