// Author:  Based on X-Midas 4.4.5 hostmainroutine.cc,v 1.3 2005/01/10 21:20:28 rawson
// Author:  Neon Ngo for C++ Primitive support in NeXtMidas XBC
// Version: $Id: hostmainroutine.cc,v 1.1 2009/08/11 01:51:46 ntn Exp $
//
// When we are built as an EXE, the X-Midas main() that we link
// against is written in C.  When we are linked in as a DLL, the
// X-Midas library routine that loads us is written in FORTRAN.
// Neither of these languages can catch exceptions thrown by a C++
// primitive and handle them in an X-Midas graceful manner
// (i.e. calling M$ERROR() rather than raising a signal).
//
// Rather than requiring every C++ primitive to have a try-catch block
// around the code in their mainroutine() method, we provide the
// wrapper method below that does it for them; i.e. we are adding C++
// primitive specific startup and run-down code.
//
// On UNIX the library routine that loads DLL primitives and the
// main() in hostlaunchc.o both call a method named mainroutine_()
// (this has to do with how UNIX FORTRAN compilers generate symbols
// for FORTRAN routines); on all other platforms they call a method
// named mainroutine().  Below we use one of these two names for the
// wrapper, and the other for the method in the primitive writer's
// code.  When debugging on any platform this allows a break-point to
// be set in mainroutine(), stopping in the primitive writer's
// mainroutine() on UNIX, and in the try-catch wrapper routine below
// for all others.  On non-UNIX platforms, a #define in primitive.h
// changes the name of the mainroutine() in the primitive writer's
// code to mainroutine_().
//
// Note: in non-C++ primitives on UNIX, a mainroutine symbol will not
// exist at all because it is by necessity changed to mainroutine_ at
// compile time. This is often confusing when debugging and is why we
// took the approach below for C++ primitives.

#include <exception>
#include <iostream>

#include <string>
using namespace std;
#include <midaslib.h>

extern void mainroutine ();   // defined in every C++ Primitive (name will be mangled by C++ compiler)
extern "C" void m_checkin (); // defined in xmlibc.c - "C" callable

extern "C" {

  void mainroutine_ ()
  {
    try {
      m_checkin();
      mainroutine();
    } catch (const std::exception& e) {
      m_error(e.what());
    } catch (...) {
      m_error("Unknown exception caught...");
    }
    cout << flush;
  }

}
