#include <mrw/exception.hpp>
#include <mrw/stacktrace.hpp>
#include <exception>
#include <iostream>

void unexpectedHandler() {
  try {
    throw;
  } catch (mrw::exception& x) {
    mrw::StackTrace::createSymtable();
    std::cerr<<"UNEXPECTED:"<<x.what()<<std::endl
             <<"---------------------------Stack:"<<std::endl
             <<x.stacktrace()
             <<"---------------------------------"<<std::endl;
  } catch (std::exception& x) {
    std::cerr<<"UNEXPECTED:"<<x.what()<<std::endl;
  } catch (...) {
    std::cerr<<"UNKNOWN UNEXPECTED"<<std::endl;
  }
  throw std::bad_exception(); // try to recover
}

void fn2() throw(std::bad_exception) {
  std::cout<<"enter fn2"<<std::endl;
  throw mrw::exception(); // that's wrong, no exception excpected
  std::cout<<"leave fn2"<<std::endl;
}

void fn1() throw(std::bad_exception) {
  std::cout<<"enter fn1"<<std::endl;
  fn2();
  std::cout<<"leave fn1"<<std::endl;
}

void fn0() throw(std::bad_exception) {
  std::cout<<"enter fn0"<<std::endl;
  try {
    fn1();
  }  catch (std::exception& x) {
    std::cerr<<"EXCEPTION caught in fn0:"<<x.what()<<std::endl;
  }
  std::cout<<"leave fn0"<<std::endl;
}

int main() {
  std::set_unexpected(&unexpectedHandler);
  try {
    std::cout<<"call fn0"<<std::endl;
    fn0();
    std::cout<<"call of fn0 successful"<<std::endl;
  } catch (...) {
    std::cerr<<"OOOPS!!!"<<std::endl;
  }
  return 0;
}